From: Rudolf Polzer Date: Mon, 9 Jan 2012 20:54:32 +0000 (+0100) Subject: Merge remote-tracking branch 'origin/divVerent/allow-override-item-model' X-Git-Tag: xonotic-v0.6.0~188^2~3 X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=commitdiff_plain;h=a7b24450e4c7ca75636df1375d01d2266bd00c8c;hp=2853aa9315226a1e8816ed8b792525d7e3420bc6 Merge remote-tracking branch 'origin/divVerent/allow-override-item-model' Conflicts: qcsrc/server/t_items.qc --- diff --git a/.gitattributes b/.gitattributes index ec3bfe3d10..bf8bf30216 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,4 @@ * -crlf - *.0 -diff -crlf *.1 crlf=input *.3 crlf=input @@ -27,7 +26,7 @@ branch-manager crlf=input BSDmakefile crlf=input bsp2ent crlf=input *.bsp -diff -crlf -*.cache -diff -crlf +*.cache crlf=input *.cbp -crlf *.cbp -diff -crlf *.c crlf=input @@ -44,15 +43,20 @@ COPYING crlf=input *.cpp crlf=input create crlf=input *.cron crlf=input +crypto-keygen-standalone -diff -crlf *.css crlf=input *.cvswrappers crlf=input +*.d0ir crlf=input *.d0pk -diff -crlf -*.db -diff -crlf +*.db crlf=input +*.db.* crlf=input +*.def2ent crlf=input *.default crlf=input *.def crlf=input *.dem -diff -crlf *.dev -crlf dir -diff -crlf +*.directory crlf=input djpeg -diff -crlf *.dll -diff -crlf DOCS -diff -crlf @@ -68,9 +72,13 @@ Doxyfile crlf=input *.dylib -diff -crlf empty -diff -crlf *.EncoderPlugin crlf=input +*.ent crlf=input +etc_svc_git-daemon_run crlf=input *.flac -diff -crlf +*.flp -diff -crlf *.form crlf=input *.framegroups crlf=input +*.fteqccfail -diff -crlf *.game crlf=input *.gdb crlf=input gendox crlf=input @@ -92,10 +100,13 @@ git-svn-update crlf=input git-update-octopus crlf=input *.glp crlf=input *.glsl crlf=input +GPL-2 crlf=input +GPL-3 crlf=input GPL crlf=input *.hardwired crlf=input *.h crlf=input *.hs crlf=input +*.htaccess crlf=input *.html crlf=input *.html-part crlf=input *.icns -diff -crlf @@ -108,7 +119,7 @@ GPL crlf=input *.info-2 -diff -crlf *.info -diff -crlf *.inl crlf=input -*.instantaction crlf=input +*.iOS crlf=input *.iqm -diff -crlf *.java crlf=input *.jhm crlf=input @@ -140,25 +151,31 @@ makespr32 crlf=input *.mkdir -diff -crlf *.mmpz -diff -crlf *.modules crlf=input +*.mp3 -diff -crlf *.nib -crlf *.obj -crlf OFFSETS -diff -crlf *.ogg -diff -crlf *.options crlf=input +*.otf -diff -crlf pangorc crlf=input +*.part crlf=input *.patch crlf=input *.patchsets crlf=input +*.pbxproj crlf=input *.pc crlf=input -*.pcx -diff -crlf *.pfb -diff -crlf *.pfm -diff -crlf +*.php crlf=input *.pk3 -diff -crlf PkgInfo crlf=input *.pl crlf=input *.plist crlf=input *.pm crlf=input *.png -diff -crlf +*.po crlf=input POSITIONS -diff -crlf +*.pot crlf=input *.proj -crlf *.properties crlf=input *.psd -diff -crlf @@ -167,17 +184,19 @@ POSITIONS -diff -crlf *.qc crlf=input *.qdt crlf=input *.qh crlf=input +*.rar -diff -crlf *.rb crlf=input *.rc2 crlf=input *.rc -crlf rdjpgcom -diff -crlf *.readme crlf=input README crlf=input -*.rtlights -diff -crlf +*.rtlights crlf=input SCHEMA crlf=input *.scm crlf=input sdl-config crlf=input SDL -diff -crlf +*.sfd -diff -crlf *.shader crlf=input *.sh crlf=input *.skin crlf=input @@ -196,15 +215,16 @@ TMAP -diff -crlf todo crlf=input TODO crlf=input *.ttf -diff -crlf -*.TTF -diff -crlf *.txt crlf=input +*.txt.* crlf=input update-shaderlists crlf=input *.vbs -crlf *.vcproj -crlf +*.vcxproj crlf=input versionbuilder crlf=input +*.vhost crlf=input *.wav -diff -crlf -*.waypoints -diff -crlf -w crlf=input +*.waypoints crlf=input *.width crlf=input *.workspace -crlf wrjpgcom -diff -crlf @@ -214,9 +234,9 @@ wrjpgcom -diff -crlf xonotic-map-compiler-autobuild crlf=input xonotic-map-compiler crlf=input xonotic-map-screenshot crlf=input -xonotic-osx-agl crlf=input xonotic-osx-sdl crlf=input *.xpm crlf=input +*.xrns -diff -crlf *.zip -diff -crlf zipdiff crlf=input *.zym -diff -crlf diff --git a/.gitignore b/.gitignore index c3e14d318e..77433f6374 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ progs.dat qcsrc/client/fteqcc.log qcsrc/menu/fteqcc.log qcsrc/server/fteqcc.log +weapons.qc.tmp diff --git a/Makefile b/Makefile index caab47a809..6d0e9a617f 100644 --- a/Makefile +++ b/Makefile @@ -1,61 +1,33 @@ SCM := $(shell if [ -d .svn ]; then echo svn; elif [ -d ../.git ]; then echo git; fi) -FTEQCC ?= fteqcc PERL ?= perl ZIP ?= 7za a -tzip -mx=9 ZIPEXCLUDE ?= -x\!*.pk3 -xr\!\.svn -x\!qcsrc DIFF ?= diff -FTEQCCFLAGS_WATERMARK ?= -DWATERMARK='"^1$(shell git describe) TEST BUILD"' -DCVAR_POPCON -FTEQCCFLAGS ?= -Werror -Wno-Q302 -O3 -Ono-c -Ono-cs $(FTEQCCFLAGS_EXTRA) $(FTEQCCFLAGS_WATERMARK) -FTEQCCFLAGS_PROGS ?= -FTEQCCFLAGS_MENU ?= - # NOTE: use -DUSE_FTE instead of -TFTE here! # It will automagically add an engine check with -TID and then change back to -TFTE FTEQCCFLAGS_CSPROGS ?= -# xonotic build system overrides this by command line argument to turn off the update-cvarcount step +# xonotic build system overrides this by command line argument to turn off the check-cvars step XON_BUILDSYSTEM = all: qc -.PHONY: update-cvarcount -update-cvarcount: +.PHONY: check-cvars +check-cvars: [ "$(XON_BUILDSYSTEM)" = "" ] || [ "$(XON_BUILDSYSTEM)" = "1" ] - [ "$(XON_BUILDSYSTEM)" = "1" ] || { DO_NOT_RUN_MAKE=1 sh update-cvarcount.sh; } + [ "$(XON_BUILDSYSTEM)" = "1" ] || { DO_NOT_RUN_MAKE=1 sh check-cvars.sh; } .PHONY: qc -qc: update-cvarcount - $(MAKE) qc-recursive - -.PHONY: qc-recursive -qc-recursive: menu.dat progs.dat csprogs.dat +qc: check-cvars + $(MAKE) -C qcsrc .PHONY: skin skin: gfx/menu/default/skinvalues.txt .PHONY: clean clean: - rm -f progs.dat menu.dat csprogs.dat - -FILES_CSPROGS = $(shell find qcsrc/client qcsrc/common qcsrc/warpzonelib -type f -not -name fteqcc.log -not -name qc.asm) qcsrc/server/w_*.qc -csprogs.dat: $(FILES_CSPROGS) - @echo make[1]: Entering directory \`$(PWD)/qcsrc/client\' - cd qcsrc/client && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_CSPROGS) - -FILES_PROGS = $(shell find qcsrc/server qcsrc/common qcsrc/warpzonelib -type f -not -name fteqcc.log -not -name qc.asm) qcsrc/server/w_*.qc -progs.dat: $(FILES_PROGS) - @echo make[1]: Entering directory \`$(PWD)/qcsrc/server\' - cd qcsrc/server && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_PROGS) - -FILES_MENU = $(shell find qcsrc/menu qcsrc/common qcsrc/warpzonelib -type f -not -name fteqcc.log -not -name qc.asm) qcsrc/server/w_*.qc -menu.dat: $(FILES_MENU) - @echo make[1]: Entering directory \`$(PWD)/qcsrc/menu\' - cd qcsrc/menu && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_MENU) + $(MAKE) -C qcsrc clean gfx/menu/default/skinvalues.txt: qcsrc/menu/skin-customizables.inc $(PERL) qcsrc/menu/skin-customizables.inc > gfx/menu/default/skinvalues.txt - -.PHONY: testcase -testcase: - cd qcsrc/testcase && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_CSPROGS) -DTESTCASE="$$TESTCASE" diff --git a/_hud_common.cfg b/_hud_common.cfg new file mode 100644 index 0000000000..c46bbee713 --- /dev/null +++ b/_hud_common.cfg @@ -0,0 +1,92 @@ +// hud variables +set _hud_configure 0 "1 = configure the HUD" +seta hud_configure_teamcolorforced 0 "1 = force display of team colors in configure mode" +seta hud_configure_checkcollisions 1 "check for collisions against other panels when in hud configure mode" +seta hud_configure_bg_minalpha 0.25 "minimum panel background alpha when in hud configure mode" +seta hud_configure_grid_alpha 0.15 "alpha for visible grid when in configure mode" + +seta hud_fontsize 11 "text fontsize for the hud" +seta hud_width 560 "2D virtual width for the hud" + +// general hud panel cvars (i.e. shouldn't be adjusted by a skin config) +seta hud_panel_weapons_ammo_full_shells 60 "show 100% of the status bar at this ammo count" +seta hud_panel_weapons_ammo_full_nails 320 "show 100% of the status bar at this ammo count" +seta hud_panel_weapons_ammo_full_cells 180 "show 100% of the status bar at this ammo count" +seta hud_panel_weapons_ammo_full_rockets 160 "show 100% of the status bar at this ammo count" +seta hud_panel_weapons_ammo_full_fuel 100 "show 100% of the status bar at this ammo count" + +seta hud_panel_ammo_maxammo "40" "when you have this much ammo, the ammo status bar is full" + +seta hud_panel_healtharmor_maxhealth "200" "when you have this much health, the health status bar is full" +seta hud_panel_healtharmor_maxarmor "200" "when you have this much armor, the armor status bar is full" +seta hud_panel_healtharmor_progressbar_gfx_damage 5 "show damage effect when damaged at least by this amount; 0 disables the effect" +seta hud_panel_healtharmor_progressbar_gfx_lowhealth 40 "health progressbar blinks when health is lower than this amount" + +seta hud_panel_engineinfo_framecounter_exponentialmovingaverage 1 "use an averaging method for calculating fps instead of counting frametime like engine does" +seta hud_panel_engineinfo_framecounter_exponentialmovingaverage_new_weight 0.1 "weight of latest data point" +seta hud_panel_engineinfo_framecounter_exponentialmovingaverage_instantupdate_change_threshold 0.5 "threshold for fps change when to update instantly, to make big fps changes update faster" + +// hud panel aliases +alias hud_panel_radar_rotate "toggle hud_panel_radar_rotation 0 1 2 3 4" +alias +hud_panel_radar_maximized "cl_cmd hud_panel_radar_maximized 1" +alias -hud_panel_radar_maximized "cl_cmd hud_panel_radar_maximized 0" +alias hud_panel_radar_maximized "cl_cmd hud_panel_radar_maximized" + +// other hud cvars +seta hud_showbinds 1 "what to show in the HUD to indicate certain keys to press: 0 display commands, 1 bound keys, 2 both" +seta hud_showbinds_limit 2 "maximum number of bound keys to show for a command. 0 for unlimited" + +seta hud_colorflash_alpha 0.5 "starting alpha of the color flash" + +seta hud_damage 0.55 "an improved version of gl_polyblend for damage, draw an image instead when hurt" +seta hud_damage_blur 10 "Use postprocessing to blur the screen when you have taken damage. This can be paired with current hud damage or just used alone. Higher values = more blur" +seta hud_damage_blur_alpha 0.5 "Amount of alpha to use when merging the blurred layers back into the render. Turning this up higher will remove bloom, so it's best to find a balance" +seta hud_damage_gentle_alpha_multiplier 0.10 "how much to multiply alpha of flash when using the cl_gentle version, it's much more opaque than the non-gentle version" +seta hud_damage_gentle_color "1 0.7 1" "color of flash for cl_gentle version" +seta hud_damage_color "1 0 0" "color of flash" +seta hud_damage_factor 0.025 "(damage * factor) = how much to add to the alpha value" +seta hud_damage_fade_rate 0.75 "how much to subtract from the alpha value each second" +seta hud_damage_maxalpha 1.5 "how much to limit the alpha value to" +seta hud_damage_pain_threshold 0.1 "how much alpha to ignore (must be bigger than the hud_damage_factor so that e.g. rot is ignored)" +seta hud_damage_pain_threshold_lower 1.25 "how much we lower pain_threshold with when nearing 0 health (if pain_threshold gets negative then we always draw a flash at alpha = fabs(pain_threshold)" +seta hud_damage_pain_threshold_lower_health 50 "at which health we start lowering pain_threshold" +seta hud_damage_pain_threshold_pulsating_min 0.6 "minimum value when calculating the pulse: max(pulsating_min, fabs(sin(PI * time / period))" +seta hud_damage_pain_threshold_pulsating_period 0.8 "one pulse every X seconds" + +seta hud_powerup 0 "power of the sharpen effect when owning the shield or strength powerups, default is 0.5" + +seta hud_postprocessing 1 "enables the ability for effects such as hud_damage_blur and hud_contents to apply a postprocessing method upon the screen - enabling this disables manual editing of the postprocess cvars" +seta hud_postprocessing_maxbluralpha 0 "maximum alpha which the blur postprocess can be, default is 0.5" +seta hud_postprocessing_maxblurradius 8 "maximum radius which the blur postprocess can be, default is 8" + +seta hud_contents 1 "an improved version of gl_polyblend for liquids such as water/lava/slime, draw a filler when inside the liquid" +seta hud_contents_blur 10 "Use postprocessing to blur the screen when you are inside a liquid. Higher values = more blur" +seta hud_contents_blur_alpha 0.5 "Amount of alpha to use when merging the blurred layers back into the render. Turning this up higher will remove bloom, so it's best to find a balance" +seta hud_contents_factor 1 "factor at which to multiply the current faded value." +seta hud_contents_fadeintime 0.02 "factor of time it takes for the alpha level to reach normal value when entering the liquid" +seta hud_contents_fadeouttime 0.1 "factor of time it takes for the alpha level to reach normal value when leaving the liquid" +seta hud_contents_lava_alpha 0.7 "alpha of the lava" +seta hud_contents_lava_color "0.8 0.1 0" "color blend when inside lava" +seta hud_contents_slime_alpha 0.7 "alpha of the slime" +seta hud_contents_slime_color "0 0.4 0.1" "color blend when inside slime" +seta hud_contents_water_alpha 0.5 "alpha of the water" +seta hud_contents_water_color "0.4 0.3 0.3" "color blend when inside water" + +seta hud_shownames 1 "draw names and health/armor of nearby players" +seta hud_shownames_enemies 1 "show tags for enemies as well" +seta hud_shownames_crosshairdistance 0 "if set, only draw tags which came within this distance of your crosshair (25 recommended)" +seta hud_shownames_crosshairdistance_time 5 "how many seconds the tag is still visible after pointing at them" +seta hud_shownames_crosshairdistance_antioverlap 0 "allow antioverlap to work as normal even with crosshairdistance on" +seta hud_shownames_self 0 "also include your own name to be shown when third person camera mode is on (chase_active/cl_eventchase)" +seta hud_shownames_status 1 "1 = draw health/armor status of teammates" +seta hud_shownames_statusbar_height 4 "height of status bar" +seta hud_shownames_aspect 8 "aspect ratio of total drawing area per name" +seta hud_shownames_fontsize 12 "font size" +seta hud_shownames_decolorize 1 "1 = decolorize name in team games, 2 = decolorize always" +seta hud_shownames_alpha 0.7 "alpha" +seta hud_shownames_resize 1 "enable resizing of the names, then the size cvars will correspond to the maximum size" +seta hud_shownames_mindistance 1000 "start fading alpha/size at this distance" +seta hud_shownames_maxdistance 5000 "alpha/size is 0 at this distance" +seta hud_shownames_antioverlap 1 "if two tags get too close to each other, fade out the one further away from you" +seta hud_shownames_antioverlap_distance 50 "2d distance to other tag after which to fade out" +seta hud_shownames_offset 52 "offset (along z-axis) tag from player origin by this many units" \ No newline at end of file diff --git a/_hud_descriptions.cfg b/_hud_descriptions.cfg index 269b07c526..109d410e80 100644 --- a/_hud_descriptions.cfg +++ b/_hud_descriptions.cfg @@ -21,6 +21,9 @@ seta hud_progressbar_health_color "" "R G B vector of the progress bar backgroun 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_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" +seta hud_progressbar_acceleration_neg_color "" "R G B vector of the progress bar background color" seta _hud_panelorder "" "contains order in which panels are to be drawn" @@ -28,8 +31,6 @@ seta hud_configure_grid "" "snap to grid when moving/resizing panels" seta hud_configure_grid_xsize "" "snap to X * vid_conwidth" seta hud_configure_grid_ysize "" "snap to Y * vid_conheight" -seta scr_centerpos "" "Y position of the centerprint" - seta hud_panel_weapons "" "enable/disable this panel" seta hud_panel_weapons_pos "" "position of this panel" seta hud_panel_weapons_size "" "size of this panel" @@ -41,6 +42,8 @@ seta hud_panel_weapons_bg_border "" "if set to something else than \"\" = overri seta hud_panel_weapons_bg_padding "" "if set to something else than \"\" = override default padding of contents from border" seta hud_panel_weapons_aspect "" "use this aspect on the items" seta hud_panel_weapons_complainbubble "" "complain bubble (out of ammo, weapon not available etc)" +seta hud_panel_weapons_complainbubble_time "" "time that a new entry stays until it fades out" +seta hud_panel_weapons_complainbubble_fadetime "" "fade out time" seta hud_panel_weapons_complainbubble_padding "" "padding for the complainbubble" seta hud_panel_weapons_complainbubble_color_outofammo "" "color of the complainbubble when showing out of ammo message" seta hud_panel_weapons_complainbubble_color_donthave "" "color of the complainbubble when showing don't have weapon message" @@ -49,6 +52,10 @@ seta hud_panel_weapons_ammo_color "" "color of status bar" seta hud_panel_weapons_ammo_alpha "" "alpha of status bar" seta hud_panel_weapons_timeout "" "panel disappears if you don't switch weapon for this amount of seconds" seta hud_panel_weapons_timeout_effect "" "disappearance effect: 0) no effect; 1) panel moves out of screen; 2) panel fades out" +seta hud_panel_weapons_label "" "1 = show number of weapon, 2 = show bound key of weapon" +seta hud_panel_weapons_accuracy "" "show accuracy color as the weapon icon background; colors can be configured with accuracy_color* cvars" +seta hud_panel_weapons_ammo "" "show ammo as a status bar" +seta hud_panel_weapons_onlyowned "" "show only owned weapons" seta hud_panel_ammo "" "enable/disable this panel" seta hud_panel_ammo_pos "" "position of this panel" @@ -70,8 +77,8 @@ seta hud_panel_powerups "" "enable/disable this panel" seta hud_panel_powerups_pos "" "position of this panel" seta hud_panel_powerups_size "" "size of this panel" seta hud_panel_powerups_flip "" "flip strength/shield positions" -seta hud_panel_powerups_baralign "" "0 = align bars to the left, 1 = align bars to the right, 2 = align right bar to the right, 3 = align left bar to the right" -seta hud_panel_powerups_iconalign "" "0 = align icons to the left, 1 = align icons to the right, 2 = align right icon to the right, 3 = align left icon to the right" +seta hud_panel_powerups_baralign "" "0 = align bars to the left, 1 = align bars to the right, 2 = align only left bar to the right, 3 = align only right bar to the right" +seta hud_panel_powerups_iconalign "" "0 = align icons to the left, 1 = align icons to the right, 2 = align only left icon to the right, 3 = align only right icon to the right" seta hud_panel_powerups_bg "" "if set to something else than \"\" = override default background" seta hud_panel_powerups_bg_color "" "if set to something else than \"\" = override default panel background color" seta hud_panel_powerups_bg_color_team "" "override panel color with team color in team based games" @@ -87,18 +94,20 @@ seta hud_panel_healtharmor "" "enable/disable this panel, 2 = combined health/ar seta hud_panel_healtharmor_pos "" "position of this panel" seta hud_panel_healtharmor_size "" "size of this panel" seta hud_panel_healtharmor_flip "" "flip health/armor positions" -seta hud_panel_healtharmor_baralign "" "0 = align bars to the left, 1 = align bars to the right, 2 = align right bar to the right, 3 = align left bar to the right" -seta hud_panel_healtharmor_iconalign "" "0 = align icons to the left, 1 = align icons to the right, 2 = align right icon to the right, 3 = align left icon to the right" +seta hud_panel_healtharmor_baralign "" "0 = align bars to the left, 1 = align bars to the right, 2 = align only left bar to the right, 3 = align only right bar to the right" +seta hud_panel_healtharmor_iconalign "" "0 = align icons to the left, 1 = align icons to the right, 2 = align only left icon to the right, 3 = align only right icon to the right" seta hud_panel_healtharmor_bg "" "if set to something else than \"\" = override default background" seta hud_panel_healtharmor_bg_color "" "if set to something else than \"\" = override default panel background color" seta hud_panel_healtharmor_bg_color_team "" "override panel color with team color in team based games" seta hud_panel_healtharmor_bg_alpha "" "if set to something else than \"\" = override default panel background alpha" seta hud_panel_healtharmor_bg_border "" "if set to something else than \"\" = override default size of border around the background" seta hud_panel_healtharmor_bg_padding "" "if set to something else than \"\" = override default padding of contents from border" +seta hud_panel_healtharmor_text "" "show text/icons in the healtharmor panel" seta hud_panel_healtharmor_progressbar "" "enable progressbar in panel" seta hud_panel_healtharmor_progressbar_health "" "progressbar image for health" seta hud_panel_healtharmor_progressbar_armor "" "progressbar image for armor" -seta hud_panel_healtharmor_text "" "show text/icons in the healtharmor panel" +seta hud_panel_healtharmor_progressbar_gfx "" "enable graphic effects on the progressbars" +seta hud_panel_healtharmor_progressbar_gfx_smooth "" "smooth changes of the progressbar when health/armor change at least by this amount; 0 disables the effect" seta hud_panel_notify "" "enable/disable this panel" seta hud_panel_notify_pos "" "position of this base of the panel" @@ -110,7 +119,10 @@ seta hud_panel_notify_bg_alpha "" "if set to something else than \"\" = override seta hud_panel_notify_bg_border "" "if set to something else than \"\" = override default size of border around the background" seta hud_panel_notify_bg_padding "" "if set to something else than \"\" = override default padding of contents from border" seta hud_panel_notify_flip "" "order the list top to bottom instead of bottom to top" +seta hud_panel_notify_fontsize "" "multiplier for the font size used for player names in the panel" seta hud_panel_notify_print "" "also con_notify print the messages that are shown on the notify panel" +seta hud_panel_notify_fadetime "" "fade out time" +seta hud_panel_notify_time "" "time that a new entry stays until it fades out" seta hud_panel_timer "" "enable/disable this panel" seta hud_panel_timer_pos "" "position of this base of the panel" @@ -121,6 +133,7 @@ seta hud_panel_timer_bg_color_team "" "override panel color with team color in t seta hud_panel_timer_bg_alpha "" "if set to something else than \"\" = override default panel background alpha" seta hud_panel_timer_bg_border "" "if set to something else than \"\" = override default size of border around the background" seta hud_panel_timer_bg_padding "" "if set to something else than \"\" = override default padding of contents from border" +seta hud_panel_timer_increment "" "show elapsed time instead of remaining time" seta hud_panel_radar "" "enable/disable this panel, 2 = also enable in non-teambased gamemodes" seta hud_panel_radar_pos "" "position of this base of the panel" @@ -132,6 +145,11 @@ seta hud_panel_radar_bg_alpha "" "if set to something else than \"\" = override seta hud_panel_radar_bg_border "" "if set to something else than \"\" = override default size of border around the background" seta hud_panel_radar_bg_padding "" "if set to something else than \"\" = override default padding of contents from border" seta hud_panel_radar_foreground_alpha "" "alpha of the map" +seta hud_panel_radar_rotation "" "rotation mode: you set what points up. 0 = player, 1 = west, 2 = south, 3 = east, 4 = north" +seta hud_panel_radar_zoommode "" "zoom mode: 0 = zoomed by default, 1 = zoomed when +zoom, 2 = always zoomed, 3 = always zoomed out" +seta hud_panel_radar_scale "" "distance you can see on the team radar" +seta hud_panel_radar_maximized_scale "" "distance you can see on the radar when maximized" +seta hud_panel_radar_maximized_size "" "size of the radar when maximized" seta hud_panel_score "" "enable/disable this panel" seta hud_panel_score_pos "" "position of this base of the panel" @@ -142,6 +160,7 @@ seta hud_panel_score_bg_color_team "" "override panel color with team color in t seta hud_panel_score_bg_alpha "" "if set to something else than \"\" = override default panel background alpha" seta hud_panel_score_bg_border "" "if set to something else than \"\" = override default size of border around the background" seta hud_panel_score_bg_padding "" "if set to something else than \"\" = override default padding of contents from border" +seta hud_panel_score_rankings "" "show rankings: 1 always show my own score; 2 pure rankings" seta hud_panel_racetimer "" "enable/disable this panel" seta hud_panel_racetimer_pos "" "position of this base of the panel" @@ -173,6 +192,7 @@ seta hud_panel_modicons_bg_color_team "" "override panel color with team color i seta hud_panel_modicons_bg_alpha "" "if set to something else than \"\" = override default panel background alpha" seta hud_panel_modicons_bg_border "" "if set to something else than \"\" = override default size of border around the background" seta hud_panel_modicons_bg_padding "" "if set to something else than \"\" = override default padding of contents from border" +seta hud_panel_modicons_dom_layout "" "3 possible layouts: 0) only icons; 1) icons and percentage of average pps (points per second); 2) icons and average pps" seta hud_panel_pressedkeys "" "enable/disable this panel, 1 = show only when spectating other players, 2 = show always" seta hud_panel_pressedkeys_pos "" "position of this base of the panel" @@ -195,7 +215,7 @@ seta hud_panel_chat_bg_alpha "" "if set to something else than \"\" = override d seta hud_panel_chat_bg_border "" "if set to something else than \"\" = override default size of border around the background" seta hud_panel_chat_bg_padding "" "if set to something else than \"\" = override default padding of contents from border" -seta hud_panel_engineinfo "" "enable/disable this panel +seta hud_panel_engineinfo "" "enable/disable this panel" seta hud_panel_engineinfo_pos "" "position of this base of the panel" seta hud_panel_engineinfo_size "" "size of this panel" seta hud_panel_engineinfo_bg "" "if set to something else than \"\" = override default background" @@ -204,8 +224,10 @@ seta hud_panel_engineinfo_bg_color_team "" "override panel color with team color seta hud_panel_engineinfo_bg_alpha "" "if set to something else than \"\" = override default panel background alpha" seta hud_panel_engineinfo_bg_border "" "if set to something else than \"\" = override default size of border around the background" seta hud_panel_engineinfo_bg_padding "" "if set to something else than \"\" = override default padding of contents from border" +seta hud_panel_engineinfo_framecounter_decimals "" "amount of decimals to show" +seta hud_panel_engineinfo_framecounter_time "" "time between framerate display updates" -seta hud_panel_infomessages "" "enable/disable this panel +seta hud_panel_infomessages "" "enable/disable this panel" seta hud_panel_infomessages_pos "" "position of this base of the panel" seta hud_panel_infomessages_size "" "size of this panel" seta hud_panel_infomessages_bg "" "if set to something else than \"\" = override default background" @@ -215,3 +237,49 @@ seta hud_panel_infomessages_bg_alpha "" "if set to something else than \"\" = ov seta hud_panel_infomessages_bg_border "" "if set to something else than \"\" = override default size of border around the background" seta hud_panel_infomessages_bg_padding "" "if set to something else than \"\" = override default padding of contents from border" seta hud_panel_infomessages_flip "" "1 = align the items to the right" + +seta hud_panel_physics "" "enable/disable this panel, 1 = show if not observing, 2 = show always, 3 = show only in race/cts if not observing" +seta hud_panel_physics_pos "" "position of this base of the panel" +seta hud_panel_physics_size "" "size of this panel" +seta hud_panel_physics_bg "" "if set to something else than \"\" = override default background" +seta hud_panel_physics_bg_color "" "if set to something else than \"\" = override default panel background color" +seta hud_panel_physics_bg_color_team "" "override panel color with team color in team based games" +seta hud_panel_physics_bg_alpha "" "if set to something else than \"\" = override default panel background alpha" +seta hud_panel_physics_bg_border "" "if set to something else than \"\" = override default size of border around the background" +seta hud_panel_physics_bg_padding "" "if set to something else than \"\" = override default padding of contents from border" +seta hud_panel_physics_baralign "" "0 = align bars to the left, 1 = align bars to the right, 2 = align only left bar to the right, 3 = align only right bar to the right, 4 = align bars to the center" +seta hud_panel_physics_flip "" "flip speed/acceleration positions" +seta hud_panel_physics_progressbar "" "enable progressbar in panel (2 = only for speed; 3 = only for acceleration)" +seta hud_panel_physics_acceleration_max "" "acceleration progressbar gets completely filled up by this value (in g)" +seta hud_panel_physics_acceleration_mode "" "0 = progressbar increases from the center to the right if the acceleration is positive, to the left if it's negative; 1 = progressbar increases from the border in the same direction for both positive and negative accelerations" +seta hud_panel_physics_acceleration_vertical "" "include the acceleration on the Z-axis" +seta hud_panel_physics_text "" "show text in panel (2 = only for speed; 3 = only for acceleration)" +seta hud_panel_physics_speed_unit "" "speed unit (1 = qu/s, 2 = m/s, 3 = km/h, 4 = mph, 5 = knots)" +seta hud_panel_physics_speed_unit_show "" "also show speed unit" +seta hud_panel_physics_speed_max "" "speed progressbar gets filled up completely by this value (in qu/s)" +seta hud_panel_physics_speed_vertical "" "include the speed on the Z-axis" +seta hud_panel_physics_topspeed "" "also show top speed" +seta hud_panel_physics_topspeed_time "" "how many seconds the top speed takes to fade out" + +seta hud_panel_centerprint "" "enable/disable this panel" +seta hud_panel_centerprint_pos "" "position of this base of the panel" +seta hud_panel_centerprint_size "" "size of this panel" +seta hud_panel_centerprint_bg "" "if set to something else than \"\" = override default background" +seta hud_panel_centerprint_bg_color "" "if set to something else than \"\" = override default panel background color" +seta hud_panel_centerprint_bg_color_team "" "override panel color with team color in team based games" +seta hud_panel_centerprint_bg_alpha "" "if set to something else than \"\" = override default panel background alpha" +seta hud_panel_centerprint_bg_border "" "if set to something else than \"\" = override default size of border around the background" +seta hud_panel_centerprint_bg_padding "" "if set to something else than \"\" = override default padding of contents from border" +seta hud_panel_centerprint_align "" "text alignment: 0 left, 0.5 center, 1 right" +seta hud_panel_centerprint_flip "" "invert messages order" +seta hud_panel_centerprint_fontscale "" "scale the text font by this amount" +seta hud_panel_centerprint_time "" "message duration (NOTE: certain messages have a fixed duration)" +seta hud_panel_centerprint_fade_in "" "how long a message takes to fade in" +seta hud_panel_centerprint_fade_out "" "how long a message takes to fade out (this time is included in the message duration and can't be > 5)" +seta hud_panel_centerprint_fade_subsequent "" "enable extra fading effects for each additional message, so that the more messages you have the more they become faded out" +seta hud_panel_centerprint_fade_subsequent_passone "" "division factor for the first pass for alpha fading, with 2 all messages after the first have half alpha" +seta hud_panel_centerprint_fade_subsequent_passone_minalpha "" "minimum factor that the first pass can fade to" +seta hud_panel_centerprint_fade_subsequent_passtwo "" "division factor for the second pass for alpha fading, it applies another fade on top of the first pass to make it more transitioned" +seta hud_panel_centerprint_fade_subsequent_passtwo_minalpha "" "minimum factor that the second pass can fade to" +seta hud_panel_centerprint_fade_subsequent_minfontsize "" "minimum factor for the font size from the subsequent fading effects" +seta hud_panel_centerprint_fade_minfontsize "" "minimum factor for the font size from the fading in/out effects" diff --git a/apply-eol-style.sh b/apply-eol-style.sh deleted file mode 100755 index 6c6c997ccd..0000000000 --- a/apply-eol-style.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -while read -r EXT EOLSTYLE; do - echo "Fixing $EXT..." - find . -name .svn -prune -o -type f \( -name "*.$EXT" -o -name "$EXT" \) -print0 | \ - case "$EOLSTYLE" in - 1) - xargs -0 svn propset svn:eol-style native - ;; - 0) - xargs -0 svn propdel svn:eol-style - ;; - esac -done 0.16 to compensate a little for lower damage +set g_balance_shotgun_primary_refire 1 +set g_balance_shotgun_primary_animtime 0.3 +set g_balance_shotgun_primary_ammo 1 +set g_balance_shotgun_primary_speed 12000 +set g_balance_shotgun_primary_bulletconstant 75 // 3.8qu +set g_balance_shotgun_secondary 1 +set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow +set g_balance_shotgun_secondary_melee_range 120 +set g_balance_shotgun_secondary_melee_swing_side 120 +set g_balance_shotgun_secondary_melee_swing_up 30 +set g_balance_shotgun_secondary_melee_time 0.15 +set g_balance_shotgun_secondary_melee_traces 10 +set g_balance_shotgun_secondary_melee_no_doubleslap 1 +set g_balance_shotgun_secondary_melee_nonplayerdamage 0 +set g_balance_shotgun_secondary_melee_multihit 1 +set g_balance_shotgun_secondary_damage 110 +set g_balance_shotgun_secondary_force 150 +set g_balance_shotgun_secondary_refire 1.1 +set g_balance_shotgun_secondary_animtime 1 +set g_balance_shotgun_reload_ammo 0 //default: 5 +set g_balance_shotgun_reload_time 2 +// }}} +// {{{ uzi +set g_balance_uzi_mode 1 // Activates varible spread for sustained & burst mode secondary +set g_balance_uzi_spread_min 0.02 +set g_balance_uzi_spread_max 0.3 // LOG: 0.6 -> 0.3 +set g_balance_uzi_spread_add 0.008 + +set g_balance_uzi_burst 3 // # of bullets in a burst (if set to 2 or more) +set g_balance_uzi_burst_animtime 0.45 +set g_balance_uzi_burst_refire 0.05 // refire between burst bullets +set g_balance_uzi_burst_refire2 0.45 // refire after burst +set g_balance_uzi_burst_spread 0.07 +set g_balance_uzi_burst_damage 25 +set g_balance_uzi_burst_force 50 +set g_balance_uzi_burst_ammo 3 + +set g_balance_uzi_first 1 +set g_balance_uzi_first_damage 15 / f/ LOG: 22 -> 15 +set g_balance_uzi_first_headshotaddeddamage 0 +set g_balance_uzi_first_force 50 +set g_balance_uzi_first_spread 0.03 +set g_balance_uzi_first_refire 0.2 +set g_balance_uzi_first_ammo 2 + +set g_balance_uzi_sustained_damage 12 // 120 dps +set g_balance_uzi_sustained_headshotaddeddamage 0 +set g_balance_uzi_sustained_force 12 +set g_balance_uzi_sustained_spread 0.06 +set g_balance_uzi_sustained_refire 0.1 +set g_balance_uzi_sustained_ammo 1 + +set g_balance_uzi_speed 18000 +set g_balance_uzi_bulletconstant 115 // 13.1qu + +set g_balance_uzi_reload_ammo 0 //default: 30 +set g_balance_uzi_reload_time 2 +// }}} +// {{{ mortar +set g_balance_grenadelauncher_primary_type 0 +set g_balance_grenadelauncher_primary_damage 44 +set g_balance_grenadelauncher_primary_edgedamage 32 +set g_balance_grenadelauncher_primary_force 300 +set g_balance_grenadelauncher_primary_radius 115 +set g_balance_grenadelauncher_primary_speed 1500 +set g_balance_grenadelauncher_primary_speed_up 225 +set g_balance_grenadelauncher_primary_speed_z 0 +set g_balance_grenadelauncher_primary_spread 0 +set g_balance_grenadelauncher_primary_lifetime 5 +set g_balance_grenadelauncher_primary_lifetime2 0.65 +set g_balance_grenadelauncher_primary_refire 0.8 +set g_balance_grenadelauncher_primary_animtime 0.3 +set g_balance_grenadelauncher_primary_ammo 2 +set g_balance_grenadelauncher_primary_health 80 +set g_balance_grenadelauncher_primary_damageforcescale 0 +set g_balance_grenadelauncher_primary_remote_minbouncecnt 0 + +set g_balance_grenadelauncher_secondary_type 1 +set g_balance_grenadelauncher_secondary_damage 62 +set g_balance_grenadelauncher_secondary_edgedamage 32 +set g_balance_grenadelauncher_secondary_force 300 +set g_balance_grenadelauncher_secondary_radius 150 +set g_balance_grenadelauncher_secondary_speed 1000 +set g_balance_grenadelauncher_secondary_speed_up 250 +set g_balance_grenadelauncher_secondary_speed_z 0 +set g_balance_grenadelauncher_secondary_spread 0 +set g_balance_grenadelauncher_secondary_lifetime 3 +set g_balance_grenadelauncher_secondary_lifetime_bounce 0 +set g_balance_grenadelauncher_secondary_lifetime_stick 0.65 +set g_balance_grenadelauncher_secondary_refire 0.8 +set g_balance_grenadelauncher_secondary_animtime 0.3 +set g_balance_grenadelauncher_secondary_ammo 2 +set g_balance_grenadelauncher_secondary_health 40 +set g_balance_grenadelauncher_secondary_damageforcescale 0 +set g_balance_grenadelauncher_secondary_remote_detonateprimary 0 + +set g_balance_grenadelauncher_bouncefactor 0.5 +set g_balance_grenadelauncher_bouncestop 0.12 + +set g_balance_grenadelauncher_reload_ammo 0 //default: 12 +set g_balance_grenadelauncher_reload_time 2 +// }}} +// {{{ minelayer +set g_balance_minelayer_damage 42 +set g_balance_minelayer_edgedamage 30 +set g_balance_minelayer_force 250 +set g_balance_minelayer_radius 175 +set g_balance_minelayer_proximityradius 150 +set g_balance_minelayer_speed 750 +set g_balance_minelayer_lifetime 60 +set g_balance_minelayer_lifetime_countdown 0 +set g_balance_minelayer_refire 1.5 +set g_balance_minelayer_animtime 0.3 +set g_balance_minelayer_ammo 5 +set g_balance_minelayer_health 15 +set g_balance_minelayer_limit 3 // 0 disables the limit // LOG: 4 -> 3 +set g_balance_minelayer_protection 1 // don't explode if the mine would hurt the owner or a team mate +set g_balance_minelayer_damageforcescale 0 +set g_balance_minelayer_detonatedelay -1 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time +set g_balance_minelayer_time 0.5 +set g_balance_minelayer_remote_damage 45 +set g_balance_minelayer_remote_edgedamage 40 +set g_balance_minelayer_remote_radius 200 +set g_balance_minelayer_remote_force 300 +set g_balance_minelayer_reload_ammo 0 //default: 15 +set g_balance_minelayer_reload_time 2 +// }}} +// {{{ electro +set g_balance_electro_lightning 1 +set g_balance_electro_primary_damage 100 +set g_balance_electro_primary_edgedamage 0 +set g_balance_electro_primary_force 425 +set g_balance_electro_primary_force_up 125 +set g_balance_electro_primary_radius 850 +set g_balance_electro_primary_comboradius 150 +set g_balance_electro_primary_speed 0 +set g_balance_electro_primary_spread 0 +set g_balance_electro_primary_lifetime 0 +set g_balance_electro_primary_refire 0.4 +set g_balance_electro_primary_animtime 0.2 +set g_balance_electro_primary_ammo 5 +set g_balance_electro_primary_range 800 +set g_balance_electro_primary_falloff_mindist 0 +set g_balance_electro_primary_falloff_maxdist 0 +set g_balance_electro_primary_falloff_halflifedist 0 +set g_balance_electro_secondary_damage 25 +set g_balance_electro_secondary_edgedamage 0 +set g_balance_electro_secondary_force 100 +set g_balance_electro_secondary_radius 100 +set g_balance_electro_secondary_speed 700 +set g_balance_electro_secondary_speed_up 200 +set g_balance_electro_secondary_speed_z 0 +set g_balance_electro_secondary_spread 0.08 +set g_balance_electro_secondary_lifetime 3.5 +set g_balance_electro_secondary_refire 0.2 +set g_balance_electro_secondary_refire2 2 +set g_balance_electro_secondary_animtime 0.2 +set g_balance_electro_secondary_ammo 2 +set g_balance_electro_secondary_health 10 +set g_balance_electro_secondary_damageforcescale 4 +set g_balance_electro_secondary_damagedbycontents 0 +set g_balance_electro_secondary_count 3 +set g_balance_electro_secondary_bouncefactor 0.5 +set g_balance_electro_secondary_bouncestop 0.075 +set g_balance_electro_combo_damage 50 +set g_balance_electro_combo_edgedamage 0 +set g_balance_electro_combo_force 80 +set g_balance_electro_combo_radius 250 +set g_balance_electro_combo_comboradius 0 +set g_balance_electro_combo_speed 400 +set g_balance_electro_combo_safeammocheck 1 +set g_balance_electro_reload_ammo 0 //default: 20 +set g_balance_electro_reload_time 2 +// }}} +// {{{ crylink +set g_balance_crylink_primary_damage 7 // LOG: 10 -> 7 +set g_balance_crylink_primary_edgedamage 4 // LOG: 6 -> 4 +set g_balance_crylink_primary_force 35 +set g_balance_crylink_primary_radius 80 +set g_balance_crylink_primary_speed 1500 +set g_balance_crylink_primary_spread 0.05 +set g_balance_crylink_primary_shots 7 +set g_balance_crylink_primary_bounces 2 +set g_balance_crylink_primary_refire 0.8 +set g_balance_crylink_primary_animtime 0.3 +set g_balance_crylink_primary_ammo 2 +set g_balance_crylink_primary_bouncedamagefactor 0.2 +set g_balance_crylink_primary_joindelay 0 +set g_balance_crylink_primary_joinspread 0.2 +set g_balance_crylink_primary_jointime 0.1 +set g_balance_crylink_primary_joinexplode 0 +set g_balance_crylink_primary_joinexplode_damage 0 +set g_balance_crylink_primary_joinexplode_edgedamage 0 +set g_balance_crylink_primary_joinexplode_radius 0 +set g_balance_crylink_primary_joinexplode_force 0 +set g_balance_crylink_primary_linkexplode 1 + +set g_balance_crylink_primary_middle_lifetime 5 // range: 10000 full, fades to 20000 +set g_balance_crylink_primary_middle_fadetime 5 +set g_balance_crylink_primary_other_lifetime 2 // range: 800 full, fades to 1300 +set g_balance_crylink_primary_other_fadetime 0.25 + +set g_balance_crylink_secondary 1 +set g_balance_crylink_secondary_damage 5 // LOG: 8 -> 5 +set g_balance_crylink_secondary_edgedamage 3 +set g_balance_crylink_secondary_force 16 // LOG: 20 -> 16 +set g_balance_crylink_secondary_radius 15 // LOG: 20 -> 15 +set g_balance_crylink_secondary_speed 1250 // LOG: 1500 -> 1250 +set g_balance_crylink_secondary_spread 0.1 +set g_balance_crylink_secondary_shots 6 +set g_balance_crylink_secondary_bounces 2 +set g_balance_crylink_secondary_refire 0.9 // LOG: 0.8 -> 0.9 +set g_balance_crylink_secondary_animtime 0.3 +set g_balance_crylink_secondary_ammo 3 // LOG: 2 -> 3 +set g_balance_crylink_secondary_bouncedamagefactor 0.4 // LOG: 0.2 -> 0.4 +set g_balance_crylink_secondary_joindelay 0 +set g_balance_crylink_secondary_joinspread 0.2 +set g_balance_crylink_secondary_jointime 0.1 +set g_balance_crylink_secondary_joinexplode 0 +set g_balance_crylink_secondary_joinexplode_damage 0 +set g_balance_crylink_secondary_joinexplode_edgedamage 0 +set g_balance_crylink_secondary_joinexplode_radius 0 +set g_balance_crylink_secondary_joinexplode_force 0 +set g_balance_crylink_secondary_linkexplode 0 + +set g_balance_crylink_secondary_middle_lifetime 5 // range: 10000 full, fades to 10000 +set g_balance_crylink_secondary_middle_fadetime 5 +set g_balance_crylink_secondary_line_lifetime 2 // range: 4000 full, fades to 8000 +set g_balance_crylink_secondary_line_fadetime 0.25 + +set g_balance_crylink_reload_ammo 0 //default: 10 +set g_balance_crylink_reload_time 2 +// }}} +// {{{ nex +set g_balance_nex_primary_damage 90 +set g_balance_nex_primary_force 500 +set g_balance_nex_primary_refire 1 +set g_balance_nex_primary_animtime 0.3 +set g_balance_nex_primary_ammo 5 +set g_balance_nex_primary_damagefalloff_mindist 0 +set g_balance_nex_primary_damagefalloff_maxdist 0 +set g_balance_nex_primary_damagefalloff_halflife 0 +set g_balance_nex_primary_damagefalloff_forcehalflife 0 + +set g_balance_nex_secondary 0 // LOG: disable secondary +set g_balance_nex_secondary_charge 0 // LOG: disable secondary charge +set g_balance_nex_secondary_charge_rate 0.4 +set g_balance_nex_secondary_chargepool 1 +set g_balance_nex_secondary_chargepool_regen 0.25 +set g_balance_nex_secondary_chargepool_pause_regen 2 +set g_balance_nex_secondary_chargepool_pause_health_regen 0.5 +set g_balance_nex_secondary_damage 0 +set g_balance_nex_secondary_force 0 +set g_balance_nex_secondary_refire 0 +set g_balance_nex_secondary_animtime 0 +set g_balance_nex_secondary_ammo 0.4 // full charge pool is 1, so it depletes in 2.5 secs +set g_balance_nex_secondary_damagefalloff_mindist 0 +set g_balance_nex_secondary_damagefalloff_maxdist 0 +set g_balance_nex_secondary_damagefalloff_halflife 0 +set g_balance_nex_secondary_damagefalloff_forcehalflife 0 + +set g_balance_nex_charge 1 +set g_balance_nex_charge_mindmg 20 +set g_balance_nex_charge_start 0.5 +set g_balance_nex_charge_rate 0.5 +set g_balance_nex_charge_animlimit 0.5 +set g_balance_nex_charge_limit 1 // LOG: 0.5 -> 1 - allow to fully charge automaticaly +set g_balance_nex_charge_rot_rate 0 // LOG: 0.1 -> 0 - disable rot +set g_balance_nex_charge_rot_pause 0.5 // Dont rot down until this long after release of charge button +set g_balance_nex_charge_shot_multiplier 0 +set g_balance_nex_charge_velocity_rate 0 +set g_balance_nex_charge_minspeed 600 +set g_balance_nex_charge_maxspeed 1000 + +set g_balance_nex_reload_ammo 0 //default: 25 +set g_balance_nex_reload_time 2 +// }}} +// {{{ minstanex +set g_balance_minstanex_refire 1 +set g_balance_minstanex_animtime 0.50 +set g_balance_minstanex_ammo 10 +set g_balance_minstanex_laser_ammo 0 +set g_balance_minstanex_laser_animtime 0.3 +set g_balance_minstanex_laser_refire 0.6 +set g_balance_minstanex_reload_ammo 0 //default: 50 +set g_balance_minstanex_reload_time 2 +// }}} +// {{{ hagar +set g_balance_hagar_primary_damage 14 +set g_balance_hagar_primary_edgedamage 6 +set g_balance_hagar_primary_force 70 +set g_balance_hagar_primary_health 0 +set g_balance_hagar_primary_damageforcescale 0 +set g_balance_hagar_primary_radius 110 +set g_balance_hagar_primary_spread 0.1 +set g_balance_hagar_primary_speed 1800 +set g_balance_hagar_primary_lifetime 5 +set g_balance_hagar_primary_refire 0.12 +set g_balance_hagar_primary_ammo 1 +set g_balance_hagar_secondary 1 +set g_balance_hagar_secondary_load 0 +set g_balance_hagar_secondary_load_speed 0.6 +set g_balance_hagar_secondary_load_spread 0.075 +set g_balance_hagar_secondary_load_spread_bias 0.5 +set g_balance_hagar_secondary_load_max 4 +set g_balance_hagar_secondary_load_hold 0 +set g_balance_hagar_secondary_load_releasedeath 1 +set g_balance_hagar_secondary_load_abort 1 +set g_balance_hagar_secondary_load_linkexplode 0 +set g_balance_hagar_secondary_load_animtime 0.2 +set g_balance_hagar_secondary_damage 14 // default for _load: 32 +set g_balance_hagar_secondary_edgedamage 6 // default for _load: 10 +set g_balance_hagar_secondary_force 70 // default for _load: 160 +set g_balance_hagar_secondary_health 0 +set g_balance_hagar_secondary_damageforcescale 0 +set g_balance_hagar_secondary_radius 125 +set g_balance_hagar_secondary_spread 0.15 // default for _load: 0.08 +set g_balance_hagar_secondary_speed 1800 +set g_balance_hagar_secondary_lifetime_min 5 +set g_balance_hagar_secondary_lifetime_rand 0 +set g_balance_hagar_secondary_refire 0.12 // default for _load: 0.8 +set g_balance_hagar_secondary_ammo 1 +set g_balance_hagar_reload_ammo 0 //default: 25 +set g_balance_hagar_reload_time 2 +// }}} +// {{{ rocketlauncher +set g_balance_rocketlauncher_damage 82 +set g_balance_rocketlauncher_edgedamage 32 +set g_balance_rocketlauncher_force 350 +set g_balance_rocketlauncher_radius 130 +set g_balance_rocketlauncher_speed 1400 +set g_balance_rocketlauncher_speedaccel 1400 +set g_balance_rocketlauncher_speedstart 800 +set g_balance_rocketlauncher_lifetime 5 +set g_balance_rocketlauncher_refire 1 +set g_balance_rocketlauncher_animtime 0.3 +set g_balance_rocketlauncher_ammo 3 +set g_balance_rocketlauncher_health 0 +set g_balance_rocketlauncher_damageforcescale 0 +set g_balance_rocketlauncher_detonatedelay 0.05 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time +set g_balance_rocketlauncher_guiderate 42 // max degrees per second +set g_balance_rocketlauncher_guideratedelay 0.01 // immediate +set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic) +set g_balance_rocketlauncher_guidedelay 0.15 // delay before guiding kicks in +set g_balance_rocketlauncher_guidestop 0 // stop guiding when firing again +set g_balance_rocketlauncher_remote_damage 60 +set g_balance_rocketlauncher_remote_edgedamage 20 +set g_balance_rocketlauncher_remote_radius 120 +set g_balance_rocketlauncher_remote_force 350 +set g_balance_rocketlauncher_reload_ammo 0 //default: 25 +set g_balance_rocketlauncher_reload_time 2 +// }}} +// {{{ porto +set g_balance_porto_primary_refire 1.5 +set g_balance_porto_primary_animtime 0.2 +set g_balance_porto_primary_speed 2000 +set g_balance_porto_primary_lifetime 5 +set g_balance_portal_health 200 // these get recharged whenever the portal is used +set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used +// }}} +// {{{ hook +set g_balance_hook_primary_fuel 5 // hook monkeys set 0 +set g_balance_hook_primary_refire 0 // hook monkeys set 0 +set g_balance_hook_primary_animtime 0.2 // good shoot anim +set g_balance_hook_primary_hooked_time_max 0 // infinite +set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free +set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked +set g_balance_hook_secondary_damage 25 // not much +set g_balance_hook_secondary_edgedamage 5 // not much +set g_balance_hook_secondary_radius 500 // LOTS +set g_balance_hook_secondary_force -2000 // LOTS +set g_balance_hook_secondary_ammo 50 // a whole pack +set g_balance_hook_secondary_lifetime 5 // infinite +set g_balance_hook_secondary_speed 0 // not much throwing +set g_balance_hook_secondary_gravity 5 // fast falling +set g_balance_hook_secondary_refire 3 // don't drop too many bombs... +set g_balance_hook_secondary_animtime 0.2 // good shoot anim +set g_balance_hook_secondary_power 3 // effect behaves like a square function +set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds +set g_balance_hook_secondary_health 0 +set g_balance_hook_secondary_damageforcescale 0 +// }}} +// {{{ hlac +set g_balance_hlac_primary_spread_min 0.01 +set g_balance_hlac_primary_spread_max 0.075 +set g_balance_hlac_primary_spread_add 0.001 +set g_balance_hlac_primary_spread_crouchmod 0.25 + +set g_balance_hlac_primary_damage 15 +set g_balance_hlac_primary_edgedamage 10 +set g_balance_hlac_primary_force 70 +set g_balance_hlac_primary_radius 40 +set g_balance_hlac_primary_speed 9000 +set g_balance_hlac_primary_lifetime 5 + +set g_balance_hlac_primary_refire 0.1 +set g_balance_hlac_primary_animtime 0.2 +set g_balance_hlac_primary_ammo 1 + +set g_balance_hlac_secondary 1 +set g_balance_hlac_secondary_spread 0.15 +set g_balance_hlac_secondary_spread_crouchmod 0.5 + +set g_balance_hlac_secondary_damage 20 +set g_balance_hlac_secondary_edgedamage 13 +set g_balance_hlac_secondary_force 100 +set g_balance_hlac_secondary_radius 45 +set g_balance_hlac_secondary_speed 9000 +set g_balance_hlac_secondary_lifetime 5 + +set g_balance_hlac_secondary_refire 0.8 +set g_balance_hlac_secondary_animtime 0.4 +set g_balance_hlac_secondary_ammo 4 +set g_balance_hlac_secondary_shots 6 + +set g_balance_hlac_reload_ammo 0 //default: 20 +set g_balance_hlac_reload_time 2 +// }}} +// {{{ rifle +set g_balance_rifle_bursttime 0 +set g_balance_rifle_primary_tracer 1 +set g_balance_rifle_primary_shots 1 +set g_balance_rifle_primary_damage 60 +set g_balance_rifle_primary_headshotaddeddamage 60 +set g_balance_rifle_primary_spread 0 +set g_balance_rifle_primary_force 2 +set g_balance_rifle_primary_speed 40000 +set g_balance_rifle_primary_lifetime 5 +set g_balance_rifle_primary_refire 1.5 +set g_balance_rifle_primary_animtime 1.4 +set g_balance_rifle_primary_ammo 10 +set g_balance_rifle_primary_bulletconstant 110 // 62.2qu +set g_balance_rifle_primary_burstcost 0 +set g_balance_rifle_primary_bullethail 0 // empty magazine on shot +set g_balance_rifle_secondary 1 +set g_balance_rifle_secondary_reload 1 +set g_balance_rifle_secondary_tracer 0 +set g_balance_rifle_secondary_shots 1 +set g_balance_rifle_secondary_damage 42 +set g_balance_rifle_secondary_headshotaddeddamage 42 +set g_balance_rifle_secondary_spread 0 +set g_balance_rifle_secondary_force 2 +set g_balance_rifle_secondary_speed 20000 +set g_balance_rifle_secondary_lifetime 5 +set g_balance_rifle_secondary_refire 1.5 +set g_balance_rifle_secondary_animtime 1.4 +set g_balance_rifle_secondary_ammo 10 +set g_balance_rifle_secondary_bulletconstant 110 // 15.5qu +set g_balance_rifle_secondary_burstcost 0 +set g_balance_rifle_secondary_bullethail 0 // empty magazine on shot +set g_balance_rifle_reload_ammo 80 //default: 80 +set g_balance_rifle_reload_time 2 +// }}} +// {{{ tuba +set g_balance_tuba_refire 0.05 +set g_balance_tuba_animtime 0.05 +set g_balance_tuba_attenuation 0.5 +set g_balance_tuba_volume 1 +set g_balance_tuba_fadetime 0.25 +set g_balance_tuba_damage 5 +set g_balance_tuba_edgedamage 0 +set g_balance_tuba_radius 200 +set g_balance_tuba_force 40 +set g_balance_tuba_pitchstep 6 +// }}} +// {{{ fireball +set g_balance_fireball_primary_ammo 40 +set g_balance_fireball_primary_animtime 0.2 +set g_balance_fireball_primary_bfgdamage 100 +set g_balance_fireball_primary_bfgforce 0 +set g_balance_fireball_primary_bfgradius 1000 +set g_balance_fireball_primary_damage 200 +set g_balance_fireball_primary_damageforcescale 4 +set g_balance_fireball_primary_edgedamage 0 +set g_balance_fireball_primary_force 700 +set g_balance_fireball_primary_health 50 +set g_balance_fireball_primary_laserburntime 0.5 +set g_balance_fireball_primary_laserdamage 80 +set g_balance_fireball_primary_laseredgedamage 20 +set g_balance_fireball_primary_laserradius 256 +set g_balance_fireball_primary_lifetime 15 +set g_balance_fireball_primary_radius 200 +set g_balance_fireball_primary_refire 5 +set g_balance_fireball_primary_refire2 0 +set g_balance_fireball_primary_speed 650 +set g_balance_fireball_primary_spread 0 +set g_balance_fireball_secondary_ammo 5 +set g_balance_fireball_secondary_animtime 0.2 +set g_balance_fireball_secondary_damage 40 +set g_balance_fireball_secondary_damageforcescale 4 +set g_balance_fireball_secondary_damagetime 5 +set g_balance_fireball_secondary_force 100 +set g_balance_fireball_secondary_laserburntime 0.5 +set g_balance_fireball_secondary_laserdamage 50 +set g_balance_fireball_secondary_laseredgedamage 20 +set g_balance_fireball_secondary_laserradius 110 +set g_balance_fireball_secondary_lifetime 7 +set g_balance_fireball_secondary_refire 2 +set g_balance_fireball_secondary_speed 900 +set g_balance_fireball_secondary_speed_up 100 +set g_balance_fireball_secondary_speed_z 0 +set g_balance_fireball_secondary_spread 0 +set g_balance_fireball_reload_ammo 0 //default: 60 +set g_balance_fireball_reload_time 2 +// }}} +// {{{ seeker +set g_balance_seeker_type 0 // 0 = old seeker, 1 = new seeker. THIS IS A TEMPORARY CVAR FOR TESTING, will be removed later. +set g_balance_seeker_flac_ammo 0.5 +set g_balance_seeker_flac_animtime 0.1 +set g_balance_seeker_flac_damage 15 +set g_balance_seeker_flac_edgedamage 10 +set g_balance_seeker_flac_force 50 +set g_balance_seeker_flac_lifetime 0.1 +set g_balance_seeker_flac_lifetime_rand 0.05 +set g_balance_seeker_flac_radius 100 +set g_balance_seeker_flac_refire 0.1 +set g_balance_seeker_flac_speed 3000 +set g_balance_seeker_flac_speed_up 1000 +set g_balance_seeker_flac_speed_z 0 +set g_balance_seeker_flac_spread 0.4 +set g_balance_seeker_missile_accel 1400 +set g_balance_seeker_missile_ammo 2 +set g_balance_seeker_missile_animtime 0.2 +set g_balance_seeker_missile_count 3 // LOG: 8 -> 3 +set g_balance_seeker_missile_damage 30 // LOG: 15 -> 30 +set g_balance_seeker_missile_damageforcescale 4 +set g_balance_seeker_missile_decel 1400 +set g_balance_seeker_missile_delay 0.25 +set g_balance_seeker_missile_edgedamage 10 +set g_balance_seeker_missile_force 150 // LOG: 100 -> 150 +set g_balance_seeker_missile_health 5 +set g_balance_seeker_missile_lifetime 15 +set g_balance_seeker_missile_proxy 0 +set g_balance_seeker_missile_proxy_delay 0.2 +set g_balance_seeker_missile_proxy_maxrange 45 +set g_balance_seeker_missile_radius 80 +set g_balance_seeker_missile_refire 0.5 +set g_balance_seeker_missile_smart 1 +set g_balance_seeker_missile_smart_mindist 800 +set g_balance_seeker_missile_smart_trace_max 2500 +set g_balance_seeker_missile_smart_trace_min 1000 +set g_balance_seeker_missile_speed 700 +set g_balance_seeker_missile_speed_up 300 +set g_balance_seeker_missile_speed_z 0 +set g_balance_seeker_missile_speed_max 1300 // LOG: 1400 -> 1300 +set g_balance_seeker_missile_spread 0 +set g_balance_seeker_missile_turnrate 0.65 +set g_balance_seeker_tag_ammo 1 +set g_balance_seeker_tag_animtime 0.2 +set g_balance_seeker_tag_damageforcescale 4 +set g_balance_seeker_tag_health 5 +set g_balance_seeker_tag_lifetime 15 +set g_balance_seeker_tag_refire 0.75 // LOG: 0.7 -> 0.75 +set g_balance_seeker_tag_speed 5000 +set g_balance_seeker_tag_spread 0 +set g_balance_seeker_tag_tracker_lifetime 10 +set g_balance_seeker_reload_ammo 0 //default: 15 +set g_balance_seeker_reload_time 2 +// End new seeker diff --git a/balanceLeeStricklin.cfg b/balanceLeeStricklin.cfg deleted file mode 100644 index 1bb993bac9..0000000000 --- a/balanceLeeStricklin.cfg +++ /dev/null @@ -1,734 +0,0 @@ -// {{{ starting gear -set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_minelayer -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_hlac 0 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_campingrifle -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_fireball 0 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_seeker -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_balance_health_start 200 -set g_balance_armor_start 115 -set g_start_ammo_shells 45 -set g_start_ammo_nails 0 -set g_start_ammo_rockets 0 -set g_start_ammo_cells 0 -set g_start_ammo_fuel 0 -set g_warmup_start_health 200 "starting values when being in warmup-stage" -set g_warmup_start_armor 100 "starting values when being in warmup-stage" -set g_warmup_start_ammo_shells 50 "starting values when being in warmup-stage" -set g_warmup_start_ammo_nails 150 "starting values when being in warmup-stage" -set g_warmup_start_ammo_rockets 50 "starting values when being in warmup-stage" -set g_warmup_start_ammo_cells 50 "starting values when being in warmup-stage" -set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage" -set g_lms_start_health 200 -set g_lms_start_armor 100 -set g_lms_start_ammo_shells 50 -set g_lms_start_ammo_nails 150 -set g_lms_start_ammo_rockets 50 -set g_lms_start_ammo_cells 50 -set g_lms_start_ammo_fuel 0 -set g_balance_nix_roundtime 25 -set g_balance_nix_incrtime 1.6 -set g_balance_nix_ammo_shells 15 -set g_balance_nix_ammo_nails 45 -set g_balance_nix_ammo_rockets 15 -set g_balance_nix_ammo_cells 15 -set g_balance_nix_ammo_fuel 0 -set g_balance_nix_ammoincr_shells 2 -set g_balance_nix_ammoincr_nails 6 -set g_balance_nix_ammoincr_rockets 2 -set g_balance_nix_ammoincr_cells 2 -set g_balance_nix_ammoincr_fuel 2 -// }}} - -// {{{ pickup items -set g_pickup_ammo_anyway 0 -set g_pickup_weapons_anyway 1 -set g_pickup_shells 20 -set g_pickup_shells_weapon 20 -set g_pickup_shells_max 45 -set g_pickup_nails 120 -set g_pickup_nails_weapon 120 -set g_pickup_nails_max 300 -set g_pickup_rockets 25 -set g_pickup_rockets_weapon 25 -set g_pickup_rockets_max 150 -set g_pickup_cells 25 -set g_pickup_cells_weapon 25 -set g_pickup_cells_max 200 -set g_pickup_fuel 25 -set g_pickup_fuel_weapon 25 -set g_pickup_fuel_jetpack 50 -set g_pickup_fuel_max 999 -set g_pickup_armorsmall 10 -set g_pickup_armorsmall_max 250 -set g_pickup_armorsmall_anyway 1 -set g_pickup_armormedium 25 -set g_pickup_armormedium_max 250 -set g_pickup_armormedium_anyway 0 -set g_pickup_armorbig 50 -set g_pickup_armorbig_max 250 -set g_pickup_armorbig_anyway 0 -set g_pickup_armorlarge 100 -set g_pickup_armorlarge_max 250 -set g_pickup_armorlarge_anyway 0 -set g_pickup_healthsmall 10 -set g_pickup_healthsmall_max 300 -set g_pickup_healthsmall_anyway 1 -set g_pickup_healthmedium 25 -set g_pickup_healthmedium_max 300 -set g_pickup_healthmedium_anyway 0 -set g_pickup_healthlarge 50 -set g_pickup_healthlarge_max 300 -set g_pickup_healthlarge_anyway 0 -set g_pickup_healthmega 100 -set g_pickup_healthmega_max 300 -set g_pickup_healthmega_anyway 1 -set g_pickup_respawntime_short 15 -set g_pickup_respawntime_medium 20 -set g_pickup_respawntime_long 30 -set g_pickup_respawntime_powerup 120 -set g_pickup_respawntime_weapon 15 -set g_pickup_respawntime_ammo 15 -set g_pickup_respawntimejitter_short 0 -set g_pickup_respawntimejitter_medium 0 -set g_pickup_respawntimejitter_long 0 -set g_pickup_respawntimejitter_powerup 10 -set g_pickup_respawntimejitter_weapon 0 -set g_pickup_respawntimejitter_ammo 0 -// }}} - -// {{{ regen/rot -set g_balance_health_regen 0 -set g_balance_health_regenlinear 5 -set g_balance_pause_health_regen 5 -set g_balance_pause_health_regen_spawn 0 -set g_balance_health_rot 0 -set g_balance_health_rotlinear 5 -set g_balance_pause_health_rot 3 -set g_balance_pause_health_rot_spawn 1 -set g_balance_health_regenstable 100 -set g_balance_health_rotstable 100 -set g_balance_health_limit 300 -set g_balance_armor_regen 0 -set g_balance_armor_regenlinear 0 -set g_balance_armor_rot 0 -set g_balance_armor_rotlinear 4.86 -set g_balance_pause_armor_rot 1 -set g_balance_pause_armor_rot_spawn 1 -set g_balance_armor_regenstable 100 -set g_balance_armor_rotstable 200 -set g_balance_armor_limit 250 -set g_balance_armor_blockpercent 0.6 -set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)" -set g_balance_fuel_regenlinear 0 -set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter -set g_balance_fuel_rot 0.05 -set g_balance_fuel_rotlinear 0 -set g_balance_pause_fuel_rot 5 -set g_balance_pause_fuel_rot_spawn 10 -set g_balance_fuel_regenstable 100 -set g_balance_fuel_rotstable 999 -set g_balance_fuel_limit 999 -// }}} - -// {{{ misc -set g_balance_selfdamagepercent 0.6 -set g_balance_weaponswitchdelay 0.15 -set g_weaponspeedfactor 1 "weapon projectile speed multiplier" -set g_weaponratefactor 1 "weapon fire rate multiplier" -set g_weapondamagefactor 1 "weapon damage multiplier" -set g_weaponforcefactor 1 "weapon force multiplier" -set g_weaponspreadfactor 1 "weapon spread multiplier" -set g_balance_firetransfer_time 0.9 -set g_balance_firetransfer_damage 0.8 -set g_throughfloor_damage 0.4 -set g_throughfloor_force 0.7 -set g_projectiles_newton_style 2 -// possible values: -// 0: absolute velocity projectiles (like Quake) -// 1: relative velocity projectiles, "Newtonian" (like Tribes 2) -// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard) -// 3: absolute velocity + player velocity component in shot direction (note: does NOT yield the right relative velocity, but may be good enough, but it is somewhat prone to sniper rockets) -// 4: just add the player velocity length to the absolute velocity (tZork's sniper rockets) -set g_projectiles_newton_style_2_minfactor 0.8 -set g_projectiles_newton_style_2_maxfactor 1.5 -set g_projectiles_spread_style 0 -// possible values: -// 0: forward + solid sphere (like Quake) - varies velocity -// 1: forward + flattened solid sphere -// 2: forward + solid circle -// 3: forward + normal distribution 3D - varies velocity -// 4: forward + normal distribution on a plane -// 5: forward + circle with 1-r falloff -// 6: forward + circle with 1-r^2 falloff -// 7: forward + circle with (1-r)(2-r) falloff -set g_balance_falldamage_deadminspeed 150 -set g_balance_falldamage_minspeed 1400 -set g_balance_falldamage_factor 0.15 -set g_balance_falldamage_maxdamage 25 -// }}} - -// {{{ powerups -set g_balance_powerup_invincible_takedamage 0.2 -set g_balance_powerup_invincible_time 30 -set g_balance_powerup_strength_damage 3 -set g_balance_powerup_strength_force 3 -set g_balance_powerup_strength_time 30 -set g_balance_powerup_strength_selfdamage 1.5 -set g_balance_powerup_strength_selfforce 1.5 -// }}} - -// {{{ jetpack/hook -set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack" -set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction" -set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)" -set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction" -set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction" -set g_jetpack_fuel 8 "fuel per second for jetpack" -set g_jetpack_attenuation 2 "jetpack sound attenuation" - -set g_grappling_hook_tarzan 2 // 2: can also pull players -set g_balance_grapplehook_speed_fly 1800 -set g_balance_grapplehook_speed_pull 2000 -set g_balance_grapplehook_force_rubber 2000 -set g_balance_grapplehook_force_rubber_overstretch 1000 -set g_balance_grapplehook_length_min 50 -set g_balance_grapplehook_stretch 50 -set g_balance_grapplehook_airfriction 0.2 -set g_balance_grapplehook_health 130 -// }}} - -// {{{ weapon properties -// {{{ laser -set g_balance_laser_primary_damage 25 -set g_balance_laser_primary_edgedamage 10 -set g_balance_laser_primary_force 182 // Original value was insanely low :P -set g_balance_laser_primary_radius 70 -set g_balance_laser_primary_speed 12000 -set g_balance_laser_primary_spread 0 -set g_balance_laser_primary_refire 0.7 -set g_balance_laser_primary_animtime 0.3 -set g_balance_laser_primary_lifetime 30 -set g_balance_laser_primary_shotangle 0 -set g_balance_laser_primary_delay 0.03 -set g_balance_laser_primary_gauntlet 0 -set g_balance_laser_primary_force_zscale 2 // 300 upforce -set g_balance_laser_primary_force_velocitybias 0.3 -set g_balance_laser_secondary 0 // when 1, a secondary laser mode exists -set g_balance_laser_secondary_damage 200 // dps -set g_balance_laser_secondary_edgedamage 0 -set g_balance_laser_secondary_force 1300 -set g_balance_laser_secondary_radius 60 -set g_balance_laser_secondary_speed 0 -set g_balance_laser_secondary_spread 0 -set g_balance_laser_secondary_refire 0.066 -set g_balance_laser_secondary_animtime 0.066 -set g_balance_laser_secondary_lifetime 0 -set g_balance_laser_secondary_shotangle 0 -set g_balance_laser_secondary_delay 0 -set g_balance_laser_secondary_gauntlet 1 -set g_balance_laser_secondary_force_zscale 1.25 -set g_balance_laser_secondary_force_velocitybias 0 -// }}} -// {{{ shotgun -set g_balance_shotgun_primary_bullets 5 -set g_balance_shotgun_primary_damage 12 -set g_balance_shotgun_primary_force 40 -set g_balance_shotgun_primary_spread 0.08 -set g_balance_shotgun_primary_refire 0.5 -set g_balance_shotgun_primary_animtime 0.2 -set g_balance_shotgun_primary_ammo 1 -set g_balance_shotgun_primary_speed 12000 -set g_balance_shotgun_primary_bulletconstant 75 // 3.8qu -set g_balance_shotgun_secondary 1 -set g_balance_shotgun_secondary_melee_delay 0.35 // match the anim -set g_balance_shotgun_secondary_melee_range 85 -set g_balance_shotgun_secondary_melee_swing 50 -set g_balance_shotgun_secondary_melee_time 0.1 -set g_balance_shotgun_secondary_damage 84 -set g_balance_shotgun_secondary_force 147 -set g_balance_shotgun_secondary_refire 1.1 -set g_balance_shotgun_secondary_animtime 1 -// }}} -// {{{ uzi -set g_balance_uzi_mode 0 // Activates varible spread for sustained & burst mode secondary -set g_balance_uzi_spread_min 0.02 -set g_balance_uzi_spread_max 0.6 -set g_balance_uzi_spread_add 0.012 -set g_balance_uzi_burst 0 // # of bullets in a burst (if set to 2 or more) -set g_balance_uzi_burst_refire 0.05 // refire between burst bullets -set g_balance_uzi_burst_refire2 0.75 // refire after burst -set g_balance_uzi_burst_spread 0.04 -set g_balance_uzi_burst_damage 18 -set g_balance_uzi_burst_force 50 -set g_balance_uzi_burst_ammo 3 -set g_balance_uzi_first 1 -set g_balance_uzi_first_damage 26 -set g_balance_uzi_first_force -30 -set g_balance_uzi_first_spread 0.01 -set g_balance_uzi_first_refire 0.2 -set g_balance_uzi_first_ammo 1 -set g_balance_uzi_sustained_damage 17 -set g_balance_uzi_sustained_force 27 -set g_balance_uzi_sustained_spread 0.05 -set g_balance_uzi_sustained_refire 0.1 -set g_balance_uzi_sustained_ammo 1 -set g_balance_uzi_speed 18000 -set g_balance_uzi_bulletconstant 300 // 13.1qu -// }}} -// {{{ mortar -set g_balance_grenadelauncher_primary_type 0 -set g_balance_grenadelauncher_primary_damage 65 -set g_balance_grenadelauncher_primary_edgedamage 35 -set g_balance_grenadelauncher_primary_force 310 -set g_balance_grenadelauncher_primary_radius 140 -set g_balance_grenadelauncher_primary_speed 2000 -set g_balance_grenadelauncher_primary_speed_up 200 -set g_balance_grenadelauncher_primary_speed_z 0 -set g_balance_grenadelauncher_primary_spread 0 -set g_balance_grenadelauncher_primary_lifetime 30 -set g_balance_grenadelauncher_primary_lifetime2 0.65 -set g_balance_grenadelauncher_primary_refire 0.7 -set g_balance_grenadelauncher_primary_animtime 0.3 -set g_balance_grenadelauncher_primary_ammo 2 -set g_balance_grenadelauncher_primary_health 72 -set g_balance_grenadelauncher_primary_damageforcescale 0 -set g_balance_grenadelauncher_primary_remote_minbouncecnt 0 - -set g_balance_grenadelauncher_secondary_type 1 -set g_balance_grenadelauncher_secondary_damage 65 -set g_balance_grenadelauncher_secondary_edgedamage 35 -set g_balance_grenadelauncher_secondary_force 320 -set g_balance_grenadelauncher_secondary_radius 140 -set g_balance_grenadelauncher_secondary_speed 1400 -set g_balance_grenadelauncher_secondary_speed_up 200 -set g_balance_grenadelauncher_secondary_speed_z 0 -set g_balance_grenadelauncher_secondary_spread 0 -set g_balance_grenadelauncher_secondary_lifetime 2.5 -set g_balance_grenadelauncher_secondary_lifetime2 1 -set g_balance_grenadelauncher_secondary_refire 0.6 -set g_balance_grenadelauncher_secondary_animtime 0.3 -set g_balance_grenadelauncher_secondary_ammo 2 -set g_balance_grenadelauncher_secondary_health 40 -set g_balance_grenadelauncher_secondary_damageforcescale 0 -set g_balance_grenadelauncher_secondary_remote_detonateprimary 0 - -set g_balance_grenadelauncher_bouncefactor 0.7 -set g_balance_grenadelauncher_bouncestop 0.12 -// }}} -// {{{ minelayer -set g_balance_minelayer_damage 65 -set g_balance_minelayer_edgedamage 30 -set g_balance_minelayer_force 250 -set g_balance_minelayer_radius 175 -set g_balance_minelayer_proximityradius 150 -set g_balance_minelayer_speed 750 -set g_balance_minelayer_lifetime 60 -set g_balance_minelayer_refire 1.3 -set g_balance_minelayer_animtime 0.4 -set g_balance_minelayer_ammo 5 -set g_balance_minelayer_health 15 -set g_balance_minelayer_limit 4 // 0 disables the limit -set g_balance_minelayer_protection 1 // don't explode if the mine would hurt the owner or a team mate -set g_balance_minelayer_damageforcescale 0 -set g_balance_minelayer_detonatedelay -1 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time -set g_balance_minelayer_time 0.5 -set g_balance_minelayer_remote_damage 45 -set g_balance_minelayer_remote_edgedamage 40 -set g_balance_minelayer_remote_radius 200 -set g_balance_minelayer_remote_force 300 -// }}} -// {{{ electro -set g_balance_electro_lightning 0 -set g_balance_electro_primary_damage 55 -set g_balance_electro_primary_edgedamage 5 -set g_balance_electro_primary_force 267 -set g_balance_electro_primary_force_up 125 -set g_balance_electro_primary_radius 150 -set g_balance_electro_primary_comboradius 75 -set g_balance_electro_primary_speed 2000 -set g_balance_electro_primary_spread 0 -set g_balance_electro_primary_lifetime 30 -set g_balance_electro_primary_refire 0.78 -set g_balance_electro_primary_animtime 0.4 -set g_balance_electro_primary_ammo 2 -set g_balance_electro_primary_range 800 -set g_balance_electro_primary_falloff_mindist 255 -set g_balance_electro_primary_falloff_maxdist 850 -set g_balance_electro_primary_falloff_halflifedist 0 -set g_balance_electro_secondary_damage 60 -set g_balance_electro_secondary_edgedamage 0 -set g_balance_electro_secondary_force 200 -set g_balance_electro_secondary_radius 150 -set g_balance_electro_secondary_speed 900 -set g_balance_electro_secondary_speed_up 200 -set g_balance_electro_secondary_speed_z 0 -set g_balance_electro_secondary_spread 0.05 -set g_balance_electro_secondary_lifetime 3 -set g_balance_electro_secondary_refire 0.2 -set g_balance_electro_secondary_refire2 1 -set g_balance_electro_secondary_animtime 0.3 -set g_balance_electro_secondary_ammo 2 -set g_balance_electro_secondary_health 10 -set g_balance_electro_secondary_damageforcescale 4 -set g_balance_electro_secondary_count 3 -set g_balance_electro_secondary_bouncefactor 0.5 -set g_balance_electro_secondary_bouncestop 0.075 -set g_balance_electro_combo_damage 70 -set g_balance_electro_combo_edgedamage 0 -set g_balance_electro_combo_force 200 -set g_balance_electro_combo_radius 250 -set g_balance_electro_combo_comboradius 70 -set g_balance_electro_combo_speed 400 -// }}} -// {{{ crylink -set g_balance_crylink_primary_damage 23 -set g_balance_crylink_primary_edgedamage 0 -set g_balance_crylink_primary_force -55 -set g_balance_crylink_primary_radius 80 -set g_balance_crylink_primary_speed 6820 -set g_balance_crylink_primary_spread 0.03 -set g_balance_crylink_primary_shots 4 -set g_balance_crylink_primary_bounces 2 -set g_balance_crylink_primary_refire 0.4 -set g_balance_crylink_primary_animtime 0.30008 -set g_balance_crylink_primary_ammo 3 -set g_balance_crylink_primary_bouncedamagefactor 0.2 -set g_balance_crylink_primary_joinspread 0 -set g_balance_crylink_primary_jointime 0 -set g_balance_crylink_primary_joinexplode 0 -set g_balance_crylink_primary_joinexplode_damage 0 -set g_balance_crylink_primary_joinexplode_edgedamage 0 -set g_balance_crylink_primary_joinexplode_radius 0 -set g_balance_crylink_primary_joinexplode_force 0 -set g_balance_crylink_primary_linkexplode 1 - -set g_balance_crylink_primary_middle_lifetime 5 // range: 10000 full, fades to 20000 -set g_balance_crylink_primary_middle_fadetime 5 -set g_balance_crylink_primary_other_lifetime 2 // range: 800 full, fades to 1300 -set g_balance_crylink_primary_other_fadetime 0.25 - -set g_balance_crylink_secondary 1 -set g_balance_crylink_secondary_damage 19 -set g_balance_crylink_secondary_edgedamage 0 -set g_balance_crylink_secondary_force -55 -set g_balance_crylink_secondary_radius 3 -set g_balance_crylink_secondary_speed 6950 -set g_balance_crylink_secondary_spread 0.08 -set g_balance_crylink_secondary_shots 7 -set g_balance_crylink_secondary_bounces 0 -set g_balance_crylink_secondary_refire 0.5 -set g_balance_crylink_secondary_animtime 0.3 -set g_balance_crylink_secondary_ammo 3 -set g_balance_crylink_secondary_bouncedamagefactor 0.5 -set g_balance_crylink_secondary_joinspread 0 -set g_balance_crylink_secondary_jointime 0 -set g_balance_crylink_secondary_joinexplode 0 -set g_balance_crylink_secondary_joinexplode_damage 0 -set g_balance_crylink_secondary_joinexplode_edgedamage 0 -set g_balance_crylink_secondary_joinexplode_radius 0 -set g_balance_crylink_secondary_joinexplode_force 0 -set g_balance_crylink_secondary_linkexplode 1 - -set g_balance_crylink_secondary_middle_lifetime 5 // range: 10000 full, fades to 10000 -set g_balance_crylink_secondary_middle_fadetime 5 -set g_balance_crylink_secondary_line_lifetime 2 // range: 4000 full, fades to 8000 -set g_balance_crylink_secondary_line_fadetime 2 -// }}} -// {{{ nex -set g_balance_nex_primary_damage 72 -set g_balance_nex_primary_force 600 -set g_balance_nex_primary_refire 1.505 -set g_balance_nex_primary_animtime 0.3 -set g_balance_nex_primary_ammo 5 -set g_balance_nex_primary_damagefalloff_mindist 9999999 -set g_balance_nex_primary_damagefalloff_maxdist 9999999 -set g_balance_nex_primary_damagefalloff_halflife 9999999 -set g_balance_nex_primary_damagefalloff_forcehalflife 9999999 - -set g_balance_nex_secondary 1 -set g_balance_nex_secondary_charge 1 -set g_balance_nex_secondary_charge_rate 0.25 -set g_balance_nex_secondary_chargepool 0 -set g_balance_nex_secondary_chargepool_regen 0.15 -set g_balance_nex_secondary_chargepool_pause_regen 1 -set g_balance_nex_secondary_chargepool_pause_health_regen 1 -set g_balance_nex_secondary_damage 80 -set g_balance_nex_secondary_force -500 -set g_balance_nex_secondary_refire 1.25 -set g_balance_nex_secondary_animtime 0.75 -set g_balance_nex_secondary_ammo 2 -set g_balance_nex_secondary_damagefalloff_mindist 9999999 -set g_balance_nex_secondary_damagefalloff_maxdist 9999999 -set g_balance_nex_secondary_damagefalloff_halflife 9999999 -set g_balance_nex_secondary_damagefalloff_forcehalflife 9999999 - -set g_balance_nex_charge 1 -set g_balance_nex_charge_mindmg 40 -set g_balance_nex_charge_start 0 -set g_balance_nex_charge_rate 0.1 -set g_balance_nex_charge_limit 0.5 -set g_balance_nex_charge_rot_rate 0 -set g_balance_nex_charge_rot_pause 0 // Dont rot down untill this long after release of charge button -set g_balance_nex_charge_shot_multiplier 0 -set g_balance_nex_charge_velocity_rate 0.2 -set g_balance_nex_charge_minspeed "" -set g_balance_nex_charge_maxspeed "" -// }}} -// {{{ minstanex -set g_balance_minstanex_refire 1 -set g_balance_minstanex_animtime 0.278 -set g_balance_minstanex_ammo 10 -// }}} -// {{{ hagar -set g_balance_hagar_primary_damage 43 -set g_balance_hagar_primary_edgedamage 15 -set g_balance_hagar_primary_force 94 -set g_balance_hagar_primary_radius 70 -set g_balance_hagar_primary_spread 0.010 -set g_balance_hagar_primary_speed 3000 -set g_balance_hagar_primary_lifetime 30 -set g_balance_hagar_primary_refire 0.15 -set g_balance_hagar_primary_ammo 2 -set g_balance_hagar_secondary 1 -set g_balance_hagar_secondary_damage 43 -set g_balance_hagar_secondary_edgedamage 15 -set g_balance_hagar_secondary_force 100 -set g_balance_hagar_secondary_radius 70 -set g_balance_hagar_secondary_spread 0.015 -set g_balance_hagar_secondary_speed 1400 -set g_balance_hagar_secondary_lifetime_min 5 -set g_balance_hagar_secondary_lifetime_rand 0 -set g_balance_hagar_secondary_refire 0.15 -set g_balance_hagar_secondary_ammo 2 -// }}} -// {{{ rocketlauncher -set g_balance_rocketlauncher_damage 65 -set g_balance_rocketlauncher_edgedamage 25 -set g_balance_rocketlauncher_force 360 -set g_balance_rocketlauncher_radius 185 -set g_balance_rocketlauncher_speed 900 -set g_balance_rocketlauncher_speedaccel 0 -set g_balance_rocketlauncher_speedstart 850 -set g_balance_rocketlauncher_lifetime 30 -set g_balance_rocketlauncher_refire 1 -set g_balance_rocketlauncher_animtime 0.3 -set g_balance_rocketlauncher_ammo 7 -set g_balance_rocketlauncher_health 40 -set g_balance_rocketlauncher_damageforcescale 4 -set g_balance_rocketlauncher_detonatedelay -1 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time -set g_balance_rocketlauncher_guiderate 65 // max degrees per second -set g_balance_rocketlauncher_guideratedelay 0.01 // immediate -set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic) -set g_balance_rocketlauncher_guidedelay 0.15 // delay before guiding kicks in -set g_balance_rocketlauncher_guidestop 0 // stop guiding when firing again -set g_balance_rocketlauncher_remote_damage 120 -set g_balance_rocketlauncher_remote_edgedamage 46 -set g_balance_rocketlauncher_remote_radius 185 -set g_balance_rocketlauncher_remote_force 590 -// }}} -// {{{ porto -set g_balance_porto_primary_refire 1.5 -set g_balance_porto_primary_animtime 0.3 -set g_balance_porto_primary_speed 5000 -set g_balance_porto_primary_lifetime 30 -set g_balance_portal_health 200 // these get recharged whenever the portal is used -set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used -// }}} -// {{{ hook -set g_balance_hook_primary_fuel 2 // hook monkeys set 0 -set g_balance_hook_primary_refire 0 // hook monkeys set 0 -set g_balance_hook_primary_animtime 0.3 // good shoot anim -set g_balance_hook_primary_hooked_time_max 0 // infinite -set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free -set g_balance_hook_primary_hooked_fuel 3 // fuel per second hooked -set g_balance_hook_secondary_damage 25 // not much -set g_balance_hook_secondary_edgedamage 5 // not much -set g_balance_hook_secondary_radius 500 // LOTS -set g_balance_hook_secondary_force -2000 // LOTS -set g_balance_hook_secondary_ammo 50 // a whole pack -set g_balance_hook_secondary_lifetime 30 // infinite -set g_balance_hook_secondary_speed 0 // not much throwing -set g_balance_hook_secondary_gravity 5 // fast falling -set g_balance_hook_secondary_refire 3 // don't drop too many bombs... -set g_balance_hook_secondary_animtime 0.3 // good shoot anim -set g_balance_hook_secondary_power 3 // effect behaves like a square function -set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds -// }}} -// {{{ hlac -set g_balance_hlac_primary_spread_min 0.01 -set g_balance_hlac_primary_spread_max 0.25 -set g_balance_hlac_primary_spread_add 0.0045 -set g_balance_hlac_primary_spread_crouchmod 0.25 - -set g_balance_hlac_primary_damage 17 -set g_balance_hlac_primary_edgedamage 10 -set g_balance_hlac_primary_force 45 -set g_balance_hlac_primary_radius 70 -set g_balance_hlac_primary_speed 9000 -set g_balance_hlac_primary_lifetime 5 - -set g_balance_hlac_primary_refire 0.1 -set g_balance_hlac_primary_animtime 0.3 -set g_balance_hlac_primary_ammo 3 - -set g_balance_hlac_secondary 1 -set g_balance_hlac_secondary_spread 0.15 -set g_balance_hlac_secondary_spread_crouchmod 0.5 - -set g_balance_hlac_secondary_damage 18 -set g_balance_hlac_secondary_edgedamage 10 -set g_balance_hlac_secondary_force 100 -set g_balance_hlac_secondary_radius 70 -set g_balance_hlac_secondary_speed 9000 -set g_balance_hlac_secondary_lifetime 5 - -set g_balance_hlac_secondary_refire 1 -set g_balance_hlac_secondary_animtime 0.3 -set g_balance_hlac_secondary_ammo 11 -set g_balance_hlac_secondary_shots 6 -// }}} -// {{{ campingrifle -set g_balance_campingrifle_magazinecapacity 8 -set g_balance_campingrifle_reloadtime 2 // matches reload anim -set g_balance_campingrifle_auto_reload_on_switch 0 -set g_balance_campingrifle_bursttime 0.85 // 0.35 - 0.1 + 0.35 - 0.1 + 0.35 = three secondaries -set g_balance_campingrifle_primary_tracer 0 -set g_balance_campingrifle_primary_damage 75 -set g_balance_campingrifle_primary_headshotaddeddamage 90 -set g_balance_campingrifle_primary_spread 0 -set g_balance_campingrifle_primary_force 2 -set g_balance_campingrifle_primary_speed 35000 -set g_balance_campingrifle_primary_lifetime 5 -set g_balance_campingrifle_primary_refire 0.7 -set g_balance_campingrifle_primary_animtime 0.3 -set g_balance_campingrifle_primary_ammo 10 -set g_balance_campingrifle_primary_bulletconstant 130 // 56.3qu -set g_balance_campingrifle_primary_burstcost 0 // require same cooldown as secondary, note it's smaller than primary refire time -set g_balance_campingrifle_primary_bullethail 0 // empty magazine on shot -set g_balance_campingrifle_secondary 1 -set g_balance_campingrifle_secondary_tracer 0 -set g_balance_campingrifle_secondary_damage 40 -set g_balance_campingrifle_secondary_headshotaddeddamage 20 -set g_balance_campingrifle_secondary_spread 0.008 -set g_balance_campingrifle_secondary_force 1 -set g_balance_campingrifle_secondary_speed 20000 -set g_balance_campingrifle_secondary_lifetime 5 -set g_balance_campingrifle_secondary_refire 0.0006 -set g_balance_campingrifle_secondary_animtime 0.1 -set g_balance_campingrifle_secondary_ammo 10 -set g_balance_campingrifle_secondary_bulletconstant 130 // 18.3qu -set g_balance_campingrifle_secondary_burstcost 0 -set g_balance_campingrifle_secondary_bullethail 0 -// }}} -// {{{ tuba -set g_balance_tuba_refire 0.05 -set g_balance_tuba_animtime 0.05 -set g_balance_tuba_attenuation 0.5 -set g_balance_tuba_volume 1 -set g_balance_tuba_fadetime 0.25 -set g_balance_tuba_damage 5 -set g_balance_tuba_edgedamage 0 -set g_balance_tuba_radius 200 -set g_balance_tuba_force 40 -// }}} -// {{{ fireball -set g_balance_fireball_primary_ammo 5 -set g_balance_fireball_primary_animtime 0.3 -set g_balance_fireball_primary_bfgdamage 0 -set g_balance_fireball_primary_bfgforce 0 -set g_balance_fireball_primary_bfgradius 0 -set g_balance_fireball_primary_damage 40 -set g_balance_fireball_primary_damageforcescale 4 -set g_balance_fireball_primary_edgedamage 0 -set g_balance_fireball_primary_force 100 -set g_balance_fireball_primary_health 9999 -set g_balance_fireball_primary_laserburntime 0.5 -set g_balance_fireball_primary_laserdamage 30 -set g_balance_fireball_primary_laseredgedamage 20 -set g_balance_fireball_primary_laserradius 110 -set g_balance_fireball_primary_lifetime 7 -set g_balance_fireball_primary_radius 20 -set g_balance_fireball_primary_refire 2 -set g_balance_fireball_primary_refire2 1.5 -set g_balance_fireball_primary_speed 900 -set g_balance_fireball_primary_spread 0 -set g_balance_fireball_secondary_ammo 25 -set g_balance_fireball_secondary_animtime 0.15 -set g_balance_fireball_secondary_damage 150 -set g_balance_fireball_secondary_damageforcescale 4 -set g_balance_fireball_secondary_damagetime 3 -set g_balance_fireball_secondary_force 700 -set g_balance_fireball_secondary_laserburntime 0.5 -set g_balance_fireball_secondary_laserdamage 30 -set g_balance_fireball_secondary_laseredgedamage 20 -set g_balance_fireball_secondary_laserradius 256 -set g_balance_fireball_secondary_lifetime 15 -set g_balance_fireball_secondary_refire 0 -set g_balance_fireball_secondary_speed 650 -set g_balance_fireball_secondary_speed_up 0 -set g_balance_fireball_secondary_speed_z 0 -set g_balance_fireball_secondary_spread 0 -// }}} -// {{{ seeker -set g_balance_seeker_flac_ammo 0.5 -set g_balance_seeker_flac_animtime 0.1 -set g_balance_seeker_flac_damage 15 -set g_balance_seeker_flac_edgedamage 10 -set g_balance_seeker_flac_force 50 -set g_balance_seeker_flac_lifetime 0.1 -set g_balance_seeker_flac_lifetime_rand 0.05 -set g_balance_seeker_flac_radius 100 -set g_balance_seeker_flac_refire 0.1 -set g_balance_seeker_flac_speed 3000 -set g_balance_seeker_flac_speed_up 1000 -set g_balance_seeker_flac_speed_z 0 -set g_balance_seeker_flac_spread 0.4 -set g_balance_seeker_missile_accel 3000 -set g_balance_seeker_missile_ammo 2 -set g_balance_seeker_missile_animtime 0.3 -set g_balance_seeker_missile_count 8 -set g_balance_seeker_missile_damage 25 -set g_balance_seeker_missile_damageforcescale 4 -set g_balance_seeker_missile_decel 6000 -set g_balance_seeker_missile_delay 0.25 -set g_balance_seeker_missile_edgedamage 10 -set g_balance_seeker_missile_force 250 -set g_balance_seeker_missile_health 5 -set g_balance_seeker_missile_lifetime 15 -set g_balance_seeker_missile_proxy 0 -set g_balance_seeker_missile_proxy_delay 0.2 -set g_balance_seeker_missile_proxy_maxrange 45 -set g_balance_seeker_missile_radius 80 -set g_balance_seeker_missile_refire 0.5 -set g_balance_seeker_missile_smart 1 -set g_balance_seeker_missile_smart_mindist 800 -set g_balance_seeker_missile_smart_trace_max 2500 -set g_balance_seeker_missile_smart_trace_min 1000 -set g_balance_seeker_missile_speed 700 -set g_balance_seeker_missile_speed_up 300 -set g_balance_seeker_missile_speed_z 0 -set g_balance_seeker_missile_speed_max 1250 -set g_balance_seeker_missile_spread 0 -set g_balance_seeker_missile_turnrate 0.65 -set g_balance_seeker_tag_ammo 1 -set g_balance_seeker_tag_animtime 0.3 -set g_balance_seeker_tag_damageforcescale 4 -set g_balance_seeker_tag_health 5 -set g_balance_seeker_tag_lifetime 15 -set g_balance_seeker_tag_refire 0.7 -set g_balance_seeker_tag_speed 9000 -set g_balance_seeker_tag_spread 0 -// End new seeker diff --git a/balanceSamual.cfg b/balanceSamual.cfg deleted file mode 100644 index d7e64bb4f2..0000000000 --- a/balanceSamual.cfg +++ /dev/null @@ -1,734 +0,0 @@ -// {{{ starting gear -set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_minelayer -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_hlac -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_campingrifle -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_seeker -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_balance_health_start 125 -set g_balance_armor_start 0 -set g_start_ammo_shells 15 -set g_start_ammo_nails 0 -set g_start_ammo_rockets 0 -set g_start_ammo_cells 0 -set g_start_ammo_fuel 0 -set g_warmup_start_health 200 "starting values when being in warmup-stage" -set g_warmup_start_armor 100 "starting values when being in warmup-stage" -set g_warmup_start_ammo_shells 50 "starting values when being in warmup-stage" -set g_warmup_start_ammo_nails 150 "starting values when being in warmup-stage" -set g_warmup_start_ammo_rockets 50 "starting values when being in warmup-stage" -set g_warmup_start_ammo_cells 50 "starting values when being in warmup-stage" -set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage" -set g_lms_start_health 200 -set g_lms_start_armor 200 -set g_lms_start_ammo_shells 120 -set g_lms_start_ammo_nails 400 -set g_lms_start_ammo_rockets 120 -set g_lms_start_ammo_cells 200 -set g_lms_start_ammo_fuel 0 -set g_balance_nix_roundtime 25 -set g_balance_nix_incrtime 1.6 -set g_balance_nix_ammo_shells 120 -set g_balance_nix_ammo_nails 400 -set g_balance_nix_ammo_rockets 120 -set g_balance_nix_ammo_cells 200 -set g_balance_nix_ammo_fuel 0 -set g_balance_nix_ammoincr_shells 2 -set g_balance_nix_ammoincr_nails 6 -set g_balance_nix_ammoincr_rockets 2 -set g_balance_nix_ammoincr_cells 2 -set g_balance_nix_ammoincr_fuel 2 -// }}} - -// {{{ pickup items -set g_pickup_ammo_anyway 1 -set g_pickup_weapons_anyway 1 -set g_pickup_shells 15 -set g_pickup_shells_weapon 15 -set g_pickup_shells_max 100 -set g_pickup_nails 75 -set g_pickup_nails_weapon 75 -set g_pickup_nails_max 300 -set g_pickup_rockets 40 -set g_pickup_rockets_weapon 40 -set g_pickup_rockets_max 160 -set g_pickup_cells 50 -set g_pickup_cells_weapon 50 -set g_pickup_cells_max 200 -set g_pickup_fuel 25 -set g_pickup_fuel_weapon 25 -set g_pickup_fuel_jetpack 50 -set g_pickup_fuel_max 100 -set g_pickup_armorsmall 10 -set g_pickup_armorsmall_max 200 -set g_pickup_armorsmall_anyway 1 -set g_pickup_armormedium 25 -set g_pickup_armormedium_max 200 -set g_pickup_armormedium_anyway 1 -set g_pickup_armorbig 50 -set g_pickup_armorbig_max 200 -set g_pickup_armorbig_anyway 1 -set g_pickup_armorlarge 100 -set g_pickup_armorlarge_max 200 -set g_pickup_armorlarge_anyway 1 -set g_pickup_healthsmall 10 -set g_pickup_healthsmall_max 200 -set g_pickup_healthsmall_anyway 1 -set g_pickup_healthmedium 25 -set g_pickup_healthmedium_max 200 -set g_pickup_healthmedium_anyway 1 -set g_pickup_healthlarge 50 -set g_pickup_healthlarge_max 200 -set g_pickup_healthlarge_anyway 1 -set g_pickup_healthmega 100 -set g_pickup_healthmega_max 200 -set g_pickup_healthmega_anyway 1 -set g_pickup_respawntime_short 15 -set g_pickup_respawntime_medium 20 -set g_pickup_respawntime_long 30 -set g_pickup_respawntime_powerup 120 -set g_pickup_respawntime_weapon 15 -set g_pickup_respawntime_ammo 15 -set g_pickup_respawntimejitter_short 0 -set g_pickup_respawntimejitter_medium 0 -set g_pickup_respawntimejitter_long 0 -set g_pickup_respawntimejitter_powerup 10 -set g_pickup_respawntimejitter_weapon 0 -set g_pickup_respawntimejitter_ammo 0 -// }}} - -// {{{ regen/rot -set g_balance_health_regen 0 -set g_balance_health_regenlinear 5 -set g_balance_pause_health_regen 5 -set g_balance_pause_health_regen_spawn 0 -set g_balance_health_rot 0 -set g_balance_health_rotlinear 5 -set g_balance_pause_health_rot 3 -set g_balance_pause_health_rot_spawn 1 -set g_balance_health_regenstable 100 -set g_balance_health_rotstable 100 -set g_balance_health_limit 999 -set g_balance_armor_regen 0 -set g_balance_armor_regenlinear 0 -set g_balance_armor_rot 0 -set g_balance_armor_rotlinear 3 -set g_balance_pause_armor_rot 1 -set g_balance_pause_armor_rot_spawn 1 -set g_balance_armor_regenstable 100 -set g_balance_armor_rotstable 100 -set g_balance_armor_limit 999 -set g_balance_armor_blockpercent 0.6 -set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)" -set g_balance_fuel_regenlinear 0 -set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter -set g_balance_fuel_rot 0.05 -set g_balance_fuel_rotlinear 0 -set g_balance_pause_fuel_rot 5 -set g_balance_pause_fuel_rot_spawn 10 -set g_balance_fuel_regenstable 50 -set g_balance_fuel_rotstable 100 -set g_balance_fuel_limit 999 -// }}} - -// {{{ misc -set g_balance_selfdamagepercent 0.75 -set g_balance_weaponswitchdelay 0.15 -set g_weaponspeedfactor 1 "weapon projectile speed multiplier" -set g_weaponratefactor 1 "weapon fire rate multiplier" -set g_weapondamagefactor 1 "weapon damage multiplier" -set g_weaponforcefactor 1 "weapon force multiplier" -set g_weaponspreadfactor 1 "weapon spread multiplier" -set g_balance_firetransfer_time 0.9 -set g_balance_firetransfer_damage 0.8 -set g_throughfloor_damage 0.4 -set g_throughfloor_force 0.7 -set g_projectiles_newton_style 2 -// possible values: -// 0: absolute velocity projectiles (like Quake) -// 1: relative velocity projectiles, "Newtonian" (like Tribes 2) -// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard) -// 3: absolute velocity + player velocity component in shot direction (note: does NOT yield the right relative velocity, but may be good enough, but it is somewhat prone to sniper rockets) -// 4: just add the player velocity length to the absolute velocity (tZork's sniper rockets) -set g_projectiles_newton_style_2_minfactor 0.8 -set g_projectiles_newton_style_2_maxfactor 1.5 -set g_projectiles_spread_style 0 -// possible values: -// 0: forward + solid sphere (like Quake) - varies velocity -// 1: forward + flattened solid sphere -// 2: forward + solid circle -// 3: forward + normal distribution 3D - varies velocity -// 4: forward + normal distribution on a plane -// 5: forward + circle with 1-r falloff -// 6: forward + circle with 1-r^2 falloff -// 7: forward + circle with (1-r)(2-r) falloff -set g_balance_falldamage_deadminspeed 150 -set g_balance_falldamage_minspeed 1400 -set g_balance_falldamage_factor 0.15 -set g_balance_falldamage_maxdamage 25 -// }}} - -// {{{ powerups -set g_balance_powerup_invincible_takedamage 0.2 -set g_balance_powerup_invincible_time 30 -set g_balance_powerup_strength_damage 3 -set g_balance_powerup_strength_force 3 -set g_balance_powerup_strength_time 30 -set g_balance_powerup_strength_selfdamage 1.5 -set g_balance_powerup_strength_selfforce 1.5 -// }}} - -// {{{ jetpack/hook -set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack" -set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction" -set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)" -set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction" -set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction" -set g_jetpack_fuel 8 "fuel per second for jetpack" -set g_jetpack_attenuation 2 "jetpack sound attenuation" - -set g_grappling_hook_tarzan 2 // 2: can also pull players -set g_balance_grapplehook_speed_fly 1800 -set g_balance_grapplehook_speed_pull 2000 -set g_balance_grapplehook_force_rubber 2000 -set g_balance_grapplehook_force_rubber_overstretch 1000 -set g_balance_grapplehook_length_min 50 -set g_balance_grapplehook_stretch 50 -set g_balance_grapplehook_airfriction 0.2 -set g_balance_grapplehook_health 130 -// }}} - -// {{{ weapon properties -// {{{ laser -set g_balance_laser_primary_damage 25 -set g_balance_laser_primary_edgedamage 10 -set g_balance_laser_primary_force 175 -set g_balance_laser_primary_radius 70 -set g_balance_laser_primary_speed 12000 -set g_balance_laser_primary_spread 0 -set g_balance_laser_primary_refire 0.7 -set g_balance_laser_primary_animtime 0.3 -set g_balance_laser_primary_lifetime 30 -set g_balance_laser_primary_shotangle 0 -set g_balance_laser_primary_delay 0.03 -set g_balance_laser_primary_gauntlet 0 -set g_balance_laser_primary_force_zscale 2 // 350 upforce -set g_balance_laser_primary_force_velocitybias 0.3 -set g_balance_laser_secondary 0 // when 1, a secondary laser mode exists -set g_balance_laser_secondary_damage 25 -set g_balance_laser_secondary_edgedamage 10 -set g_balance_laser_secondary_force 400 -set g_balance_laser_secondary_radius 70 -set g_balance_laser_secondary_speed 12000 -set g_balance_laser_secondary_spread 0 -set g_balance_laser_secondary_refire 0.7 -set g_balance_laser_secondary_animtime 0.3 -set g_balance_laser_secondary_lifetime 30 -set g_balance_laser_secondary_shotangle -90 -set g_balance_laser_secondary_delay 0 -set g_balance_laser_secondary_gauntlet 0 -set g_balance_laser_secondary_force_zscale 1.25 -set g_balance_laser_secondary_force_velocitybias 0 -// }}} -// {{{ shotgun -set g_balance_shotgun_primary_bullets 10 -set g_balance_shotgun_primary_damage 6 -set g_balance_shotgun_primary_force 15 -set g_balance_shotgun_primary_spread 0.11 -set g_balance_shotgun_primary_refire 0.5 -set g_balance_shotgun_primary_animtime 0.2 -set g_balance_shotgun_primary_ammo 1 -set g_balance_shotgun_primary_speed 8000 -set g_balance_shotgun_primary_bulletconstant 75 // 3.8qu -set g_balance_shotgun_secondary 1 -set g_balance_shotgun_secondary_melee_delay 0.35 // match the anim -set g_balance_shotgun_secondary_melee_range 60 -set g_balance_shotgun_secondary_melee_swing 50 -set g_balance_shotgun_secondary_melee_time 0.1 -set g_balance_shotgun_secondary_damage 115 -set g_balance_shotgun_secondary_force 150 -set g_balance_shotgun_secondary_refire 1.1 -set g_balance_shotgun_secondary_animtime 1 -// }}} -// {{{ uzi -set g_balance_uzi_mode 0 // Activates varible spread for sustained & burst mode secondary -set g_balance_uzi_spread_min 0.02 -set g_balance_uzi_spread_max 0.6 -set g_balance_uzi_spread_add 0.012 -set g_balance_uzi_burst 0 // # of bullets in a burst (if set to 2 or more) -set g_balance_uzi_burst_refire 0.05 // refire between burst bullets -set g_balance_uzi_burst_refire2 0.75 // refire after burst -set g_balance_uzi_burst_spread 0.04 -set g_balance_uzi_burst_damage 18 -set g_balance_uzi_burst_force 50 -set g_balance_uzi_burst_ammo 3 -set g_balance_uzi_first 1 -set g_balance_uzi_first_damage 18 -set g_balance_uzi_first_force 20 -set g_balance_uzi_first_spread 0.03 -set g_balance_uzi_first_refire 0.2 -set g_balance_uzi_first_ammo 1 -set g_balance_uzi_sustained_damage 10 -set g_balance_uzi_sustained_force 10 -set g_balance_uzi_sustained_spread 0.08 -set g_balance_uzi_sustained_refire 0.1 -set g_balance_uzi_sustained_ammo 1 -set g_balance_uzi_speed 18000 -set g_balance_uzi_bulletconstant 115 // 13.1qu -// }}} -// {{{ mortar -set g_balance_grenadelauncher_primary_type 0 -set g_balance_grenadelauncher_primary_damage 50 -set g_balance_grenadelauncher_primary_edgedamage 38 -set g_balance_grenadelauncher_primary_force 400 -set g_balance_grenadelauncher_primary_radius 140 -set g_balance_grenadelauncher_primary_speed 2000 -set g_balance_grenadelauncher_primary_speed_up 220 -set g_balance_grenadelauncher_primary_speed_z 0 -set g_balance_grenadelauncher_primary_spread 0 -set g_balance_grenadelauncher_primary_lifetime 30 -set g_balance_grenadelauncher_primary_lifetime2 1 -set g_balance_grenadelauncher_primary_refire 0.8 -set g_balance_grenadelauncher_primary_animtime 0.3 -set g_balance_grenadelauncher_primary_ammo 2 -set g_balance_grenadelauncher_primary_health 25 -set g_balance_grenadelauncher_primary_damageforcescale 4 -set g_balance_grenadelauncher_primary_remote_minbouncecnt 0 - -set g_balance_grenadelauncher_secondary_type 1 -set g_balance_grenadelauncher_secondary_damage 60 -set g_balance_grenadelauncher_secondary_edgedamage 38 -set g_balance_grenadelauncher_secondary_force 400 -set g_balance_grenadelauncher_secondary_radius 140 -set g_balance_grenadelauncher_secondary_speed 1400 -set g_balance_grenadelauncher_secondary_speed_up 150 -set g_balance_grenadelauncher_secondary_speed_z 0 -set g_balance_grenadelauncher_secondary_spread 0 -set g_balance_grenadelauncher_secondary_lifetime 1 -set g_balance_grenadelauncher_secondary_lifetime2 0 -set g_balance_grenadelauncher_secondary_refire 0.7 -set g_balance_grenadelauncher_secondary_animtime 0.3 -set g_balance_grenadelauncher_secondary_ammo 2 -set g_balance_grenadelauncher_secondary_health 70 -set g_balance_grenadelauncher_secondary_damageforcescale 4 -set g_balance_grenadelauncher_secondary_remote_detonateprimary 0 - -set g_balance_grenadelauncher_bouncefactor 0.5 -set g_balance_grenadelauncher_bouncestop 0.075 -// }}} -// {{{ minelayer // TODO -set g_balance_minelayer_damage 35 -set g_balance_minelayer_edgedamage 30 -set g_balance_minelayer_force 250 -set g_balance_minelayer_radius 175 -set g_balance_minelayer_proximityradius 150 -set g_balance_minelayer_speed 750 -set g_balance_minelayer_lifetime 60 -set g_balance_minelayer_refire 1.5 -set g_balance_minelayer_animtime 0.4 -set g_balance_minelayer_ammo 5 -set g_balance_minelayer_health 15 -set g_balance_minelayer_limit 4 // 0 disables the limit -set g_balance_minelayer_protection 1 // don't explode if the mine would hurt the owner or a team mate -set g_balance_minelayer_damageforcescale 0 -set g_balance_minelayer_detonatedelay -1 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time -set g_balance_minelayer_time 0.5 -set g_balance_minelayer_remote_damage 45 -set g_balance_minelayer_remote_edgedamage 40 -set g_balance_minelayer_remote_radius 200 -set g_balance_minelayer_remote_force 300 -// }}} -// {{{ electro // TODO -set g_balance_electro_lightning 1 -set g_balance_electro_primary_damage 90 -set g_balance_electro_primary_edgedamage 0 -set g_balance_electro_primary_force 425 -set g_balance_electro_primary_force_up 125 -set g_balance_electro_primary_radius 850 -set g_balance_electro_primary_comboradius 75 -set g_balance_electro_primary_speed 0 -set g_balance_electro_primary_spread 0 -set g_balance_electro_primary_lifetime 0 -set g_balance_electro_primary_refire 0.6 -set g_balance_electro_primary_animtime 0.03 -set g_balance_electro_primary_ammo 7 -set g_balance_electro_primary_range 800 -set g_balance_electro_primary_falloff_mindist 255 // 0.3 * radius -set g_balance_electro_primary_falloff_maxdist 850 -set g_balance_electro_primary_falloff_halflifedist 425 -set g_balance_electro_secondary_damage 25 -set g_balance_electro_secondary_edgedamage 0 -set g_balance_electro_secondary_force 100 -set g_balance_electro_secondary_radius 100 -set g_balance_electro_secondary_speed 900 -set g_balance_electro_secondary_speed_up 200 -set g_balance_electro_secondary_speed_z 0 -set g_balance_electro_secondary_spread 0.08 -set g_balance_electro_secondary_lifetime 2.5 -set g_balance_electro_secondary_refire 0.2 -set g_balance_electro_secondary_refire2 1 -set g_balance_electro_secondary_animtime 0.2 -set g_balance_electro_secondary_ammo 2 -set g_balance_electro_secondary_health 5 -set g_balance_electro_secondary_damageforcescale 4 -set g_balance_electro_secondary_count 3 -set g_balance_electro_secondary_bouncefactor 0.5 -set g_balance_electro_secondary_bouncestop 0.075 -set g_balance_electro_combo_damage 50 -set g_balance_electro_combo_edgedamage 0 -set g_balance_electro_combo_force 200 -set g_balance_electro_combo_radius 250 -set g_balance_electro_combo_comboradius 0 -set g_balance_electro_combo_speed 400 -// }}} -// {{{ crylink -set g_balance_crylink_primary_damage 10 -set g_balance_crylink_primary_edgedamage 0 -set g_balance_crylink_primary_force -55 -set g_balance_crylink_primary_radius 50 -set g_balance_crylink_primary_speed 3000 -set g_balance_crylink_primary_spread 0.05 -set g_balance_crylink_primary_shots 4 -set g_balance_crylink_primary_bounces 1 -set g_balance_crylink_primary_refire 0.4 -set g_balance_crylink_primary_animtime 0.3 -set g_balance_crylink_primary_ammo 2 -set g_balance_crylink_primary_bouncedamagefactor 0.5 -set g_balance_crylink_primary_joinspread 0 -set g_balance_crylink_primary_jointime 0 -set g_balance_crylink_primary_joinexplode 0 -set g_balance_crylink_primary_joinexplode_damage 0 -set g_balance_crylink_primary_joinexplode_edgedamage 0 -set g_balance_crylink_primary_joinexplode_radius 0 -set g_balance_crylink_primary_joinexplode_force 0 -set g_balance_crylink_primary_linkexplode 1 - -set g_balance_crylink_primary_middle_lifetime 5 // range: 35000 full, fades to 70000 -set g_balance_crylink_primary_middle_fadetime 5 -set g_balance_crylink_primary_other_lifetime 5 -set g_balance_crylink_primary_other_fadetime 5 - -set g_balance_crylink_secondary 1 -set g_balance_crylink_secondary_damage 8 -set g_balance_crylink_secondary_edgedamage 0 -set g_balance_crylink_secondary_force -40 -set g_balance_crylink_secondary_radius 10 -set g_balance_crylink_secondary_speed 9000 -set g_balance_crylink_secondary_spread 0.03 -set g_balance_crylink_secondary_shots 3 -set g_balance_crylink_secondary_bounces 0 -set g_balance_crylink_secondary_refire 0.2 -set g_balance_crylink_secondary_animtime 0.2 -set g_balance_crylink_secondary_ammo 2 -set g_balance_crylink_secondary_bouncedamagefactor 0.5 -set g_balance_crylink_secondary_joinspread 0 -set g_balance_crylink_secondary_jointime 0 -set g_balance_crylink_secondary_joinexplode 0 -set g_balance_crylink_secondary_joinexplode_damage 0 -set g_balance_crylink_secondary_joinexplode_edgedamage 0 -set g_balance_crylink_secondary_joinexplode_radius 0 -set g_balance_crylink_secondary_joinexplode_force 0 -set g_balance_crylink_secondary_linkexplode 1 - -set g_balance_crylink_secondary_middle_lifetime 5 // range: 35000 full, fades to 70000 -set g_balance_crylink_secondary_middle_fadetime 5 -set g_balance_crylink_secondary_line_lifetime 5 -set g_balance_crylink_secondary_line_fadetime 5 -// }}} -// {{{ nex -set g_balance_nex_primary_damage 90 -set g_balance_nex_primary_force 400 -set g_balance_nex_primary_refire 1.5 -set g_balance_nex_primary_animtime 0.3 -set g_balance_nex_primary_ammo 5 -set g_balance_nex_primary_damagefalloff_mindist 1000 -set g_balance_nex_primary_damagefalloff_maxdist 3000 -set g_balance_nex_primary_damagefalloff_halflife 1500 -set g_balance_nex_primary_damagefalloff_forcehalflife 1500 - -set g_balance_nex_secondary 0 -set g_balance_nex_secondary_charge 0 -set g_balance_nex_secondary_charge_rate 0.1 -set g_balance_nex_secondary_chargepool 0 -set g_balance_nex_secondary_chargepool_regen 0.15 -set g_balance_nex_secondary_chargepool_pause_regen 1 -set g_balance_nex_secondary_chargepool_pause_health_regen 1 -set g_balance_nex_secondary_damage 0 -set g_balance_nex_secondary_force 0 -set g_balance_nex_secondary_refire 0 -set g_balance_nex_secondary_animtime 0 -set g_balance_nex_secondary_ammo 2 -set g_balance_nex_secondary_damagefalloff_mindist 0 -set g_balance_nex_secondary_damagefalloff_maxdist 0 -set g_balance_nex_secondary_damagefalloff_halflife 0 -set g_balance_nex_secondary_damagefalloff_forcehalflife 0 - -set g_balance_nex_charge 1 -set g_balance_nex_charge_mindmg 40 -set g_balance_nex_charge_start 0 -set g_balance_nex_charge_rate 0.1 -set g_balance_nex_charge_limit 0.5 -set g_balance_nex_charge_rot_rate 0 -set g_balance_nex_charge_rot_pause 0 // Dont rot down untill this long after release of charge button -set g_balance_nex_charge_shot_multiplier 0.25 -set g_balance_nex_charge_velocity_rate 0.2 -set g_balance_nex_charge_minspeed 400 -set g_balance_nex_charge_maxspeed 1000 -// }}} -// {{{ minstanex -set g_balance_minstanex_refire 1 -set g_balance_minstanex_animtime 0.3 -set g_balance_minstanex_ammo 10 -// }}} -// {{{ hagar -set g_balance_hagar_primary_damage 30 -set g_balance_hagar_primary_edgedamage 0 -set g_balance_hagar_primary_force 50 -set g_balance_hagar_primary_radius 70 -set g_balance_hagar_primary_spread 0.08 -set g_balance_hagar_primary_speed 2000 -set g_balance_hagar_primary_lifetime 0.12 -set g_balance_hagar_primary_refire 0.15 -set g_balance_hagar_primary_ammo 1 -set g_balance_hagar_secondary 1 -set g_balance_hagar_secondary_damage 37 -set g_balance_hagar_secondary_edgedamage 15 -set g_balance_hagar_secondary_force 100 -set g_balance_hagar_secondary_radius 65 -set g_balance_hagar_secondary_spread 0.015 -set g_balance_hagar_secondary_speed 2000 -set g_balance_hagar_secondary_lifetime_min 30 -set g_balance_hagar_secondary_lifetime_rand 0 -set g_balance_hagar_secondary_refire 0.15 -set g_balance_hagar_secondary_ammo 1 -// }}} -// {{{ rocketlauncher -set g_balance_rocketlauncher_damage 80 -set g_balance_rocketlauncher_edgedamage 40 -set g_balance_rocketlauncher_force 600 -set g_balance_rocketlauncher_radius 100 -set g_balance_rocketlauncher_speed 1600 -set g_balance_rocketlauncher_speedaccel 1600 -set g_balance_rocketlauncher_speedstart 800 -set g_balance_rocketlauncher_lifetime 30 -set g_balance_rocketlauncher_refire 1.2 -set g_balance_rocketlauncher_animtime 0.3 -set g_balance_rocketlauncher_ammo 3 -set g_balance_rocketlauncher_health 40 -set g_balance_rocketlauncher_damageforcescale 4 -set g_balance_rocketlauncher_detonatedelay 0.05 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time -set g_balance_rocketlauncher_guiderate 140 // max degrees per second -set g_balance_rocketlauncher_guideratedelay 0.01 // immediate -set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic) -set g_balance_rocketlauncher_guidedelay 0.15 // delay before guiding kicks in -set g_balance_rocketlauncher_guidestop 0 // stop guiding when firing again -set g_balance_rocketlauncher_remote_damage 70 -set g_balance_rocketlauncher_remote_edgedamage 30 -set g_balance_rocketlauncher_remote_radius 100 -set g_balance_rocketlauncher_remote_force 500 -// }}} -// {{{ porto -set g_balance_porto_primary_refire 1.5 -set g_balance_porto_primary_animtime 0.3 -set g_balance_porto_primary_speed 5000 -set g_balance_porto_primary_lifetime 5 -set g_balance_portal_health 200 // these get recharged whenever the portal is used -set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used -// }}} -// {{{ hook -set g_balance_hook_primary_fuel 5 // hook monkeys set 0 -set g_balance_hook_primary_refire 0 // hook monkeys set 0 -set g_balance_hook_primary_animtime 0.3 // good shoot anim -set g_balance_hook_primary_hooked_time_max 0 // infinite -set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free -set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked -set g_balance_hook_secondary_damage 25 // not much -set g_balance_hook_secondary_edgedamage 5 // not much -set g_balance_hook_secondary_radius 500 // LOTS -set g_balance_hook_secondary_force -2000 // LOTS -set g_balance_hook_secondary_ammo 50 // a whole pack -set g_balance_hook_secondary_lifetime 5 // infinite -set g_balance_hook_secondary_speed 0 // not much throwing -set g_balance_hook_secondary_gravity 5 // fast falling -set g_balance_hook_secondary_refire 3 // don't drop too many bombs... -set g_balance_hook_secondary_animtime 0.3 // good shoot anim -set g_balance_hook_secondary_power 3 // effect behaves like a square function -set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds -// }}} -// {{{ hlac -set g_balance_hlac_primary_spread_min 0.01 -set g_balance_hlac_primary_spread_max 0.25 -set g_balance_hlac_primary_spread_add 0.0045 -set g_balance_hlac_primary_spread_crouchmod 0.25 - -set g_balance_hlac_primary_damage 23 -set g_balance_hlac_primary_edgedamage 10 -set g_balance_hlac_primary_force 100 -set g_balance_hlac_primary_radius 70 -set g_balance_hlac_primary_speed 9000 -set g_balance_hlac_primary_lifetime 5 - -set g_balance_hlac_primary_refire 0.1 -set g_balance_hlac_primary_animtime 0.4 -set g_balance_hlac_primary_ammo 1 - -set g_balance_hlac_secondary 1 -set g_balance_hlac_secondary_spread 0.15 -set g_balance_hlac_secondary_spread_crouchmod 0.5 - -set g_balance_hlac_secondary_damage 23 -set g_balance_hlac_secondary_edgedamage 10 -set g_balance_hlac_secondary_force 100 -set g_balance_hlac_secondary_radius 70 -set g_balance_hlac_secondary_speed 9000 -set g_balance_hlac_secondary_lifetime 5 - -set g_balance_hlac_secondary_refire 1 -set g_balance_hlac_secondary_animtime 0.3 -set g_balance_hlac_secondary_ammo 10 -set g_balance_hlac_secondary_shots 6 -// }}} -// {{{ campingrifle -set g_balance_campingrifle_magazinecapacity 8 // make it pretty much useless in close combat -set g_balance_campingrifle_reloadtime 2 // matches reload anim -set g_balance_campingrifle_auto_reload_on_switch 0 -set g_balance_campingrifle_bursttime 0 -set g_balance_campingrifle_primary_tracer 1 -set g_balance_campingrifle_primary_damage 65 -set g_balance_campingrifle_primary_headshotaddeddamage 75 -set g_balance_campingrifle_primary_spread 0 -set g_balance_campingrifle_primary_force 2 -set g_balance_campingrifle_primary_speed 40000 -set g_balance_campingrifle_primary_lifetime 5 -set g_balance_campingrifle_primary_refire 0.75 -set g_balance_campingrifle_primary_animtime 0.3 -set g_balance_campingrifle_primary_ammo 10 -set g_balance_campingrifle_primary_bulletconstant 110 // 62.2qu -set g_balance_campingrifle_primary_burstcost 0 -set g_balance_campingrifle_primary_bullethail 0 // empty magazine on shot -set g_balance_campingrifle_secondary 1 -set g_balance_campingrifle_secondary_tracer 0 -set g_balance_campingrifle_secondary_damage 50 -set g_balance_campingrifle_secondary_headshotaddeddamage 50 // 50 damage only on head -set g_balance_campingrifle_secondary_spread 0 -set g_balance_campingrifle_secondary_force 2 -set g_balance_campingrifle_secondary_speed 20000 -set g_balance_campingrifle_secondary_lifetime 5 -set g_balance_campingrifle_secondary_refire 0.1 -set g_balance_campingrifle_secondary_animtime 0.1 -set g_balance_campingrifle_secondary_ammo 10 -set g_balance_campingrifle_secondary_bulletconstant 110 // 15.5qu -set g_balance_campingrifle_secondary_burstcost 0 -set g_balance_campingrifle_secondary_bullethail 0 // empty magazine on shot -// }}} -// {{{ tuba -set g_balance_tuba_refire 0.05 -set g_balance_tuba_animtime 0.05 -set g_balance_tuba_attenuation 0.5 -set g_balance_tuba_volume 1 -set g_balance_tuba_fadetime 0.25 -set g_balance_tuba_damage 5 -set g_balance_tuba_edgedamage 0 -set g_balance_tuba_radius 200 -set g_balance_tuba_force 40 -// }}} -// {{{ fireball -set g_balance_fireball_primary_ammo 40 -set g_balance_fireball_primary_animtime 0.15 -set g_balance_fireball_primary_bfgdamage 100 -set g_balance_fireball_primary_bfgforce 0 -set g_balance_fireball_primary_bfgradius 1000 -set g_balance_fireball_primary_damage 200 -set g_balance_fireball_primary_damageforcescale 4 -set g_balance_fireball_primary_edgedamage 0 -set g_balance_fireball_primary_force 700 -set g_balance_fireball_primary_health 50 -set g_balance_fireball_primary_laserburntime 0.5 -set g_balance_fireball_primary_laserdamage 80 -set g_balance_fireball_primary_laseredgedamage 20 -set g_balance_fireball_primary_laserradius 256 -set g_balance_fireball_primary_lifetime 15 -set g_balance_fireball_primary_radius 200 -set g_balance_fireball_primary_refire 5 -set g_balance_fireball_primary_refire2 0 -set g_balance_fireball_primary_speed 650 -set g_balance_fireball_primary_spread 0 -set g_balance_fireball_secondary_ammo 5 -set g_balance_fireball_secondary_animtime 0.3 -set g_balance_fireball_secondary_damage 40 -set g_balance_fireball_secondary_damageforcescale 4 -set g_balance_fireball_secondary_damagetime 5 -set g_balance_fireball_secondary_force 100 -set g_balance_fireball_secondary_laserburntime 0.5 -set g_balance_fireball_secondary_laserdamage 50 -set g_balance_fireball_secondary_laseredgedamage 20 -set g_balance_fireball_secondary_laserradius 110 -set g_balance_fireball_secondary_lifetime 7 -set g_balance_fireball_secondary_refire 2 -set g_balance_fireball_secondary_speed 900 -set g_balance_fireball_secondary_speed_up 100 -set g_balance_fireball_secondary_speed_z 0 -set g_balance_fireball_secondary_spread 0 -// }}} -// {{{ seeker -set g_balance_seeker_flac_ammo 0.5 -set g_balance_seeker_flac_animtime 0.1 -set g_balance_seeker_flac_damage 15 -set g_balance_seeker_flac_edgedamage 10 -set g_balance_seeker_flac_force 50 -set g_balance_seeker_flac_lifetime 0.1 -set g_balance_seeker_flac_lifetime_rand 0.05 -set g_balance_seeker_flac_radius 100 -set g_balance_seeker_flac_refire 0.1 -set g_balance_seeker_flac_speed 3000 -set g_balance_seeker_flac_speed_up 1000 -set g_balance_seeker_flac_speed_z 0 -set g_balance_seeker_flac_spread 0.4 -set g_balance_seeker_missile_accel 3000 -set g_balance_seeker_missile_ammo 2 -set g_balance_seeker_missile_animtime 0.3 -set g_balance_seeker_missile_count 4 -set g_balance_seeker_missile_damage 40 -set g_balance_seeker_missile_damageforcescale 4 -set g_balance_seeker_missile_decel 6000 -set g_balance_seeker_missile_delay 0.25 -set g_balance_seeker_missile_edgedamage 10 -set g_balance_seeker_missile_force 250 -set g_balance_seeker_missile_health 5 -set g_balance_seeker_missile_lifetime 15 -set g_balance_seeker_missile_proxy 0 -set g_balance_seeker_missile_proxy_delay 0.2 -set g_balance_seeker_missile_proxy_maxrange 45 -set g_balance_seeker_missile_radius 80 -set g_balance_seeker_missile_refire 0.5 -set g_balance_seeker_missile_smart 1 -set g_balance_seeker_missile_smart_mindist 800 -set g_balance_seeker_missile_smart_trace_max 2500 -set g_balance_seeker_missile_smart_trace_min 1000 -set g_balance_seeker_missile_speed 700 -set g_balance_seeker_missile_speed_up 300 -set g_balance_seeker_missile_speed_z 0 -set g_balance_seeker_missile_speed_max 1250 -set g_balance_seeker_missile_spread 0 -set g_balance_seeker_missile_turnrate 0.65 -set g_balance_seeker_tag_ammo 1 -set g_balance_seeker_tag_animtime 0.3 -set g_balance_seeker_tag_damageforcescale 4 -set g_balance_seeker_tag_health 5 -set g_balance_seeker_tag_lifetime 15 -set g_balance_seeker_tag_refire 0.7 -set g_balance_seeker_tag_speed 9000 -set g_balance_seeker_tag_spread 0 -// End new seeker diff --git a/balanceXPM.cfg b/balanceXPM.cfg new file mode 100644 index 0000000000..a866d75245 --- /dev/null +++ b/balanceXPM.cfg @@ -0,0 +1,828 @@ +// {{{ starting gear +set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_minelayer -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" // UNTIL IT CAN BE REMOVED FROM CODE +set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_hlac -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" // UNTIL IT CAN BE REMOVED FROM CODE +set g_start_weapon_rifle -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" // UNTIL IT CAN BE REMOVED FROM CODE +set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_seeker -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_balance_health_start 100 +set g_balance_armor_start 0 +set g_start_ammo_shells 15 +set g_start_ammo_nails 0 +set g_start_ammo_rockets 0 +set g_start_ammo_cells 0 +set g_start_ammo_fuel 0 +set g_warmup_start_health 100 "starting values when being in warmup-stage" +set g_warmup_start_armor 100 "starting values when being in warmup-stage" +set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage" +set g_warmup_start_ammo_nails 160 "starting values when being in warmup-stage" +set g_warmup_start_ammo_rockets 80 "starting values when being in warmup-stage" +set g_warmup_start_ammo_cells 90 "starting values when being in warmup-stage" +set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage" +set g_lms_start_health 200 +set g_lms_start_armor 200 +set g_lms_start_ammo_shells 60 +set g_lms_start_ammo_nails 320 +set g_lms_start_ammo_rockets 160 +set g_lms_start_ammo_cells 180 +set g_lms_start_ammo_fuel 0 +set g_balance_nix_roundtime 25 +set g_balance_nix_incrtime 1.6 +set g_balance_nix_ammo_shells 60 +set g_balance_nix_ammo_nails 320 +set g_balance_nix_ammo_rockets 160 +set g_balance_nix_ammo_cells 180 +set g_balance_nix_ammo_fuel 0 +set g_balance_nix_ammoincr_shells 2 // eh this will need figured out later I assume +set g_balance_nix_ammoincr_nails 6 +set g_balance_nix_ammoincr_rockets 2 +set g_balance_nix_ammoincr_cells 2 +set g_balance_nix_ammoincr_fuel 2 +// }}} + +// {{{ pickup items +set g_pickup_ammo_anyway 1 +set g_pickup_weapons_anyway 1 +set g_pickup_shells 15 +set g_pickup_shells_weapon 15 +set g_pickup_shells_max 60 +set g_pickup_nails 80 +set g_pickup_nails_weapon 80 +set g_pickup_nails_max 320 +set g_pickup_rockets 40 +set g_pickup_rockets_weapon 40 +set g_pickup_rockets_max 160 +set g_pickup_cells 30 +set g_pickup_cells_weapon 30 +set g_pickup_cells_max 180 +set g_pickup_fuel 50 +set g_pickup_fuel_weapon 50 +set g_pickup_fuel_jetpack 100 +set g_pickup_fuel_max 100 +set g_pickup_armorsmall 5 +set g_pickup_armorsmall_max 200 +set g_pickup_armorsmall_anyway 1 +set g_pickup_armormedium 25 +set g_pickup_armormedium_max 200 +set g_pickup_armormedium_anyway 1 +set g_pickup_armorbig 50 +set g_pickup_armorbig_max 200 +set g_pickup_armorbig_anyway 1 +set g_pickup_armorlarge 100 +set g_pickup_armorlarge_max 200 +set g_pickup_armorlarge_anyway 1 +set g_pickup_healthsmall 5 +set g_pickup_healthsmall_max 200 +set g_pickup_healthsmall_anyway 1 +set g_pickup_healthmedium 25 +set g_pickup_healthmedium_max 200 +set g_pickup_healthmedium_anyway 1 +set g_pickup_healthlarge 50 +set g_pickup_healthlarge_max 200 +set g_pickup_healthlarge_anyway 1 +set g_pickup_healthmega 100 +set g_pickup_healthmega_max 200 +set g_pickup_healthmega_anyway 1 +set g_pickup_respawntime_short 15 +set g_pickup_respawntime_medium 20 +set g_pickup_respawntime_long 30 +set g_pickup_respawntime_powerup 120 +set g_pickup_respawntime_weapon 10 +set g_pickup_respawntime_ammo 15 +set g_pickup_respawntimejitter_short 0 +set g_pickup_respawntimejitter_medium 0 +set g_pickup_respawntimejitter_long 0 +set g_pickup_respawntimejitter_powerup 30 +set g_pickup_respawntimejitter_weapon 0 +set g_pickup_respawntimejitter_ammo 0 +// }}} + +// {{{ regen/rot +set g_balance_health_regen 0.08 +set g_balance_health_regenlinear 0.5 +set g_balance_pause_health_regen 5 +set g_balance_pause_health_regen_spawn 0 +set g_balance_health_rot 0.04 +set g_balance_health_rotlinear 0.75 +set g_balance_pause_health_rot 1 +set g_balance_pause_health_rot_spawn 5 +set g_balance_health_regenstable 100 +set g_balance_health_rotstable 100 +set g_balance_health_limit 999 +set g_balance_armor_regen 0 +set g_balance_armor_regenlinear 0 +set g_balance_armor_rot 0.04 +set g_balance_armor_rotlinear 0.75 +set g_balance_pause_armor_rot 1 +set g_balance_pause_armor_rot_spawn 5 +set g_balance_armor_regenstable 100 +set g_balance_armor_rotstable 100 +set g_balance_armor_limit 999 +set g_balance_armor_blockpercent 0.6 +set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)" +set g_balance_fuel_regenlinear 0 +set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter +set g_balance_fuel_rot 0.05 +set g_balance_fuel_rotlinear 0 +set g_balance_pause_fuel_rot 5 +set g_balance_pause_fuel_rot_spawn 10 +set g_balance_fuel_regenstable 50 +set g_balance_fuel_rotstable 100 +set g_balance_fuel_limit 999 +// }}} + +// {{{ misc +set g_balance_selfdamagepercent 0.65 +set g_balance_weaponswitchdelay 0.15 +set g_weaponspeedfactor 1 "weapon projectile speed multiplier" +set g_weaponratefactor 1 "weapon fire rate multiplier" +set g_weapondamagefactor 1 "weapon damage multiplier" +set g_weaponforcefactor 1 "weapon force multiplier" +set g_weaponspreadfactor 1 "weapon spread multiplier" +set g_balance_firetransfer_time 0.9 +set g_balance_firetransfer_damage 0.8 +set g_throughfloor_damage 0.75 +set g_throughfloor_force 0.75 +set g_projectiles_damage 1 +// possible values: +// -2: absolutely no damage to projectiles (no exceptions) +// -1: no damage other than the exceptions (electro combo, hagar join explode, minelayer mines) +// 0: only damage from contents (lava/slime) or exceptions +// 1: only self damage or damage from contents or exceptions +// 2: allow all damage to projectiles normally +set g_projectiles_newton_style 0 +// possible values: +// 0: absolute velocity projectiles (like Quake) +// 1: relative velocity projectiles, "Newtonian" (like Tribes 2) +// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard) +// 3: absolute velocity + player velocity component in shot direction (note: does NOT yield the right relative velocity, but may be good enough, but it is somewhat prone to sniper rockets) +// 4: just add the player velocity length to the absolute velocity (tZork's sniper rockets) +set g_projectiles_newton_style_2_minfactor 0.8 +set g_projectiles_newton_style_2_maxfactor 1.5 +set g_projectiles_spread_style 7 +// possible values: +// 0: forward + solid sphere (like Quake) - varies velocity +// 1: forward + flattened solid sphere +// 2: forward + solid circle +// 3: forward + normal distribution 3D - varies velocity +// 4: forward + normal distribution on a plane +// 5: forward + circle with 1-r falloff +// 6: forward + circle with 1-r^2 falloff +// 7: forward + circle with (1-r)(2-r) falloff +set g_balance_falldamage_deadminspeed 250 +set g_balance_falldamage_minspeed 900 +set g_balance_falldamage_factor 0.20 +set g_balance_falldamage_maxdamage 40 +set g_balance_damagepush_speedfactor 2.5 +set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage +set g_balance_contents_drowndelay 10 // time under water before a player begins drowning +set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning +set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava +set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime +set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime +set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap" +// }}} + +// {{{ powerups +set g_balance_powerup_invincible_takedamage 0.25 // only 1/4th damage is taken +set g_balance_powerup_invincible_time 30 +set g_balance_powerup_strength_damage 3 +set g_balance_powerup_strength_force 3 +set g_balance_powerup_strength_time 30 +set g_balance_powerup_strength_selfdamage 1.5 +set g_balance_powerup_strength_selfforce 1.5 +// }}} + +// {{{ jetpack/hook +set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack" +set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction" +set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)" +set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction" +set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction" +set g_jetpack_fuel 8 "fuel per second for jetpack" +set g_jetpack_attenuation 2 "jetpack sound attenuation" + +set g_grappling_hook_tarzan 2 // 2: can also pull players +set g_balance_grapplehook_speed_fly 1800 +set g_balance_grapplehook_speed_pull 2000 +set g_balance_grapplehook_force_rubber 2000 +set g_balance_grapplehook_force_rubber_overstretch 1000 +set g_balance_grapplehook_length_min 50 +set g_balance_grapplehook_stretch 50 +set g_balance_grapplehook_airfriction 0.2 +set g_balance_grapplehook_health 50 +set g_balance_grapplehook_damagedbycontents 1 +// }}} + +// {{{ weapon properties +// {{{ laser +set g_balance_laser_primary_damage 25 +set g_balance_laser_primary_edgedamage 12.5 +set g_balance_laser_primary_force 300 +set g_balance_laser_primary_radius 70 +set g_balance_laser_primary_speed 6000 +set g_balance_laser_primary_spread 0 +set g_balance_laser_primary_refire 0.7 +set g_balance_laser_primary_animtime 0.3 +set g_balance_laser_primary_lifetime 5 +set g_balance_laser_primary_shotangle 0 +set g_balance_laser_primary_delay 0 +set g_balance_laser_primary_gauntlet 0 +set g_balance_laser_primary_force_zscale 1.25 +set g_balance_laser_primary_force_velocitybias 0 +set g_balance_laser_primary_force_other_scale 1 +set g_balance_laser_secondary 0 // when 1, a secondary laser mode exists +set g_balance_laser_secondary_damage 25 +set g_balance_laser_secondary_edgedamage 12.5 +set g_balance_laser_secondary_force 400 +set g_balance_laser_secondary_radius 70 +set g_balance_laser_secondary_speed 12000 +set g_balance_laser_secondary_spread 0 +set g_balance_laser_secondary_refire 0.7 +set g_balance_laser_secondary_animtime 0.3 +set g_balance_laser_secondary_lifetime 5 +set g_balance_laser_secondary_shotangle -90 +set g_balance_laser_secondary_delay 0 +set g_balance_laser_secondary_gauntlet 0 +set g_balance_laser_secondary_force_zscale 1.25 +set g_balance_laser_secondary_force_velocitybias 0 +set g_balance_laser_secondary_force_other_scale 1 +set g_balance_laser_reload_ammo 0 //default: 6 +set g_balance_laser_reload_time 2 +// }}} +// {{{ shotgun +set g_balance_shotgun_primary_bullets 14 +set g_balance_shotgun_primary_damage 4 +set g_balance_shotgun_primary_force 15 +set g_balance_shotgun_primary_spread 0.12 +set g_balance_shotgun_primary_refire 0.75 +set g_balance_shotgun_primary_animtime 0.2 +set g_balance_shotgun_primary_ammo 1 +set g_balance_shotgun_primary_speed 8000 +set g_balance_shotgun_primary_bulletconstant 75 // 3.8qu +set g_balance_shotgun_secondary 1 +set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow +set g_balance_shotgun_secondary_melee_range 120 +set g_balance_shotgun_secondary_melee_swing_side 120 +set g_balance_shotgun_secondary_melee_swing_up 30 +set g_balance_shotgun_secondary_melee_time 0.15 +set g_balance_shotgun_secondary_melee_traces 10 +set g_balance_shotgun_secondary_melee_no_doubleslap 1 +set g_balance_shotgun_secondary_melee_nonplayerdamage 40 +set g_balance_shotgun_secondary_melee_multihit 1 +set g_balance_shotgun_secondary_damage 80 +set g_balance_shotgun_secondary_force 200 +set g_balance_shotgun_secondary_refire 1.25 +set g_balance_shotgun_secondary_animtime 1 +set g_balance_shotgun_reload_ammo 0 //default: 5 +set g_balance_shotgun_reload_time 2 +// }}} +// {{{ uzi +set g_balance_uzi_mode 1 // Activates varible spread for sustained & burst mode secondary +set g_balance_uzi_spread_min 0.02 +set g_balance_uzi_spread_max 0.05 +set g_balance_uzi_spread_add 0.012 + +set g_balance_uzi_burst 3 // # of bullets in a burst (if set to 2 or more) +set g_balance_uzi_burst_animtime 0.3 +set g_balance_uzi_burst_refire 0.06 // refire between burst bullets +set g_balance_uzi_burst_refire2 0.45 // refire after burst +set g_balance_uzi_burst_spread 0.02 +set g_balance_uzi_burst_damage 25 +set g_balance_uzi_burst_force 20 +set g_balance_uzi_burst_ammo 3 + +set g_balance_uzi_first 1 +set g_balance_uzi_first_damage 14 +set g_balance_uzi_first_headshotaddeddamage 0 +set g_balance_uzi_first_force 5 +set g_balance_uzi_first_spread 0.03 +set g_balance_uzi_first_refire 0.125 +set g_balance_uzi_first_ammo 1 + +set g_balance_uzi_sustained_damage 10 // 100 dps +set g_balance_uzi_sustained_headshotaddeddamage 0 +set g_balance_uzi_sustained_force 5 +set g_balance_uzi_sustained_spread 0.03 +set g_balance_uzi_sustained_refire 0.1 +set g_balance_uzi_sustained_ammo 1 + +set g_balance_uzi_speed 18000 +set g_balance_uzi_bulletconstant 115 // 13.1qu + +set g_balance_uzi_reload_ammo 60 //default: 30 +set g_balance_uzi_reload_time 2 +// }}} +// {{{ mortar +set g_balance_grenadelauncher_primary_type 0 +set g_balance_grenadelauncher_primary_damage 50 +set g_balance_grenadelauncher_primary_edgedamage 25 +set g_balance_grenadelauncher_primary_force 250 +set g_balance_grenadelauncher_primary_radius 120 +set g_balance_grenadelauncher_primary_speed 1900 +set g_balance_grenadelauncher_primary_speed_up 225 +set g_balance_grenadelauncher_primary_speed_z 0 +set g_balance_grenadelauncher_primary_spread 0 +set g_balance_grenadelauncher_primary_lifetime 5 +set g_balance_grenadelauncher_primary_lifetime2 1 +set g_balance_grenadelauncher_primary_refire 0.8 +set g_balance_grenadelauncher_primary_animtime 0.3 +set g_balance_grenadelauncher_primary_ammo 2 +set g_balance_grenadelauncher_primary_health 15 +set g_balance_grenadelauncher_primary_damageforcescale 0 +set g_balance_grenadelauncher_primary_remote_minbouncecnt 0 + +set g_balance_grenadelauncher_secondary_type 1 +set g_balance_grenadelauncher_secondary_damage 60 +set g_balance_grenadelauncher_secondary_edgedamage 30 +set g_balance_grenadelauncher_secondary_force 250 +set g_balance_grenadelauncher_secondary_radius 120 +set g_balance_grenadelauncher_secondary_speed 1400 +set g_balance_grenadelauncher_secondary_speed_up 150 +set g_balance_grenadelauncher_secondary_speed_z 0 +set g_balance_grenadelauncher_secondary_spread 0 +set g_balance_grenadelauncher_secondary_lifetime 5 +set g_balance_grenadelauncher_secondary_lifetime_bounce 0.5 +set g_balance_grenadelauncher_secondary_lifetime_stick 0 +set g_balance_grenadelauncher_secondary_refire 0.7 +set g_balance_grenadelauncher_secondary_animtime 0.3 +set g_balance_grenadelauncher_secondary_ammo 2 +set g_balance_grenadelauncher_secondary_health 30 +set g_balance_grenadelauncher_secondary_damageforcescale 4 +set g_balance_grenadelauncher_secondary_remote_detonateprimary 0 + +set g_balance_grenadelauncher_bouncefactor 0.5 +set g_balance_grenadelauncher_bouncestop 0.075 + +set g_balance_grenadelauncher_reload_ammo 0 //default: 12 +set g_balance_grenadelauncher_reload_time 2 +// }}} +// {{{ minelayer +set g_balance_minelayer_damage 40 +set g_balance_minelayer_edgedamage 20 +set g_balance_minelayer_force 250 +set g_balance_minelayer_radius 175 +set g_balance_minelayer_proximityradius 150 +set g_balance_minelayer_speed 1000 +set g_balance_minelayer_lifetime 10 +set g_balance_minelayer_lifetime_countdown 0.5 +set g_balance_minelayer_refire 1.5 +set g_balance_minelayer_animtime 0.4 +set g_balance_minelayer_ammo 4 +set g_balance_minelayer_health 15 +set g_balance_minelayer_limit 3 // 0 disables the limit +set g_balance_minelayer_protection 0 // don't explode if the mine would hurt the owner or a team mate +set g_balance_minelayer_damageforcescale 0 +set g_balance_minelayer_detonatedelay -1 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time +set g_balance_minelayer_time 0.5 +set g_balance_minelayer_remote_damage 45 +set g_balance_minelayer_remote_edgedamage 40 +set g_balance_minelayer_remote_radius 200 +set g_balance_minelayer_remote_force 300 +set g_balance_minelayer_reload_ammo 0 //default: 15 +set g_balance_minelayer_reload_time 2 +// }}} +// {{{ electro +set g_balance_electro_lightning 0 +set g_balance_electro_primary_damage 40 +set g_balance_electro_primary_edgedamage 20 +set g_balance_electro_primary_force 200 +set g_balance_electro_primary_force_up 0 +set g_balance_electro_primary_radius 100 +set g_balance_electro_primary_comboradius 150 +set g_balance_electro_primary_speed 2500 +set g_balance_electro_primary_spread 0 +set g_balance_electro_primary_lifetime 5 +set g_balance_electro_primary_refire 0.6 +set g_balance_electro_primary_animtime 0.1 +set g_balance_electro_primary_ammo 4 +set g_balance_electro_primary_range 0 +set g_balance_electro_primary_falloff_mindist 255 // 0.3 * radius +set g_balance_electro_primary_falloff_maxdist 850 +set g_balance_electro_primary_falloff_halflifedist 425 +set g_balance_electro_secondary_damage 40 +set g_balance_electro_secondary_edgedamage 20 +set g_balance_electro_secondary_force 50 +set g_balance_electro_secondary_radius 150 +set g_balance_electro_secondary_speed 900 +set g_balance_electro_secondary_speed_up 200 +set g_balance_electro_secondary_speed_z 0 +set g_balance_electro_secondary_spread 0.05 +set g_balance_electro_secondary_lifetime 3 +set g_balance_electro_secondary_refire 0.2 +set g_balance_electro_secondary_refire2 1.5 +set g_balance_electro_secondary_animtime 0.2 +set g_balance_electro_secondary_ammo 2 +set g_balance_electro_secondary_health 5 +set g_balance_electro_secondary_damageforcescale 4 +set g_balance_electro_secondary_damagedbycontents 1 +set g_balance_electro_secondary_count 3 +set g_balance_electro_secondary_bouncefactor 0.4 +set g_balance_electro_secondary_bouncestop 0.05 +set g_balance_electro_combo_damage 50 +set g_balance_electro_combo_edgedamage 25 +set g_balance_electro_combo_force 120 +set g_balance_electro_combo_radius 175 +set g_balance_electro_combo_comboradius 275 +set g_balance_electro_combo_speed 2000 +set g_balance_electro_combo_safeammocheck 0 +set g_balance_electro_reload_ammo 0 //default: 20 +set g_balance_electro_reload_time 2 +// }}} +// {{{ crylink +set g_balance_crylink_primary_damage 10 +set g_balance_crylink_primary_edgedamage 5 +set g_balance_crylink_primary_force -55 +set g_balance_crylink_primary_radius 80 +set g_balance_crylink_primary_speed 2000 +set g_balance_crylink_primary_spread 0.08 +set g_balance_crylink_primary_shots 6 +set g_balance_crylink_primary_bounces 1 +set g_balance_crylink_primary_refire 0.7 +set g_balance_crylink_primary_animtime 0.3 +set g_balance_crylink_primary_ammo 3 +set g_balance_crylink_primary_bouncedamagefactor 0.5 +set g_balance_crylink_primary_joindelay 0.1 +set g_balance_crylink_primary_joinspread 0.2 +set g_balance_crylink_primary_jointime 0 +set g_balance_crylink_primary_joinexplode 1 +set g_balance_crylink_primary_joinexplode_damage 0 +set g_balance_crylink_primary_joinexplode_edgedamage 0 +set g_balance_crylink_primary_joinexplode_radius 0 +set g_balance_crylink_primary_joinexplode_force 0 +set g_balance_crylink_primary_linkexplode 1 + +set g_balance_crylink_primary_middle_lifetime 5 // range: 35000 full, fades to 70000 +set g_balance_crylink_primary_middle_fadetime 5 +set g_balance_crylink_primary_other_lifetime 5 +set g_balance_crylink_primary_other_fadetime 5 + +set g_balance_crylink_secondary 1 +set g_balance_crylink_secondary_damage 5 +set g_balance_crylink_secondary_edgedamage 0 +set g_balance_crylink_secondary_force -40 +set g_balance_crylink_secondary_radius 70 +set g_balance_crylink_secondary_speed 2000 +set g_balance_crylink_secondary_spread 0.02 +set g_balance_crylink_secondary_shots 3 +set g_balance_crylink_secondary_bounces 1 +set g_balance_crylink_secondary_refire 0.2 +set g_balance_crylink_secondary_animtime 0.2 +set g_balance_crylink_secondary_ammo 2 +set g_balance_crylink_secondary_bouncedamagefactor 0.5 +set g_balance_crylink_secondary_joindelay 0 +set g_balance_crylink_secondary_joinspread 0 +set g_balance_crylink_secondary_jointime 0 +set g_balance_crylink_secondary_joinexplode 0 +set g_balance_crylink_secondary_joinexplode_damage 0 +set g_balance_crylink_secondary_joinexplode_edgedamage 0 +set g_balance_crylink_secondary_joinexplode_radius 0 +set g_balance_crylink_secondary_joinexplode_force 0 +set g_balance_crylink_secondary_linkexplode 1 + +set g_balance_crylink_secondary_middle_lifetime 5 // range: 35000 full, fades to 70000 +set g_balance_crylink_secondary_middle_fadetime 5 +set g_balance_crylink_secondary_line_lifetime 5 +set g_balance_crylink_secondary_line_fadetime 5 + +set g_balance_crylink_reload_ammo 0 //default: 10 +set g_balance_crylink_reload_time 2 +// }}} +// {{{ nex +set g_balance_nex_primary_damage 90 +set g_balance_nex_primary_force 400 +set g_balance_nex_primary_refire 1.5 +set g_balance_nex_primary_animtime 0.45 +set g_balance_nex_primary_ammo 6 +set g_balance_nex_primary_damagefalloff_mindist 0 // 1000 For tZork ;3 +set g_balance_nex_primary_damagefalloff_maxdist 0 // 3000 +set g_balance_nex_primary_damagefalloff_halflife 0 // 1500 +set g_balance_nex_primary_damagefalloff_forcehalflife 0 // 1500 + +set g_balance_nex_secondary 0 +set g_balance_nex_secondary_charge 0 +set g_balance_nex_secondary_charge_rate 0.1 +set g_balance_nex_secondary_chargepool 0 +set g_balance_nex_secondary_chargepool_regen 0.15 +set g_balance_nex_secondary_chargepool_pause_regen 1 +set g_balance_nex_secondary_chargepool_pause_health_regen 1 +set g_balance_nex_secondary_damage 0 +set g_balance_nex_secondary_force 0 +set g_balance_nex_secondary_refire 0 +set g_balance_nex_secondary_animtime 0 +set g_balance_nex_secondary_ammo 2 +set g_balance_nex_secondary_damagefalloff_mindist 0 +set g_balance_nex_secondary_damagefalloff_maxdist 0 +set g_balance_nex_secondary_damagefalloff_halflife 0 +set g_balance_nex_secondary_damagefalloff_forcehalflife 0 + +set g_balance_nex_charge 1 +set g_balance_nex_charge_mindmg 40 +set g_balance_nex_charge_start 0.5 +set g_balance_nex_charge_rate 0.4 +set g_balance_nex_charge_animlimit 0.5 +set g_balance_nex_charge_limit 1 +set g_balance_nex_charge_rot_rate 0 +set g_balance_nex_charge_rot_pause 0 // Dont rot down until this long after release of charge button +set g_balance_nex_charge_shot_multiplier 0 +set g_balance_nex_charge_velocity_rate 0 +set g_balance_nex_charge_minspeed 400 +set g_balance_nex_charge_maxspeed 800 + +set g_balance_nex_reload_ammo 0 //default: 25 +set g_balance_nex_reload_time 2 +// }}} +// {{{ minstanex +set g_balance_minstanex_refire 1 +set g_balance_minstanex_animtime 0.3 +set g_balance_minstanex_ammo 10 +set g_balance_minstanex_laser_ammo 0 +set g_balance_minstanex_laser_animtime 0.3 +set g_balance_minstanex_laser_refire 0.7 +set g_balance_minstanex_reload_ammo 0 //default: 50 +set g_balance_minstanex_reload_time 2 +// }}} +// {{{ hagar +set g_balance_hagar_primary_damage 25 +set g_balance_hagar_primary_edgedamage 12.5 +set g_balance_hagar_primary_force 100 +set g_balance_hagar_primary_health 15 +set g_balance_hagar_primary_damageforcescale 0 +set g_balance_hagar_primary_radius 65 +set g_balance_hagar_primary_spread 0.04 +set g_balance_hagar_primary_speed 2200 +set g_balance_hagar_primary_lifetime 5 +set g_balance_hagar_primary_refire 0.16667 // 6 rockets per second +set g_balance_hagar_primary_ammo 1 +set g_balance_hagar_secondary 1 +set g_balance_hagar_secondary_load 1 +set g_balance_hagar_secondary_load_speed 0.5 +set g_balance_hagar_secondary_load_spread 0.075 +set g_balance_hagar_secondary_load_spread_bias 0.5 +set g_balance_hagar_secondary_load_max 4 +set g_balance_hagar_secondary_load_hold 4 +set g_balance_hagar_secondary_load_releasedeath 0 +set g_balance_hagar_secondary_load_abort 1 +set g_balance_hagar_secondary_load_linkexplode 0 +set g_balance_hagar_secondary_load_animtime 0.2 +set g_balance_hagar_secondary_damage 40 +set g_balance_hagar_secondary_edgedamage 20 +set g_balance_hagar_secondary_force 75 +set g_balance_hagar_secondary_health 15 +set g_balance_hagar_secondary_damageforcescale 0 +set g_balance_hagar_secondary_radius 80 +set g_balance_hagar_secondary_spread 0.05 +set g_balance_hagar_secondary_speed 2000 +set g_balance_hagar_secondary_lifetime_min 10 +set g_balance_hagar_secondary_lifetime_rand 0 +set g_balance_hagar_secondary_refire 0.5 +set g_balance_hagar_secondary_ammo 1 +set g_balance_hagar_reload_ammo 0 //default: 25 +set g_balance_hagar_reload_time 2 +// }}} +// {{{ rocketlauncher +set g_balance_rocketlauncher_damage 80 +set g_balance_rocketlauncher_edgedamage 40 +set g_balance_rocketlauncher_force 400 +set g_balance_rocketlauncher_radius 110 +set g_balance_rocketlauncher_speed 1300 +set g_balance_rocketlauncher_speedaccel 1300 +set g_balance_rocketlauncher_speedstart 1000 +set g_balance_rocketlauncher_lifetime 10 +set g_balance_rocketlauncher_refire 1.1 +set g_balance_rocketlauncher_animtime 0.35 +set g_balance_rocketlauncher_ammo 4 +set g_balance_rocketlauncher_health 30 // 30 // 5 hitpoints above maximum laser value -- this way lasers can't blow it up, but grenadelauncher still can most the time. +set g_balance_rocketlauncher_damageforcescale 1 // low damage force scale so that it can still be affected by other hits, but not so much that it does a 90 degree turn +set g_balance_rocketlauncher_detonatedelay 0.02 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time +set g_balance_rocketlauncher_guiderate 90 // max degrees per second +set g_balance_rocketlauncher_guideratedelay 0.01 // immediate +set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic) +set g_balance_rocketlauncher_guidedelay 0.2 // delay before guiding kicks in +set g_balance_rocketlauncher_guidestop 0 // stop guiding when firing again +set g_balance_rocketlauncher_remote_damage 70 +set g_balance_rocketlauncher_remote_edgedamage 35 +set g_balance_rocketlauncher_remote_radius 110 +set g_balance_rocketlauncher_remote_force 400 +set g_balance_rocketlauncher_reload_ammo 0 //default: 25 +set g_balance_rocketlauncher_reload_time 2 +// }}} +// {{{ porto +set g_balance_porto_primary_refire 1.5 +set g_balance_porto_primary_animtime 0.3 +set g_balance_porto_primary_speed 1000 +set g_balance_porto_primary_lifetime 5 +set g_balance_portal_health 200 // these get recharged whenever the portal is used +set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used +// }}} +// {{{ hook +set g_balance_hook_primary_fuel 5 // hook monkeys set 0 +set g_balance_hook_primary_refire 0 // hook monkeys set 0 +set g_balance_hook_primary_animtime 0.3 // good shoot anim +set g_balance_hook_primary_hooked_time_max 0 // infinite +set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free +set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked +set g_balance_hook_secondary_damage 25 // not much +set g_balance_hook_secondary_edgedamage 5 // not much +set g_balance_hook_secondary_radius 500 // LOTS +set g_balance_hook_secondary_force -2000 // LOTS +set g_balance_hook_secondary_ammo 30 // a whole pack +set g_balance_hook_secondary_lifetime 5 // infinite +set g_balance_hook_secondary_speed 0 // not much throwing +set g_balance_hook_secondary_gravity 5 // fast falling +set g_balance_hook_secondary_refire 3 // don't drop too many bombs... +set g_balance_hook_secondary_animtime 0.3 // good shoot anim +set g_balance_hook_secondary_power 3 // effect behaves like a square function +set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds +set g_balance_hook_secondary_health 15 +set g_balance_hook_secondary_damageforcescale 0 +// }}} +// {{{ hlac // TO BE REMOVED +set g_balance_hlac_primary_spread_min 0.01 +set g_balance_hlac_primary_spread_max 0.25 +set g_balance_hlac_primary_spread_add 0.0045 +set g_balance_hlac_primary_spread_crouchmod 0.25 + +set g_balance_hlac_primary_damage 18 +set g_balance_hlac_primary_edgedamage 9 +set g_balance_hlac_primary_force 90 +set g_balance_hlac_primary_radius 70 +set g_balance_hlac_primary_speed 9000 +set g_balance_hlac_primary_lifetime 5 + +set g_balance_hlac_primary_refire 0.15 +set g_balance_hlac_primary_animtime 0.4 +set g_balance_hlac_primary_ammo 1 + +set g_balance_hlac_secondary 1 +set g_balance_hlac_secondary_spread 0.15 +set g_balance_hlac_secondary_spread_crouchmod 0.5 + +set g_balance_hlac_secondary_damage 15 +set g_balance_hlac_secondary_edgedamage 7.5 +set g_balance_hlac_secondary_force 90 +set g_balance_hlac_secondary_radius 70 +set g_balance_hlac_secondary_speed 9000 +set g_balance_hlac_secondary_lifetime 5 + +set g_balance_hlac_secondary_refire 1 +set g_balance_hlac_secondary_animtime 0.3 +set g_balance_hlac_secondary_ammo 10 +set g_balance_hlac_secondary_shots 6 + +set g_balance_hlac_reload_ammo 0 //default: 20 +set g_balance_hlac_reload_time 2 +// }}} +// {{{ rifle +set g_balance_rifle_bursttime 0 +set g_balance_rifle_primary_tracer 1 +set g_balance_rifle_primary_shots 1 +set g_balance_rifle_primary_damage 40 +set g_balance_rifle_primary_headshotaddeddamage 40 +set g_balance_rifle_primary_spread 0 +set g_balance_rifle_primary_force 100 +set g_balance_rifle_primary_speed 40000 +set g_balance_rifle_primary_lifetime 5 +set g_balance_rifle_primary_refire 1.2 +set g_balance_rifle_primary_animtime 0.4 +set g_balance_rifle_primary_ammo 10 +set g_balance_rifle_primary_bulletconstant 110 // 62.2qu +set g_balance_rifle_primary_burstcost 0 +set g_balance_rifle_primary_bullethail 0 // empty magazine on shot +set g_balance_rifle_secondary 1 +set g_balance_rifle_secondary_reload 0 +set g_balance_rifle_secondary_tracer 0 +set g_balance_rifle_secondary_shots 4 +set g_balance_rifle_secondary_damage 10 +set g_balance_rifle_secondary_headshotaddeddamage 20 +set g_balance_rifle_secondary_spread 0.04 +set g_balance_rifle_secondary_force 50 +set g_balance_rifle_secondary_speed 20000 +set g_balance_rifle_secondary_lifetime 5 +set g_balance_rifle_secondary_refire 0.9 +set g_balance_rifle_secondary_animtime 0.3 +set g_balance_rifle_secondary_ammo 10 +set g_balance_rifle_secondary_bulletconstant 110 // 15.5qu +set g_balance_rifle_secondary_burstcost 0 +set g_balance_rifle_secondary_bullethail 0 // empty magazine on shot +set g_balance_rifle_reload_ammo 80 //default: 80 +set g_balance_rifle_reload_time 2 +// }}} +// {{{ tuba +set g_balance_tuba_refire 0.05 +set g_balance_tuba_animtime 0.05 +set g_balance_tuba_attenuation 0.5 +set g_balance_tuba_volume 1 +set g_balance_tuba_fadetime 0.25 +set g_balance_tuba_damage 5 +set g_balance_tuba_edgedamage 0 +set g_balance_tuba_radius 200 +set g_balance_tuba_force 40 +set g_balance_tuba_pitchstep 6 +// }}} +// {{{ fireball // this is a superweapon -- lets make it behave as one. +set g_balance_fireball_primary_ammo 20 +set g_balance_fireball_primary_animtime 0.2 +set g_balance_fireball_primary_bfgdamage 100 +set g_balance_fireball_primary_bfgforce 0 +set g_balance_fireball_primary_bfgradius 1000 +set g_balance_fireball_primary_damage 200 +set g_balance_fireball_primary_damageforcescale 0 +set g_balance_fireball_primary_edgedamage 50 +set g_balance_fireball_primary_force 600 +set g_balance_fireball_primary_health 0 +set g_balance_fireball_primary_laserburntime 0.5 +set g_balance_fireball_primary_laserdamage 80 +set g_balance_fireball_primary_laseredgedamage 20 +set g_balance_fireball_primary_laserradius 256 +set g_balance_fireball_primary_lifetime 15 +set g_balance_fireball_primary_radius 200 +set g_balance_fireball_primary_refire 2 +set g_balance_fireball_primary_refire2 0 +set g_balance_fireball_primary_speed 1200 +set g_balance_fireball_primary_spread 0 +set g_balance_fireball_secondary_ammo 5 +set g_balance_fireball_secondary_animtime 0.3 +set g_balance_fireball_secondary_damage 40 +set g_balance_fireball_secondary_damageforcescale 4 +set g_balance_fireball_secondary_damagetime 5 +set g_balance_fireball_secondary_force 100 +set g_balance_fireball_secondary_laserburntime 0.5 +set g_balance_fireball_secondary_laserdamage 50 +set g_balance_fireball_secondary_laseredgedamage 20 +set g_balance_fireball_secondary_laserradius 110 +set g_balance_fireball_secondary_lifetime 7 +set g_balance_fireball_secondary_refire 1.5 +set g_balance_fireball_secondary_speed 900 +set g_balance_fireball_secondary_speed_up 100 +set g_balance_fireball_secondary_speed_z 0 +set g_balance_fireball_secondary_spread 0 +set g_balance_fireball_reload_ammo 0 //default: 100 +set g_balance_fireball_reload_time 2 +// }}} +// {{{ seeker +set g_balance_seeker_type 1 // 0 = old seeker, 1 = new seeker. THIS IS A TEMPORARY CVAR FOR TESTING, will be removed later. +set g_balance_seeker_flac_ammo 0.5 +set g_balance_seeker_flac_animtime 0.1 +set g_balance_seeker_flac_damage 15 +set g_balance_seeker_flac_edgedamage 10 +set g_balance_seeker_flac_force 50 +set g_balance_seeker_flac_lifetime 0.1 +set g_balance_seeker_flac_lifetime_rand 0.05 +set g_balance_seeker_flac_radius 100 +set g_balance_seeker_flac_refire 0.1 +set g_balance_seeker_flac_speed 3000 +set g_balance_seeker_flac_speed_up 1000 +set g_balance_seeker_flac_speed_z 0 +set g_balance_seeker_flac_spread 0.4 +set g_balance_seeker_tag_ammo 1 +set g_balance_seeker_tag_animtime 0.2 +set g_balance_seeker_tag_damageforcescale 0 +set g_balance_seeker_tag_health 0 +set g_balance_seeker_tag_lifetime 15 +set g_balance_seeker_tag_refire 0.75 // LOG: 0.7 -> 0.75 +set g_balance_seeker_tag_speed 5000 +set g_balance_seeker_tag_spread 0 +set g_balance_seeker_tag_tracker_lifetime 10 +set g_balance_seeker_missile_accel 1500 +set g_balance_seeker_missile_ammo 2 +set g_balance_seeker_missile_animtime 0.2 +set g_balance_seeker_missile_count 3 // LOG: 8 -> 3 +set g_balance_seeker_missile_damage 16 // LOG: 15 -> 30 +set g_balance_seeker_missile_damageforcescale 4 +set g_balance_seeker_missile_decel 6000 +set g_balance_seeker_missile_delay 0.25 +set g_balance_seeker_missile_edgedamage 8 +set g_balance_seeker_missile_force 50 // LOG: 100 -> 150 +set g_balance_seeker_missile_health 1 +set g_balance_seeker_missile_lifetime 15 +set g_balance_seeker_missile_proxy 0 +set g_balance_seeker_missile_proxy_delay 0.2 +set g_balance_seeker_missile_proxy_maxrange 45 +set g_balance_seeker_missile_radius 70 +set g_balance_seeker_missile_refire 0.25 +set g_balance_seeker_missile_smart 0 +set g_balance_seeker_missile_smart_mindist 800 +set g_balance_seeker_missile_smart_trace_max 2500 +set g_balance_seeker_missile_smart_trace_min 1000 +set g_balance_seeker_missile_speed 1500 +set g_balance_seeker_missile_speed_up 0 +set g_balance_seeker_missile_speed_z 0 +set g_balance_seeker_missile_speed_max 2000 // LOG: 1400 -> 1300 +set g_balance_seeker_missile_spread 0 +set g_balance_seeker_missile_turnrate 0.15 +set g_balance_seeker_reload_ammo 0 //default: 15 +set g_balance_seeker_reload_time 2 +// End new seeker diff --git a/balanceXonotic.cfg b/balanceXonotic.cfg index 72283286f3..b4e368a28e 100644 --- a/balanceXonotic.cfg +++ b/balanceXonotic.cfg @@ -7,45 +7,45 @@ set g_start_weapon_minelayer -1 "0 = never provide the weapon, 1 = always provid set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" // UNTIL IT CAN BE REMOVED FROM CODE set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_hlac -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_campingrifle -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_hlac -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" // UNTIL IT CAN BE REMOVED FROM CODE +set g_start_weapon_rifle -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" // UNTIL IT CAN BE REMOVED FROM CODE set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" set g_start_weapon_seeker -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_balance_health_start 125 +set g_balance_health_start 100 set g_balance_armor_start 0 -set g_start_ammo_shells 20 +set g_start_ammo_shells 15 set g_start_ammo_nails 0 set g_start_ammo_rockets 0 set g_start_ammo_cells 0 set g_start_ammo_fuel 0 -set g_warmup_start_health 200 "starting values when being in warmup-stage" +set g_warmup_start_health 100 "starting values when being in warmup-stage" set g_warmup_start_armor 100 "starting values when being in warmup-stage" -set g_warmup_start_ammo_shells 50 "starting values when being in warmup-stage" -set g_warmup_start_ammo_nails 150 "starting values when being in warmup-stage" -set g_warmup_start_ammo_rockets 50 "starting values when being in warmup-stage" -set g_warmup_start_ammo_cells 50 "starting values when being in warmup-stage" +set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage" +set g_warmup_start_ammo_nails 160 "starting values when being in warmup-stage" +set g_warmup_start_ammo_rockets 80 "starting values when being in warmup-stage" +set g_warmup_start_ammo_cells 90 "starting values when being in warmup-stage" set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage" set g_lms_start_health 200 -set g_lms_start_armor 100 -set g_lms_start_ammo_shells 30 -set g_lms_start_ammo_nails 200 -set g_lms_start_ammo_rockets 150 -set g_lms_start_ammo_cells 150 +set g_lms_start_armor 200 +set g_lms_start_ammo_shells 60 +set g_lms_start_ammo_nails 320 +set g_lms_start_ammo_rockets 160 +set g_lms_start_ammo_cells 180 set g_lms_start_ammo_fuel 0 set g_balance_nix_roundtime 25 set g_balance_nix_incrtime 1.6 -set g_balance_nix_ammo_shells 15 -set g_balance_nix_ammo_nails 45 -set g_balance_nix_ammo_rockets 15 -set g_balance_nix_ammo_cells 15 +set g_balance_nix_ammo_shells 60 +set g_balance_nix_ammo_nails 320 +set g_balance_nix_ammo_rockets 160 +set g_balance_nix_ammo_cells 180 set g_balance_nix_ammo_fuel 0 -set g_balance_nix_ammoincr_shells 2 +set g_balance_nix_ammoincr_shells 2 // eh this will need figured out later I assume set g_balance_nix_ammoincr_nails 6 set g_balance_nix_ammoincr_rockets 2 set g_balance_nix_ammoincr_cells 2 @@ -55,82 +55,82 @@ set g_balance_nix_ammoincr_fuel 2 // {{{ pickup items set g_pickup_ammo_anyway 1 set g_pickup_weapons_anyway 1 -set g_pickup_shells 20 -set g_pickup_shells_weapon 10 -set g_pickup_shells_max 45 -set g_pickup_nails 120 -set g_pickup_nails_weapon 60 -set g_pickup_nails_max 300 -set g_pickup_rockets 25 -set g_pickup_rockets_weapon 15 -set g_pickup_rockets_max 150 +set g_pickup_shells 15 +set g_pickup_shells_weapon 15 +set g_pickup_shells_max 60 +set g_pickup_nails 80 +set g_pickup_nails_weapon 80 +set g_pickup_nails_max 320 +set g_pickup_rockets 40 +set g_pickup_rockets_weapon 40 +set g_pickup_rockets_max 160 set g_pickup_cells 30 -set g_pickup_cells_weapon 20 -set g_pickup_cells_max 150 -set g_pickup_fuel 25 -set g_pickup_fuel_weapon 15 -set g_pickup_fuel_jetpack 50 +set g_pickup_cells_weapon 30 +set g_pickup_cells_max 180 +set g_pickup_fuel 50 +set g_pickup_fuel_weapon 50 +set g_pickup_fuel_jetpack 100 set g_pickup_fuel_max 100 set g_pickup_armorsmall 5 -set g_pickup_armorsmall_max 150 +set g_pickup_armorsmall_max 200 set g_pickup_armorsmall_anyway 1 set g_pickup_armormedium 25 -set g_pickup_armormedium_max 50 -set g_pickup_armormedium_anyway 0 +set g_pickup_armormedium_max 200 +set g_pickup_armormedium_anyway 1 set g_pickup_armorbig 50 -set g_pickup_armorbig_max 50 -set g_pickup_armorbig_anyway 0 +set g_pickup_armorbig_max 200 +set g_pickup_armorbig_anyway 1 set g_pickup_armorlarge 100 -set g_pickup_armorlarge_max 150 +set g_pickup_armorlarge_max 200 set g_pickup_armorlarge_anyway 1 set g_pickup_healthsmall 5 -set g_pickup_healthsmall_max 250 +set g_pickup_healthsmall_max 200 set g_pickup_healthsmall_anyway 1 set g_pickup_healthmedium 25 -set g_pickup_healthmedium_max 100 -set g_pickup_healthmedium_anyway 0 +set g_pickup_healthmedium_max 200 +set g_pickup_healthmedium_anyway 1 set g_pickup_healthlarge 50 -set g_pickup_healthlarge_max 150 -set g_pickup_healthlarge_anyway 0 +set g_pickup_healthlarge_max 200 +set g_pickup_healthlarge_anyway 1 set g_pickup_healthmega 100 -set g_pickup_healthmega_max 250 +set g_pickup_healthmega_max 200 set g_pickup_healthmega_anyway 1 set g_pickup_respawntime_short 15 set g_pickup_respawntime_medium 20 set g_pickup_respawntime_long 30 set g_pickup_respawntime_powerup 120 set g_pickup_respawntime_weapon 10 -set g_pickup_respawntime_ammo 25 +set g_pickup_respawntime_ammo 10 set g_pickup_respawntimejitter_short 0 set g_pickup_respawntimejitter_medium 0 set g_pickup_respawntimejitter_long 0 -set g_pickup_respawntimejitter_powerup 10 +set g_pickup_respawntimejitter_powerup 30 set g_pickup_respawntimejitter_weapon 0 set g_pickup_respawntimejitter_ammo 0 // }}} // {{{ regen/rot -set g_balance_health_regen 0.05 -set g_balance_health_regenlinear 0 +set g_balance_health_regen 0.08 +set g_balance_health_regenlinear 0.5 set g_balance_pause_health_regen 5 set g_balance_pause_health_regen_spawn 0 -set g_balance_health_rot 0 -set g_balance_health_rotlinear 1 +set g_balance_health_rot 0.04 +set g_balance_health_rotlinear 0.75 set g_balance_pause_health_rot 1 -set g_balance_pause_health_rot_spawn 0 +set g_balance_pause_health_rot_spawn 5 set g_balance_health_regenstable 100 set g_balance_health_rotstable 100 set g_balance_health_limit 999 set g_balance_armor_regen 0 set g_balance_armor_regenlinear 0 -set g_balance_armor_rot 0 -set g_balance_armor_rotlinear 1 +set g_balance_armor_rot 0.04 +set g_balance_armor_rotlinear 0.75 set g_balance_pause_armor_rot 1 -set g_balance_pause_armor_rot_spawn 0 +set g_balance_pause_armor_rot_spawn 5 set g_balance_armor_regenstable 100 set g_balance_armor_rotstable 100 set g_balance_armor_limit 999 -set g_balance_armor_blockpercent 0.7 +set g_balance_armor_blockpercent 0.6 set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)" set g_balance_fuel_regenlinear 0 set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter @@ -145,7 +145,7 @@ set g_balance_fuel_limit 999 // {{{ misc set g_balance_selfdamagepercent 0.65 -set g_balance_weaponswitchdelay 0.1 +set g_balance_weaponswitchdelay 0.15 set g_weaponspeedfactor 1 "weapon projectile speed multiplier" set g_weaponratefactor 1 "weapon fire rate multiplier" set g_weapondamagefactor 1 "weapon damage multiplier" @@ -153,8 +153,15 @@ set g_weaponforcefactor 1 "weapon force multiplier" set g_weaponspreadfactor 1 "weapon spread multiplier" set g_balance_firetransfer_time 0.9 set g_balance_firetransfer_damage 0.8 -set g_throughfloor_damage 0.5 -set g_throughfloor_force 0.7 +set g_throughfloor_damage 0.75 +set g_throughfloor_force 0.75 +set g_projectiles_damage 2 +// possible values: +// -2: absolutely no damage to projectiles (no exceptions) +// -1: no damage other than the exceptions (electro combo, hagar join explode, minelayer mines) +// 0: only damage from contents (lava/slime) or exceptions +// 1: only self damage or damage from contents or exceptions +// 2: allow all damage to projectiles normally set g_projectiles_newton_style 2 // possible values: // 0: absolute velocity projectiles (like Quake) @@ -162,8 +169,8 @@ set g_projectiles_newton_style 2 // 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard) // 3: absolute velocity + player velocity component in shot direction (note: does NOT yield the right relative velocity, but may be good enough, but it is somewhat prone to sniper rockets) // 4: just add the player velocity length to the absolute velocity (tZork's sniper rockets) -set g_projectiles_newton_style_2_minfactor 0.7 -set g_projectiles_newton_style_2_maxfactor 5 +set g_projectiles_newton_style_2_minfactor 0.8 +set g_projectiles_newton_style_2_maxfactor 1.5 set g_projectiles_spread_style 7 // possible values: // 0: forward + solid sphere (like Quake) - varies velocity @@ -174,17 +181,25 @@ set g_projectiles_spread_style 7 // 5: forward + circle with 1-r falloff // 6: forward + circle with 1-r^2 falloff // 7: forward + circle with (1-r)(2-r) falloff -set g_balance_falldamage_deadminspeed 150 -set g_balance_falldamage_minspeed 800 +set g_balance_falldamage_deadminspeed 250 +set g_balance_falldamage_minspeed 900 set g_balance_falldamage_factor 0.20 -set g_balance_falldamage_maxdamage 15 +set g_balance_falldamage_maxdamage 40 +set g_balance_damagepush_speedfactor 2.5 +set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage +set g_balance_contents_drowndelay 10 // time under water before a player begins drowning +set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning +set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava +set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime +set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime +set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap" // }}} // {{{ powerups -set g_balance_powerup_invincible_takedamage 0.3 +set g_balance_powerup_invincible_takedamage 0.25 // only 1/4th damage is taken set g_balance_powerup_invincible_time 30 set g_balance_powerup_strength_damage 3 -set g_balance_powerup_strength_force 4 +set g_balance_powerup_strength_force 3 set g_balance_powerup_strength_time 30 set g_balance_powerup_strength_selfdamage 1.5 set g_balance_powerup_strength_selfforce 1.5 @@ -194,7 +209,7 @@ set g_balance_powerup_strength_selfforce 1.5 set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack" set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction" set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)" -set g_jetpack_maxspeed_side 1500 "max speed of the jetpack in xy direction" +set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction" set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction" set g_jetpack_fuel 8 "fuel per second for jetpack" set g_jetpack_attenuation 2 "jetpack sound attenuation" @@ -207,145 +222,168 @@ set g_balance_grapplehook_force_rubber_overstretch 1000 set g_balance_grapplehook_length_min 50 set g_balance_grapplehook_stretch 50 set g_balance_grapplehook_airfriction 0.2 -set g_balance_grapplehook_health 130 +set g_balance_grapplehook_health 50 +set g_balance_grapplehook_damagedbycontents 1 // }}} // {{{ weapon properties // {{{ laser -set g_balance_laser_primary_damage 20 // dps 33, hope that's not too high -set g_balance_laser_primary_edgedamage 20 -set g_balance_laser_primary_force 150 // this looks insanely low, but actually isn't with zscale and velocitybias -set g_balance_laser_primary_radius 60 -set g_balance_laser_primary_speed 5000 +set g_balance_laser_primary_damage 25 +set g_balance_laser_primary_edgedamage 12.5 +set g_balance_laser_primary_force 300 +set g_balance_laser_primary_radius 70 +set g_balance_laser_primary_speed 6000 set g_balance_laser_primary_spread 0 -set g_balance_laser_primary_refire 0.6 -set g_balance_laser_primary_animtime 0.6 +set g_balance_laser_primary_refire 0.7 +set g_balance_laser_primary_animtime 0.3 set g_balance_laser_primary_lifetime 5 set g_balance_laser_primary_shotangle 0 set g_balance_laser_primary_delay 0 set g_balance_laser_primary_gauntlet 0 -set g_balance_laser_primary_force_zscale 2 // 300 upforce -set g_balance_laser_primary_force_velocitybias 0.3 +set g_balance_laser_primary_force_zscale 1.25 +set g_balance_laser_primary_force_velocitybias 0 +set g_balance_laser_primary_force_other_scale 1 set g_balance_laser_secondary 0 // when 1, a secondary laser mode exists -set g_balance_laser_secondary_damage 200 // dps -set g_balance_laser_secondary_edgedamage 0 -set g_balance_laser_secondary_force 1300 -set g_balance_laser_secondary_radius 60 -set g_balance_laser_secondary_speed 0 +set g_balance_laser_secondary_damage 25 +set g_balance_laser_secondary_edgedamage 12.5 +set g_balance_laser_secondary_force 400 +set g_balance_laser_secondary_radius 70 +set g_balance_laser_secondary_speed 12000 set g_balance_laser_secondary_spread 0 -set g_balance_laser_secondary_refire 0.066 -set g_balance_laser_secondary_animtime 0.066 -set g_balance_laser_secondary_lifetime 0 -set g_balance_laser_secondary_shotangle 0 +set g_balance_laser_secondary_refire 0.7 +set g_balance_laser_secondary_animtime 0.3 +set g_balance_laser_secondary_lifetime 5 +set g_balance_laser_secondary_shotangle -90 set g_balance_laser_secondary_delay 0 -set g_balance_laser_secondary_gauntlet 1 +set g_balance_laser_secondary_gauntlet 0 set g_balance_laser_secondary_force_zscale 1.25 set g_balance_laser_secondary_force_velocitybias 0 +set g_balance_laser_secondary_force_other_scale 1 +set g_balance_laser_reload_ammo 0 //default: 6 +set g_balance_laser_reload_time 2 // }}} // {{{ shotgun -set g_balance_shotgun_primary_bullets 18 +set g_balance_shotgun_primary_bullets 14 set g_balance_shotgun_primary_damage 4 -set g_balance_shotgun_primary_force 20 -set g_balance_shotgun_primary_spread 0.18 -set g_balance_shotgun_primary_refire 1 -set g_balance_shotgun_primary_animtime 0.4 +set g_balance_shotgun_primary_force 15 +set g_balance_shotgun_primary_spread 0.12 +set g_balance_shotgun_primary_refire 0.75 +set g_balance_shotgun_primary_animtime 0.2 set g_balance_shotgun_primary_ammo 1 -set g_balance_shotgun_primary_speed 12000 +set g_balance_shotgun_primary_speed 8000 set g_balance_shotgun_primary_bulletconstant 75 // 3.8qu set g_balance_shotgun_secondary 1 -set g_balance_shotgun_secondary_melee_delay 0.35 // match the anim -set g_balance_shotgun_secondary_melee_range 85 -set g_balance_shotgun_secondary_melee_swing 50 -set g_balance_shotgun_secondary_melee_time 0.1 -set g_balance_shotgun_secondary_damage 110 -set g_balance_shotgun_secondary_force 150 -set g_balance_shotgun_secondary_refire 1.1 +set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow +set g_balance_shotgun_secondary_melee_range 120 +set g_balance_shotgun_secondary_melee_swing_side 120 +set g_balance_shotgun_secondary_melee_swing_up 30 +set g_balance_shotgun_secondary_melee_time 0.15 +set g_balance_shotgun_secondary_melee_traces 10 +set g_balance_shotgun_secondary_melee_no_doubleslap 1 +set g_balance_shotgun_secondary_melee_nonplayerdamage 40 +set g_balance_shotgun_secondary_melee_multihit 1 +set g_balance_shotgun_secondary_damage 80 +set g_balance_shotgun_secondary_force 200 +set g_balance_shotgun_secondary_refire 1.25 set g_balance_shotgun_secondary_animtime 1 +set g_balance_shotgun_reload_ammo 0 //default: 5 +set g_balance_shotgun_reload_time 2 // }}} // {{{ uzi set g_balance_uzi_mode 1 // Activates varible spread for sustained & burst mode secondary set g_balance_uzi_spread_min 0.02 -set g_balance_uzi_spread_max 0.6 -set g_balance_uzi_spread_add 0.008 +set g_balance_uzi_spread_max 0.05 +set g_balance_uzi_spread_add 0.012 set g_balance_uzi_burst 3 // # of bullets in a burst (if set to 2 or more) -set g_balance_uzi_burst_refire 0.05 // refire between burst bullets -set g_balance_uzi_burst_refire2 0.45 // refire after burst -set g_balance_uzi_burst_spread 0.05 -set g_balance_uzi_burst_damage 20 // 100 dps, delivered in 0.15s -set g_balance_uzi_burst_force 50 +set g_balance_uzi_burst_animtime 0.3 +set g_balance_uzi_burst_refire 0.06 // refire between burst bullets +set g_balance_uzi_burst_refire2 0.45 // refire after burst +set g_balance_uzi_burst_spread 0.02 +set g_balance_uzi_burst_damage 25 +set g_balance_uzi_burst_force 20 set g_balance_uzi_burst_ammo 3 set g_balance_uzi_first 1 -set g_balance_uzi_first_damage 20 // 100 dps -set g_balance_uzi_first_force 50 +set g_balance_uzi_first_damage 14 +set g_balance_uzi_first_headshotaddeddamage 0 +set g_balance_uzi_first_force 5 set g_balance_uzi_first_spread 0.03 -set g_balance_uzi_first_refire 0.2 -set g_balance_uzi_first_ammo 2 +set g_balance_uzi_first_refire 0.125 +set g_balance_uzi_first_ammo 1 -set g_balance_uzi_sustained_damage 12 // 120 dps -set g_balance_uzi_sustained_force 12 -set g_balance_uzi_sustained_spread 0.08 +set g_balance_uzi_sustained_damage 10 // 100 dps +set g_balance_uzi_sustained_headshotaddeddamage 0 +set g_balance_uzi_sustained_force 5 +set g_balance_uzi_sustained_spread 0.03 set g_balance_uzi_sustained_refire 0.1 set g_balance_uzi_sustained_ammo 1 set g_balance_uzi_speed 18000 set g_balance_uzi_bulletconstant 115 // 13.1qu + +set g_balance_uzi_reload_ammo 60 //default: 30 +set g_balance_uzi_reload_time 2 // }}} // {{{ mortar set g_balance_grenadelauncher_primary_type 0 -set g_balance_grenadelauncher_primary_damage 44 -set g_balance_grenadelauncher_primary_edgedamage 32 -set g_balance_grenadelauncher_primary_force 300 -set g_balance_grenadelauncher_primary_radius 115 -set g_balance_grenadelauncher_primary_speed 1500 +set g_balance_grenadelauncher_primary_damage 50 +set g_balance_grenadelauncher_primary_edgedamage 25 +set g_balance_grenadelauncher_primary_force 250 +set g_balance_grenadelauncher_primary_radius 120 +set g_balance_grenadelauncher_primary_speed 1900 set g_balance_grenadelauncher_primary_speed_up 225 set g_balance_grenadelauncher_primary_speed_z 0 set g_balance_grenadelauncher_primary_spread 0 set g_balance_grenadelauncher_primary_lifetime 5 -set g_balance_grenadelauncher_primary_lifetime2 0.65 +set g_balance_grenadelauncher_primary_lifetime2 1 set g_balance_grenadelauncher_primary_refire 0.8 -set g_balance_grenadelauncher_primary_animtime 0.4 +set g_balance_grenadelauncher_primary_animtime 0.3 set g_balance_grenadelauncher_primary_ammo 2 -set g_balance_grenadelauncher_primary_health 80 +set g_balance_grenadelauncher_primary_health 15 set g_balance_grenadelauncher_primary_damageforcescale 0 set g_balance_grenadelauncher_primary_remote_minbouncecnt 0 set g_balance_grenadelauncher_secondary_type 1 -set g_balance_grenadelauncher_secondary_damage 62 -set g_balance_grenadelauncher_secondary_edgedamage 32 -set g_balance_grenadelauncher_secondary_force 300 -set g_balance_grenadelauncher_secondary_radius 150 -set g_balance_grenadelauncher_secondary_speed 1000 -set g_balance_grenadelauncher_secondary_speed_up 250 +set g_balance_grenadelauncher_secondary_damage 60 +set g_balance_grenadelauncher_secondary_edgedamage 30 +set g_balance_grenadelauncher_secondary_force 250 +set g_balance_grenadelauncher_secondary_radius 120 +set g_balance_grenadelauncher_secondary_speed 1400 +set g_balance_grenadelauncher_secondary_speed_up 150 set g_balance_grenadelauncher_secondary_speed_z 0 set g_balance_grenadelauncher_secondary_spread 0 -set g_balance_grenadelauncher_secondary_lifetime 3 -set g_balance_grenadelauncher_secondary_lifetime2 0.65 -set g_balance_grenadelauncher_secondary_refire 0.8 -set g_balance_grenadelauncher_secondary_animtime 0.4 +set g_balance_grenadelauncher_secondary_lifetime 5 +set g_balance_grenadelauncher_secondary_lifetime_bounce 0.5 +set g_balance_grenadelauncher_secondary_lifetime_stick 0 +set g_balance_grenadelauncher_secondary_refire 0.7 +set g_balance_grenadelauncher_secondary_animtime 0.3 set g_balance_grenadelauncher_secondary_ammo 2 -set g_balance_grenadelauncher_secondary_health 40 -set g_balance_grenadelauncher_secondary_damageforcescale 0 +set g_balance_grenadelauncher_secondary_health 30 +set g_balance_grenadelauncher_secondary_damageforcescale 4 set g_balance_grenadelauncher_secondary_remote_detonateprimary 0 set g_balance_grenadelauncher_bouncefactor 0.5 -set g_balance_grenadelauncher_bouncestop 0.12 +set g_balance_grenadelauncher_bouncestop 0.075 + +set g_balance_grenadelauncher_reload_ammo 0 //default: 12 +set g_balance_grenadelauncher_reload_time 2 // }}} // {{{ minelayer -set g_balance_minelayer_damage 42 -set g_balance_minelayer_edgedamage 30 +set g_balance_minelayer_damage 40 +set g_balance_minelayer_edgedamage 20 set g_balance_minelayer_force 250 set g_balance_minelayer_radius 175 set g_balance_minelayer_proximityradius 150 -set g_balance_minelayer_speed 750 -set g_balance_minelayer_lifetime 60 +set g_balance_minelayer_speed 1000 +set g_balance_minelayer_lifetime 10 +set g_balance_minelayer_lifetime_countdown 0.5 set g_balance_minelayer_refire 1.5 set g_balance_minelayer_animtime 0.4 -set g_balance_minelayer_ammo 5 +set g_balance_minelayer_ammo 4 set g_balance_minelayer_health 15 -set g_balance_minelayer_limit 4 // 0 disables the limit -set g_balance_minelayer_protection 1 // don't explode if the mine would hurt the owner or a team mate +set g_balance_minelayer_limit 3 // 0 disables the limit +set g_balance_minelayer_protection 0 // don't explode if the mine would hurt the owner or a team mate set g_balance_minelayer_damageforcescale 0 set g_balance_minelayer_detonatedelay -1 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time set g_balance_minelayer_time 0.5 @@ -353,90 +391,98 @@ set g_balance_minelayer_remote_damage 45 set g_balance_minelayer_remote_edgedamage 40 set g_balance_minelayer_remote_radius 200 set g_balance_minelayer_remote_force 300 +set g_balance_minelayer_reload_ammo 0 //default: 15 +set g_balance_minelayer_reload_time 2 // }}} // {{{ electro -set g_balance_electro_lightning 1 -set g_balance_electro_primary_damage 92 -set g_balance_electro_primary_edgedamage 0 -set g_balance_electro_primary_force 425 -set g_balance_electro_primary_force_up 125 -set g_balance_electro_primary_radius 850 -set g_balance_electro_primary_comboradius 75 -set g_balance_electro_primary_speed 0 +set g_balance_electro_lightning 0 +set g_balance_electro_primary_damage 40 +set g_balance_electro_primary_edgedamage 20 +set g_balance_electro_primary_force 200 +set g_balance_electro_primary_force_up 0 +set g_balance_electro_primary_radius 100 +set g_balance_electro_primary_comboradius 150 +set g_balance_electro_primary_speed 2500 set g_balance_electro_primary_spread 0 -set g_balance_electro_primary_lifetime 0 -set g_balance_electro_primary_refire 0.4 -set g_balance_electro_primary_animtime 0.03333333 -set g_balance_electro_primary_ammo 5 -set g_balance_electro_primary_range 800 -set g_balance_electro_primary_falloff_mindist 0 -set g_balance_electro_primary_falloff_maxdist 0 -set g_balance_electro_primary_falloff_halflifedist 0 -set g_balance_electro_secondary_damage 25 -set g_balance_electro_secondary_edgedamage 0 -set g_balance_electro_secondary_force 100 -set g_balance_electro_secondary_radius 100 -set g_balance_electro_secondary_speed 700 +set g_balance_electro_primary_lifetime 5 +set g_balance_electro_primary_refire 0.6 +set g_balance_electro_primary_animtime 0.1 +set g_balance_electro_primary_ammo 4 +set g_balance_electro_primary_range 0 +set g_balance_electro_primary_falloff_mindist 255 // 0.3 * radius +set g_balance_electro_primary_falloff_maxdist 850 +set g_balance_electro_primary_falloff_halflifedist 425 +set g_balance_electro_secondary_damage 40 +set g_balance_electro_secondary_edgedamage 20 +set g_balance_electro_secondary_force 50 +set g_balance_electro_secondary_radius 150 +set g_balance_electro_secondary_speed 900 set g_balance_electro_secondary_speed_up 200 set g_balance_electro_secondary_speed_z 0 -set g_balance_electro_secondary_spread 0.08 -set g_balance_electro_secondary_lifetime 3.5 +set g_balance_electro_secondary_spread 0.05 +set g_balance_electro_secondary_lifetime 3 set g_balance_electro_secondary_refire 0.2 -set g_balance_electro_secondary_refire2 2 +set g_balance_electro_secondary_refire2 1.5 set g_balance_electro_secondary_animtime 0.2 set g_balance_electro_secondary_ammo 2 -set g_balance_electro_secondary_health 10 +set g_balance_electro_secondary_health 5 set g_balance_electro_secondary_damageforcescale 4 +set g_balance_electro_secondary_damagedbycontents 1 set g_balance_electro_secondary_count 3 -set g_balance_electro_secondary_bouncefactor 0.5 -set g_balance_electro_secondary_bouncestop 0.075 +set g_balance_electro_secondary_bouncefactor 0.4 +set g_balance_electro_secondary_bouncestop 0.05 set g_balance_electro_combo_damage 50 -set g_balance_electro_combo_edgedamage 0 -set g_balance_electro_combo_force 80 -set g_balance_electro_combo_radius 250 -set g_balance_electro_combo_comboradius 0 -set g_balance_electro_combo_speed 400 +set g_balance_electro_combo_edgedamage 25 +set g_balance_electro_combo_force 120 +set g_balance_electro_combo_radius 175 +set g_balance_electro_combo_comboradius 275 +set g_balance_electro_combo_speed 2000 +set g_balance_electro_combo_safeammocheck 1 +set g_balance_electro_reload_ammo 0 //default: 20 +set g_balance_electro_reload_time 2 // }}} -// {{{ crylink +// {{{ crylink set g_balance_crylink_primary_damage 10 -set g_balance_crylink_primary_edgedamage 6 -set g_balance_crylink_primary_force 40 +set g_balance_crylink_primary_edgedamage 5 +set g_balance_crylink_primary_force -55 set g_balance_crylink_primary_radius 80 -set g_balance_crylink_primary_speed 1500 -set g_balance_crylink_primary_spread 0.05 -set g_balance_crylink_primary_shots 7 -set g_balance_crylink_primary_bounces 2 -set g_balance_crylink_primary_refire 0.8 -set g_balance_crylink_primary_animtime 0.4 -set g_balance_crylink_primary_ammo 2 -set g_balance_crylink_primary_bouncedamagefactor 0.2 +set g_balance_crylink_primary_speed 2000 +set g_balance_crylink_primary_spread 0.08 +set g_balance_crylink_primary_shots 6 +set g_balance_crylink_primary_bounces 1 +set g_balance_crylink_primary_refire 0.7 +set g_balance_crylink_primary_animtime 0.3 +set g_balance_crylink_primary_ammo 3 +set g_balance_crylink_primary_bouncedamagefactor 0.5 +set g_balance_crylink_primary_joindelay 0.1 set g_balance_crylink_primary_joinspread 0.2 -set g_balance_crylink_primary_jointime 0.1 -set g_balance_crylink_primary_joinexplode 0 +set g_balance_crylink_primary_jointime 0 +set g_balance_crylink_primary_joinexplode 1 set g_balance_crylink_primary_joinexplode_damage 0 set g_balance_crylink_primary_joinexplode_edgedamage 0 set g_balance_crylink_primary_joinexplode_radius 0 set g_balance_crylink_primary_joinexplode_force 0 set g_balance_crylink_primary_linkexplode 1 -set g_balance_crylink_primary_middle_lifetime 5 // range: 10000 full, fades to 20000 +set g_balance_crylink_primary_middle_lifetime 5 // range: 35000 full, fades to 70000 set g_balance_crylink_primary_middle_fadetime 5 -set g_balance_crylink_primary_other_lifetime 2 // range: 800 full, fades to 1300 -set g_balance_crylink_primary_other_fadetime 0.25 +set g_balance_crylink_primary_other_lifetime 5 +set g_balance_crylink_primary_other_fadetime 5 set g_balance_crylink_secondary 1 -set g_balance_crylink_secondary_damage 3 +set g_balance_crylink_secondary_damage 5 set g_balance_crylink_secondary_edgedamage 0 -set g_balance_crylink_secondary_force -20 -set g_balance_crylink_secondary_radius 5 -set g_balance_crylink_secondary_speed 1700 -set g_balance_crylink_secondary_spread 0.03 +set g_balance_crylink_secondary_force -40 +set g_balance_crylink_secondary_radius 70 +set g_balance_crylink_secondary_speed 2000 +set g_balance_crylink_secondary_spread 0.02 set g_balance_crylink_secondary_shots 3 -set g_balance_crylink_secondary_bounces 0 -set g_balance_crylink_secondary_refire 0.15 -set g_balance_crylink_secondary_animtime 0.15 -set g_balance_crylink_secondary_ammo 1 +set g_balance_crylink_secondary_bounces 1 +set g_balance_crylink_secondary_refire 0.2 +set g_balance_crylink_secondary_animtime 0.2 +set g_balance_crylink_secondary_ammo 2 set g_balance_crylink_secondary_bouncedamagefactor 0.5 +set g_balance_crylink_secondary_joindelay 0 set g_balance_crylink_secondary_joinspread 0 set g_balance_crylink_secondary_jointime 0 set g_balance_crylink_secondary_joinexplode 0 @@ -446,26 +492,29 @@ set g_balance_crylink_secondary_joinexplode_radius 0 set g_balance_crylink_secondary_joinexplode_force 0 set g_balance_crylink_secondary_linkexplode 1 -set g_balance_crylink_secondary_middle_lifetime 5 // range: 10000 full, fades to 10000 +set g_balance_crylink_secondary_middle_lifetime 5 // range: 35000 full, fades to 70000 set g_balance_crylink_secondary_middle_fadetime 5 -set g_balance_crylink_secondary_line_lifetime 2 // range: 4000 full, fades to 8000 -set g_balance_crylink_secondary_line_fadetime 2 +set g_balance_crylink_secondary_line_lifetime 5 +set g_balance_crylink_secondary_line_fadetime 5 + +set g_balance_crylink_reload_ammo 0 //default: 10 +set g_balance_crylink_reload_time 2 // }}} // {{{ nex set g_balance_nex_primary_damage 90 -set g_balance_nex_primary_force 500 -set g_balance_nex_primary_refire 1 -set g_balance_nex_primary_animtime 0.4 -set g_balance_nex_primary_ammo 5 -set g_balance_nex_primary_damagefalloff_mindist 0 -set g_balance_nex_primary_damagefalloff_maxdist 0 -set g_balance_nex_primary_damagefalloff_halflife 0 -set g_balance_nex_primary_damagefalloff_forcehalflife 0 +set g_balance_nex_primary_force 400 +set g_balance_nex_primary_refire 1.5 +set g_balance_nex_primary_animtime 0.45 +set g_balance_nex_primary_ammo 6 +set g_balance_nex_primary_damagefalloff_mindist 0 // 1000 For tZork ;3 +set g_balance_nex_primary_damagefalloff_maxdist 0 // 3000 +set g_balance_nex_primary_damagefalloff_halflife 0 // 1500 +set g_balance_nex_primary_damagefalloff_forcehalflife 0 // 1500 -set g_balance_nex_secondary 1 -set g_balance_nex_secondary_charge 1 -set g_balance_nex_secondary_charge_rate 0.4 -set g_balance_nex_secondary_chargepool 1 +set g_balance_nex_secondary 0 +set g_balance_nex_secondary_charge 0 +set g_balance_nex_secondary_charge_rate 0.1 +set g_balance_nex_secondary_chargepool 0 set g_balance_nex_secondary_chargepool_regen 0.15 set g_balance_nex_secondary_chargepool_pause_regen 1 set g_balance_nex_secondary_chargepool_pause_health_regen 1 @@ -473,80 +522,107 @@ set g_balance_nex_secondary_damage 0 set g_balance_nex_secondary_force 0 set g_balance_nex_secondary_refire 0 set g_balance_nex_secondary_animtime 0 -set g_balance_nex_secondary_ammo 0.2 // full charge pool is 1, so it depletes in 5 secs +set g_balance_nex_secondary_ammo 2 set g_balance_nex_secondary_damagefalloff_mindist 0 set g_balance_nex_secondary_damagefalloff_maxdist 0 set g_balance_nex_secondary_damagefalloff_halflife 0 set g_balance_nex_secondary_damagefalloff_forcehalflife 0 set g_balance_nex_charge 1 -set g_balance_nex_charge_mindmg 20 +set g_balance_nex_charge_mindmg 40 set g_balance_nex_charge_start 0.5 -set g_balance_nex_charge_rate 0.5 -set g_balance_nex_charge_limit 0.5 -set g_balance_nex_charge_rot_rate 0.1 -set g_balance_nex_charge_rot_pause 1 // Dont rot down until this long after release of charge button +set g_balance_nex_charge_rate 0.4 +set g_balance_nex_charge_animlimit 0.5 +set g_balance_nex_charge_limit 1 +set g_balance_nex_charge_rot_rate 0 +set g_balance_nex_charge_rot_pause 0 // Dont rot down until this long after release of charge button set g_balance_nex_charge_shot_multiplier 0 set g_balance_nex_charge_velocity_rate 0 -set g_balance_nex_charge_minspeed 600 -set g_balance_nex_charge_maxspeed 1000 +set g_balance_nex_charge_minspeed 400 +set g_balance_nex_charge_maxspeed 800 + +set g_balance_nex_reload_ammo 0 //default: 25 +set g_balance_nex_reload_time 2 // }}} // {{{ minstanex set g_balance_minstanex_refire 1 -set g_balance_minstanex_animtime 0.75 +set g_balance_minstanex_animtime 0.3 set g_balance_minstanex_ammo 10 +set g_balance_minstanex_laser_ammo 0 +set g_balance_minstanex_laser_animtime 0.3 +set g_balance_minstanex_laser_refire 0.7 +set g_balance_minstanex_reload_ammo 0 //default: 50 +set g_balance_minstanex_reload_time 2 // }}} // {{{ hagar -set g_balance_hagar_primary_damage 14 -set g_balance_hagar_primary_edgedamage 6 -set g_balance_hagar_primary_force 70 -set g_balance_hagar_primary_radius 115 -set g_balance_hagar_primary_spread 0.1 -set g_balance_hagar_primary_speed 1800 +set g_balance_hagar_primary_damage 25 +set g_balance_hagar_primary_edgedamage 12.5 +set g_balance_hagar_primary_force 100 +set g_balance_hagar_primary_health 15 +set g_balance_hagar_primary_damageforcescale 0 +set g_balance_hagar_primary_radius 65 +set g_balance_hagar_primary_spread 0.04 +set g_balance_hagar_primary_speed 2200 set g_balance_hagar_primary_lifetime 5 -set g_balance_hagar_primary_refire 0.12 +set g_balance_hagar_primary_refire 0.16667 // 6 rockets per second set g_balance_hagar_primary_ammo 1 set g_balance_hagar_secondary 1 -set g_balance_hagar_secondary_damage 14 -set g_balance_hagar_secondary_edgedamage 6 -set g_balance_hagar_secondary_force 70 -set g_balance_hagar_secondary_radius 125 -set g_balance_hagar_secondary_spread 0.15 -set g_balance_hagar_secondary_speed 1800 -set g_balance_hagar_secondary_lifetime_min 5 +set g_balance_hagar_secondary_load 1 +set g_balance_hagar_secondary_load_speed 0.5 +set g_balance_hagar_secondary_load_spread 0.075 +set g_balance_hagar_secondary_load_spread_bias 0.5 +set g_balance_hagar_secondary_load_max 4 +set g_balance_hagar_secondary_load_hold 4 +set g_balance_hagar_secondary_load_releasedeath 0 +set g_balance_hagar_secondary_load_abort 1 +set g_balance_hagar_secondary_load_linkexplode 0 +set g_balance_hagar_secondary_load_animtime 0.2 +set g_balance_hagar_secondary_damage 40 +set g_balance_hagar_secondary_edgedamage 20 +set g_balance_hagar_secondary_force 75 +set g_balance_hagar_secondary_health 15 +set g_balance_hagar_secondary_damageforcescale 0 +set g_balance_hagar_secondary_radius 80 +set g_balance_hagar_secondary_spread 0.05 +set g_balance_hagar_secondary_speed 2000 +set g_balance_hagar_secondary_lifetime_min 10 set g_balance_hagar_secondary_lifetime_rand 0 -set g_balance_hagar_secondary_refire 0.12 +set g_balance_hagar_secondary_refire 0.5 set g_balance_hagar_secondary_ammo 1 +set g_balance_hagar_reload_ammo 0 //default: 25 +set g_balance_hagar_reload_time 2 // }}} // {{{ rocketlauncher -set g_balance_rocketlauncher_damage 82 -set g_balance_rocketlauncher_edgedamage 32 -set g_balance_rocketlauncher_force 350 -set g_balance_rocketlauncher_radius 130 -set g_balance_rocketlauncher_speed 1400 -set g_balance_rocketlauncher_speedaccel 1400 -set g_balance_rocketlauncher_speedstart 800 -set g_balance_rocketlauncher_lifetime 5 -set g_balance_rocketlauncher_refire 1 -set g_balance_rocketlauncher_animtime 0.4 -set g_balance_rocketlauncher_ammo 3 -set g_balance_rocketlauncher_health 0 -set g_balance_rocketlauncher_damageforcescale 0 -set g_balance_rocketlauncher_detonatedelay 0.05 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time -set g_balance_rocketlauncher_guiderate 42 // max degrees per second +set g_balance_rocketlauncher_damage 80 +set g_balance_rocketlauncher_edgedamage 40 +set g_balance_rocketlauncher_force 400 +set g_balance_rocketlauncher_radius 110 +set g_balance_rocketlauncher_speed 1300 +set g_balance_rocketlauncher_speedaccel 1300 +set g_balance_rocketlauncher_speedstart 1000 +set g_balance_rocketlauncher_lifetime 10 +set g_balance_rocketlauncher_refire 1.1 +set g_balance_rocketlauncher_animtime 0.35 +set g_balance_rocketlauncher_ammo 4 +set g_balance_rocketlauncher_health 30 // 30 // 5 hitpoints above maximum laser value -- this way lasers can't blow it up, but grenadelauncher still can most the time. +set g_balance_rocketlauncher_damageforcescale 1 // low damage force scale so that it can still be affected by other hits, but not so much that it does a 90 degree turn +set g_balance_rocketlauncher_detonatedelay 0.02 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time +set g_balance_rocketlauncher_guiderate 90 // max degrees per second set g_balance_rocketlauncher_guideratedelay 0.01 // immediate set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic) -set g_balance_rocketlauncher_guidedelay 0.15 // delay before guiding kicks in +set g_balance_rocketlauncher_guidedelay 0.2 // delay before guiding kicks in set g_balance_rocketlauncher_guidestop 0 // stop guiding when firing again -set g_balance_rocketlauncher_remote_damage 60 -set g_balance_rocketlauncher_remote_edgedamage 20 -set g_balance_rocketlauncher_remote_radius 120 -set g_balance_rocketlauncher_remote_force 350 +set g_balance_rocketlauncher_remote_damage 70 +set g_balance_rocketlauncher_remote_edgedamage 35 +set g_balance_rocketlauncher_remote_radius 110 +set g_balance_rocketlauncher_remote_force 400 +set g_balance_rocketlauncher_reload_ammo 0 //default: 25 +set g_balance_rocketlauncher_reload_time 2 // }}} // {{{ porto set g_balance_porto_primary_refire 1.5 set g_balance_porto_primary_animtime 0.3 -set g_balance_porto_primary_speed 2000 +set g_balance_porto_primary_speed 1000 set g_balance_porto_primary_lifetime 5 set g_balance_portal_health 200 // these get recharged whenever the portal is used set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used @@ -562,7 +638,7 @@ set g_balance_hook_secondary_damage 25 // not much set g_balance_hook_secondary_edgedamage 5 // not much set g_balance_hook_secondary_radius 500 // LOTS set g_balance_hook_secondary_force -2000 // LOTS -set g_balance_hook_secondary_ammo 50 // a whole pack +set g_balance_hook_secondary_ammo 30 // a whole pack set g_balance_hook_secondary_lifetime 5 // infinite set g_balance_hook_secondary_speed 0 // not much throwing set g_balance_hook_secondary_gravity 5 // fast falling @@ -570,72 +646,79 @@ set g_balance_hook_secondary_refire 3 // don't drop too many bombs... set g_balance_hook_secondary_animtime 0.3 // good shoot anim set g_balance_hook_secondary_power 3 // effect behaves like a square function set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds +set g_balance_hook_secondary_health 15 +set g_balance_hook_secondary_damageforcescale 0 // }}} -// {{{ hlac +// {{{ hlac // TO BE REMOVED set g_balance_hlac_primary_spread_min 0.01 -set g_balance_hlac_primary_spread_max 0.075 -set g_balance_hlac_primary_spread_add 0.001 +set g_balance_hlac_primary_spread_max 0.25 +set g_balance_hlac_primary_spread_add 0.0045 set g_balance_hlac_primary_spread_crouchmod 0.25 -set g_balance_hlac_primary_damage 15 -set g_balance_hlac_primary_edgedamage 10 -set g_balance_hlac_primary_force 70 -set g_balance_hlac_primary_radius 40 +set g_balance_hlac_primary_damage 18 +set g_balance_hlac_primary_edgedamage 9 +set g_balance_hlac_primary_force 90 +set g_balance_hlac_primary_radius 70 set g_balance_hlac_primary_speed 9000 set g_balance_hlac_primary_lifetime 5 -set g_balance_hlac_primary_refire 0.1 -set g_balance_hlac_primary_animtime 0.3 +set g_balance_hlac_primary_refire 0.15 +set g_balance_hlac_primary_animtime 0.4 set g_balance_hlac_primary_ammo 1 set g_balance_hlac_secondary 1 set g_balance_hlac_secondary_spread 0.15 set g_balance_hlac_secondary_spread_crouchmod 0.5 -set g_balance_hlac_secondary_damage 20 -set g_balance_hlac_secondary_edgedamage 13 -set g_balance_hlac_secondary_force 100 -set g_balance_hlac_secondary_radius 45 +set g_balance_hlac_secondary_damage 15 +set g_balance_hlac_secondary_edgedamage 7.5 +set g_balance_hlac_secondary_force 90 +set g_balance_hlac_secondary_radius 70 set g_balance_hlac_secondary_speed 9000 set g_balance_hlac_secondary_lifetime 5 -set g_balance_hlac_secondary_refire 0.8 -set g_balance_hlac_secondary_animtime 0.6 -set g_balance_hlac_secondary_ammo 4 +set g_balance_hlac_secondary_refire 1 +set g_balance_hlac_secondary_animtime 0.3 +set g_balance_hlac_secondary_ammo 10 set g_balance_hlac_secondary_shots 6 + +set g_balance_hlac_reload_ammo 0 //default: 20 +set g_balance_hlac_reload_time 2 // }}} -// {{{ campingrifle -set g_balance_campingrifle_magazinecapacity 8 // make it pretty much useless in close combat -set g_balance_campingrifle_reloadtime 2 // matches reload anim -set g_balance_campingrifle_auto_reload_on_switch 0 -set g_balance_campingrifle_bursttime 0 -set g_balance_campingrifle_primary_tracer 1 -set g_balance_campingrifle_primary_damage 60 -set g_balance_campingrifle_primary_headshotaddeddamage 100 -set g_balance_campingrifle_primary_spread 0 -set g_balance_campingrifle_primary_force 2 -set g_balance_campingrifle_primary_speed 40000 -set g_balance_campingrifle_primary_lifetime 5 -set g_balance_campingrifle_primary_refire 1.5 -set g_balance_campingrifle_primary_animtime 1.4 -set g_balance_campingrifle_primary_ammo 10 -set g_balance_campingrifle_primary_bulletconstant 110 // 62.2qu -set g_balance_campingrifle_primary_burstcost 0 -set g_balance_campingrifle_primary_bullethail 0 // empty magazine on shot -set g_balance_campingrifle_secondary 1 -set g_balance_campingrifle_secondary_tracer 0 -set g_balance_campingrifle_secondary_damage 42 -set g_balance_campingrifle_secondary_headshotaddeddamage 70 -set g_balance_campingrifle_secondary_spread 0 -set g_balance_campingrifle_secondary_force 2 -set g_balance_campingrifle_secondary_speed 20000 -set g_balance_campingrifle_secondary_lifetime 5 -set g_balance_campingrifle_secondary_refire 1.5 -set g_balance_campingrifle_secondary_animtime 1.4 -set g_balance_campingrifle_secondary_ammo 10 -set g_balance_campingrifle_secondary_bulletconstant 110 // 15.5qu -set g_balance_campingrifle_secondary_burstcost 0 -set g_balance_campingrifle_secondary_bullethail 0 // empty magazine on shot +// {{{ rifle +set g_balance_rifle_bursttime 0 +set g_balance_rifle_primary_tracer 1 +set g_balance_rifle_primary_shots 1 +set g_balance_rifle_primary_damage 40 +set g_balance_rifle_primary_headshotaddeddamage 40 +set g_balance_rifle_primary_spread 0 +set g_balance_rifle_primary_force 100 +set g_balance_rifle_primary_speed 40000 +set g_balance_rifle_primary_lifetime 5 +set g_balance_rifle_primary_refire 1.2 +set g_balance_rifle_primary_animtime 0.4 +set g_balance_rifle_primary_ammo 10 +set g_balance_rifle_primary_bulletconstant 110 // 62.2qu +set g_balance_rifle_primary_burstcost 0 +set g_balance_rifle_primary_bullethail 0 // empty magazine on shot +set g_balance_rifle_secondary 1 +set g_balance_rifle_secondary_reload 0 +set g_balance_rifle_secondary_tracer 0 +set g_balance_rifle_secondary_shots 4 +set g_balance_rifle_secondary_damage 10 +set g_balance_rifle_secondary_headshotaddeddamage 20 +set g_balance_rifle_secondary_spread 0.04 +set g_balance_rifle_secondary_force 50 +set g_balance_rifle_secondary_speed 20000 +set g_balance_rifle_secondary_lifetime 5 +set g_balance_rifle_secondary_refire 0.9 +set g_balance_rifle_secondary_animtime 0.3 +set g_balance_rifle_secondary_ammo 10 +set g_balance_rifle_secondary_bulletconstant 110 // 15.5qu +set g_balance_rifle_secondary_burstcost 0 +set g_balance_rifle_secondary_bullethail 0 // empty magazine on shot +set g_balance_rifle_reload_ammo 80 //default: 80 +set g_balance_rifle_reload_time 2 // }}} // {{{ tuba set g_balance_tuba_refire 0.05 @@ -647,27 +730,28 @@ set g_balance_tuba_damage 5 set g_balance_tuba_edgedamage 0 set g_balance_tuba_radius 200 set g_balance_tuba_force 40 +set g_balance_tuba_pitchstep 6 // }}} -// {{{ fireball -set g_balance_fireball_primary_ammo 40 -set g_balance_fireball_primary_animtime 0.15 +// {{{ fireball // this is a superweapon -- lets make it behave as one. +set g_balance_fireball_primary_ammo 20 +set g_balance_fireball_primary_animtime 0.2 set g_balance_fireball_primary_bfgdamage 100 set g_balance_fireball_primary_bfgforce 0 set g_balance_fireball_primary_bfgradius 1000 set g_balance_fireball_primary_damage 200 -set g_balance_fireball_primary_damageforcescale 4 -set g_balance_fireball_primary_edgedamage 0 -set g_balance_fireball_primary_force 700 -set g_balance_fireball_primary_health 50 +set g_balance_fireball_primary_damageforcescale 0 +set g_balance_fireball_primary_edgedamage 50 +set g_balance_fireball_primary_force 600 +set g_balance_fireball_primary_health 0 set g_balance_fireball_primary_laserburntime 0.5 set g_balance_fireball_primary_laserdamage 80 set g_balance_fireball_primary_laseredgedamage 20 set g_balance_fireball_primary_laserradius 256 set g_balance_fireball_primary_lifetime 15 set g_balance_fireball_primary_radius 200 -set g_balance_fireball_primary_refire 5 +set g_balance_fireball_primary_refire 2 set g_balance_fireball_primary_refire2 0 -set g_balance_fireball_primary_speed 650 +set g_balance_fireball_primary_speed 1200 set g_balance_fireball_primary_spread 0 set g_balance_fireball_secondary_ammo 5 set g_balance_fireball_secondary_animtime 0.3 @@ -680,13 +764,16 @@ set g_balance_fireball_secondary_laserdamage 50 set g_balance_fireball_secondary_laseredgedamage 20 set g_balance_fireball_secondary_laserradius 110 set g_balance_fireball_secondary_lifetime 7 -set g_balance_fireball_secondary_refire 2 +set g_balance_fireball_secondary_refire 1.5 set g_balance_fireball_secondary_speed 900 set g_balance_fireball_secondary_speed_up 100 set g_balance_fireball_secondary_speed_z 0 set g_balance_fireball_secondary_spread 0 +set g_balance_fireball_reload_ammo 0 //default: 100 +set g_balance_fireball_reload_time 2 // }}} // {{{ seeker +set g_balance_seeker_type 1 // 0 = old seeker, 1 = new seeker. THIS IS A TEMPORARY CVAR FOR TESTING, will be removed later. set g_balance_seeker_flac_ammo 0.5 set g_balance_seeker_flac_animtime 0.1 set g_balance_seeker_flac_damage 15 @@ -700,39 +787,42 @@ set g_balance_seeker_flac_speed 3000 set g_balance_seeker_flac_speed_up 1000 set g_balance_seeker_flac_speed_z 0 set g_balance_seeker_flac_spread 0.4 -set g_balance_seeker_missile_accel 1400 +set g_balance_seeker_tag_ammo 1 +set g_balance_seeker_tag_animtime 0.2 +set g_balance_seeker_tag_damageforcescale 0 +set g_balance_seeker_tag_health 0 +set g_balance_seeker_tag_lifetime 15 +set g_balance_seeker_tag_refire 0.75 // LOG: 0.7 -> 0.75 +set g_balance_seeker_tag_speed 5000 +set g_balance_seeker_tag_spread 0 +set g_balance_seeker_tag_tracker_lifetime 10 +set g_balance_seeker_missile_accel 1500 set g_balance_seeker_missile_ammo 2 -set g_balance_seeker_missile_animtime 0.3 -set g_balance_seeker_missile_count 8 -set g_balance_seeker_missile_damage 15 +set g_balance_seeker_missile_animtime 0.2 +set g_balance_seeker_missile_count 3 // LOG: 8 -> 3 +set g_balance_seeker_missile_damage 16 // LOG: 15 -> 30 set g_balance_seeker_missile_damageforcescale 4 -set g_balance_seeker_missile_decel 1400 +set g_balance_seeker_missile_decel 6000 set g_balance_seeker_missile_delay 0.25 -set g_balance_seeker_missile_edgedamage 10 -set g_balance_seeker_missile_force 250 -set g_balance_seeker_missile_health 5 +set g_balance_seeker_missile_edgedamage 8 +set g_balance_seeker_missile_force 50 // LOG: 100 -> 150 +set g_balance_seeker_missile_health 1 set g_balance_seeker_missile_lifetime 15 set g_balance_seeker_missile_proxy 0 set g_balance_seeker_missile_proxy_delay 0.2 set g_balance_seeker_missile_proxy_maxrange 45 -set g_balance_seeker_missile_radius 80 -set g_balance_seeker_missile_refire 0.5 -set g_balance_seeker_missile_smart 1 +set g_balance_seeker_missile_radius 70 +set g_balance_seeker_missile_refire 0.25 +set g_balance_seeker_missile_smart 0 set g_balance_seeker_missile_smart_mindist 800 set g_balance_seeker_missile_smart_trace_max 2500 set g_balance_seeker_missile_smart_trace_min 1000 -set g_balance_seeker_missile_speed 700 -set g_balance_seeker_missile_speed_up 300 +set g_balance_seeker_missile_speed 1500 +set g_balance_seeker_missile_speed_up 0 set g_balance_seeker_missile_speed_z 0 -set g_balance_seeker_missile_speed_max 1400 +set g_balance_seeker_missile_speed_max 2000 // LOG: 1400 -> 1300 set g_balance_seeker_missile_spread 0 -set g_balance_seeker_missile_turnrate 0.65 -set g_balance_seeker_tag_ammo 1 -set g_balance_seeker_tag_animtime 0.3 -set g_balance_seeker_tag_damageforcescale 4 -set g_balance_seeker_tag_health 5 -set g_balance_seeker_tag_lifetime 15 -set g_balance_seeker_tag_refire 0.7 -set g_balance_seeker_tag_speed 5000 -set g_balance_seeker_tag_spread 0 +set g_balance_seeker_missile_turnrate 0.15 +set g_balance_seeker_reload_ammo 0 //default: 15 +set g_balance_seeker_reload_time 2 // End new seeker diff --git a/balancetZork.cfg b/balancetZork.cfg deleted file mode 100644 index bff56f2338..0000000000 --- a/balancetZork.cfg +++ /dev/null @@ -1,756 +0,0 @@ -// {{{ starting gear -set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_minelayer -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_hlac -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_campingrifle -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_seeker -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_balance_health_start 125 -set g_balance_armor_start 0 -set g_start_ammo_shells 20 -set g_start_ammo_nails 0 -set g_start_ammo_rockets 0 -set g_start_ammo_cells 0 -set g_start_ammo_fuel 0 -set g_warmup_start_health 200 "starting values when being in warmup-stage" -set g_warmup_start_armor 100 "starting values when being in warmup-stage" -set g_warmup_start_ammo_shells 50 "starting values when being in warmup-stage" -set g_warmup_start_ammo_nails 150 "starting values when being in warmup-stage" -set g_warmup_start_ammo_rockets 50 "starting values when being in warmup-stage" -set g_warmup_start_ammo_cells 50 "starting values when being in warmup-stage" -set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage" -set g_lms_start_health 200 -set g_lms_start_armor 100 -set g_lms_start_ammo_shells 30 -set g_lms_start_ammo_nails 250 -set g_lms_start_ammo_rockets 100 -set g_lms_start_ammo_cells 200 -set g_lms_start_ammo_fuel 0 -set g_balance_nix_roundtime 25 -set g_balance_nix_incrtime 1.6 -set g_balance_nix_ammo_shells 15 -set g_balance_nix_ammo_nails 45 -set g_balance_nix_ammo_rockets 15 -set g_balance_nix_ammo_cells 15 -set g_balance_nix_ammo_fuel 0 -set g_balance_nix_ammoincr_shells 2 -set g_balance_nix_ammoincr_nails 6 -set g_balance_nix_ammoincr_rockets 2 -set g_balance_nix_ammoincr_cells 2 -set g_balance_nix_ammoincr_fuel 2 -// }}} - -// {{{ pickup items -set g_pickup_ammo_anyway 1 -set g_pickup_weapons_anyway 1 - -set g_pickup_shells 20 -set g_pickup_shells_weapon 10 -set g_pickup_shells_max 50 - -set g_pickup_nails 60 -set g_pickup_nails_weapon 60 -set g_pickup_nails_max 300 - -set g_pickup_rockets 25 -set g_pickup_rockets_weapon 15 -set g_pickup_rockets_max 150 - -set g_pickup_cells 30 -set g_pickup_cells_weapon 20 -set g_pickup_cells_max 300 - -set g_pickup_fuel 25 -set g_pickup_fuel_weapon 15 -set g_pickup_fuel_jetpack 50 -set g_pickup_fuel_max 999 - -set g_pickup_armorsmall 5 -set g_pickup_armorsmall_max 999 -set g_pickup_armorsmall_anyway 0 - -set g_pickup_armormedium 25 -set g_pickup_armormedium_max 100 -set g_pickup_armormedium_anyway 0 - -set g_pickup_armorbig 50 -set g_pickup_armorbig_max 150 -set g_pickup_armorbig_anyway 0 - -set g_pickup_armorlarge 100 -set g_pickup_armorlarge_max 999 -set g_pickup_armorlarge_anyway 0 - -set g_pickup_healthsmall 5 -set g_pickup_healthsmall_max 999 -set g_pickup_healthsmall_anyway 0 - -set g_pickup_healthmedium 25 -set g_pickup_healthmedium_max 100 -set g_pickup_healthmedium_anyway 0 - -set g_pickup_healthlarge 50 -set g_pickup_healthlarge_max 150 -set g_pickup_healthlarge_anyway 0 - -set g_pickup_healthmega 100 -set g_pickup_healthmega_max 999 -set g_pickup_healthmega_anyway 0 - -set g_pickup_respawntime_short 15 -set g_pickup_respawntime_medium 20 -set g_pickup_respawntime_long 30 -set g_pickup_respawntime_powerup 120 -set g_pickup_respawntime_weapon 20 -set g_pickup_respawntime_ammo 15 - -set g_pickup_respawntimejitter_short 0 -set g_pickup_respawntimejitter_medium 0 -set g_pickup_respawntimejitter_long 0 -set g_pickup_respawntimejitter_powerup 10 -set g_pickup_respawntimejitter_weapon 0 -set g_pickup_respawntimejitter_ammo 0 -// }}} - -// {{{ regen/rot -set g_balance_health_regen 0.1 -set g_balance_health_regenlinear 0 -set g_balance_pause_health_regen 5 -set g_balance_pause_health_regen_spawn 0 -set g_balance_health_rot 0.1 -set g_balance_health_rotlinear 2.5 -set g_balance_pause_health_rot 4 -set g_balance_pause_health_rot_spawn 8 -set g_balance_health_regenstable 100 -set g_balance_health_rotstable 100 -set g_balance_health_limit 999 -set g_balance_armor_regen 0 -set g_balance_armor_regenlinear 0 -set g_balance_armor_rot 0.1 -set g_balance_armor_rotlinear 2.5 -set g_balance_pause_armor_rot 4 -set g_balance_pause_armor_rot_spawn 8 -set g_balance_armor_regenstable 100 -set g_balance_armor_rotstable 100 -set g_balance_armor_limit 999 -set g_balance_armor_blockpercent 0.7 -set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)" -set g_balance_fuel_regenlinear 0 -set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter -set g_balance_fuel_rot 0.05 -set g_balance_fuel_rotlinear 0 -set g_balance_pause_fuel_rot 4 -set g_balance_pause_fuel_rot_spawn 8 -set g_balance_fuel_regenstable 50 -set g_balance_fuel_rotstable 100 -set g_balance_fuel_limit 999 -// }}} - -// {{{ misc -set g_balance_selfdamagepercent 0.6 -set g_balance_weaponswitchdelay 0.15 -set g_weaponspeedfactor 1 "weapon projectile speed multiplier" -set g_weaponratefactor 1 "weapon fire rate multiplier" -set g_weapondamagefactor 1 "weapon damage multiplier" -set g_weaponforcefactor 1 "weapon force multiplier" -set g_weaponspreadfactor 1 "weapon spread multiplier" -set g_balance_firetransfer_time 0.9 -set g_balance_firetransfer_damage 0.8 -set g_throughfloor_damage 0.5 -set g_throughfloor_force 0.7 -set g_projectiles_newton_style 2 -// possible values: -// 0: absolute velocity projectiles (like Quake) -// 1: relative velocity projectiles, "Newtonian" (like Tribes 2) -// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard) -// 3: absolute velocity + player velocity component in shot direction (note: does NOT yield the right relative velocity, but may be good enough, but it is somewhat prone to sniper rockets) -// 4: just add the player velocity length to the absolute velocity (tZork's sniper rockets) -set g_projectiles_newton_style_2_minfactor 0.7 -set g_projectiles_newton_style_2_maxfactor 5 -set g_projectiles_spread_style 7 -// possible values: -// 0: forward + solid sphere (like Quake) - varies velocity -// 1: forward + flattened solid sphere -// 2: forward + solid circle -// 3: forward + normal distribution 3D - varies velocity -// 4: forward + normal distribution on a plane -// 5: forward + circle with 1-r falloff -// 6: forward + circle with 1-r^2 falloff -// 7: forward + circle with (1-r)(2-r) falloff -set g_balance_falldamage_deadminspeed 150 -set g_balance_falldamage_minspeed 800 -set g_balance_falldamage_factor 0.02 // maxspeed = minspeed + maxdamage / factor = 4550 -set g_balance_falldamage_maxdamage 75 -// }}} - -// {{{ powerups -set g_balance_powerup_invincible_takedamage 0.3 -set g_balance_powerup_invincible_time 30 -set g_balance_powerup_strength_damage 3 -set g_balance_powerup_strength_force 3 -set g_balance_powerup_strength_time 30 -set g_balance_powerup_strength_selfdamage 1.5 -set g_balance_powerup_strength_selfforce 1.5 -// }}} - -// {{{ jetpack/hook -set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack" -set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction" -set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)" -set g_jetpack_maxspeed_side 1500 "max speed of the jetpack in xy direction" -set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction" -set g_jetpack_fuel 8 "fuel per second for jetpack" -set g_jetpack_attenuation 2 "jetpack sound attenuation" - -set g_grappling_hook_tarzan 2 // 2: can also pull players -set g_balance_grapplehook_speed_fly 1800 -set g_balance_grapplehook_speed_pull 2000 -set g_balance_grapplehook_force_rubber 2000 -set g_balance_grapplehook_force_rubber_overstretch 1000 -set g_balance_grapplehook_length_min 50 -set g_balance_grapplehook_stretch 50 -set g_balance_grapplehook_airfriction 0.2 -set g_balance_grapplehook_health 130 -// }}} - -// {{{ weapon properties -// {{{ laser -set g_balance_laser_primary_damage 20 -set g_balance_laser_primary_edgedamage 10 -set g_balance_laser_primary_force 230 -set g_balance_laser_primary_radius 60 -set g_balance_laser_primary_speed 9000 -set g_balance_laser_primary_spread 0 -set g_balance_laser_primary_refire 0.6 -set g_balance_laser_primary_animtime 0.6 -set g_balance_laser_primary_lifetime 5 -set g_balance_laser_primary_shotangle 0 -set g_balance_laser_primary_delay 0 -set g_balance_laser_primary_gauntlet 0 -set g_balance_laser_primary_force_zscale 1.2 -set g_balance_laser_primary_force_velocitybias 0 -set g_balance_laser_secondary 0 // when 1, a secondary laser mode exists -set g_balance_laser_secondary_damage 35 -set g_balance_laser_secondary_edgedamage 10 -set g_balance_laser_secondary_force 400 -set g_balance_laser_secondary_radius 70 -set g_balance_laser_secondary_speed 9000 -set g_balance_laser_secondary_spread 0 -set g_balance_laser_secondary_refire 0.7 -set g_balance_laser_secondary_animtime 0.3 -set g_balance_laser_secondary_lifetime 30 -set g_balance_laser_secondary_shotangle 0 -set g_balance_laser_secondary_delay 0 -set g_balance_laser_secondary_gauntlet 0 -set g_balance_laser_secondary_force_zscale 1 -set g_balance_laser_secondary_force_velocitybias 0 -// }}} -// {{{ shotgun -set g_balance_shotgun_primary_bullets 10 -set g_balance_shotgun_primary_damage 5 -set g_balance_shotgun_primary_force 5 -set g_balance_shotgun_primary_spread 0.07 -set g_balance_shotgun_primary_refire 0.8 -set g_balance_shotgun_primary_animtime 0.2 -set g_balance_shotgun_primary_ammo 1 -set g_balance_shotgun_primary_speed 12000 -set g_balance_shotgun_primary_bulletconstant 75 // 3.8qu -set g_balance_shotgun_secondary 1 -set g_balance_shotgun_secondary_melee_delay 0.35 // match the anim -set g_balance_shotgun_secondary_melee_range 85 -set g_balance_shotgun_secondary_melee_swing 50 -set g_balance_shotgun_secondary_melee_time 0.1 -set g_balance_shotgun_secondary_damage 110 -set g_balance_shotgun_secondary_force 150 -set g_balance_shotgun_secondary_refire 1.1 -set g_balance_shotgun_secondary_animtime 1 -// }}} - -// {{{ uzi -set g_balance_uzi_mode 1 // Activates varible spread for sustained & burst mode secondary -set g_balance_uzi_spread_min 0.02 -set g_balance_uzi_spread_max 0.6 -set g_balance_uzi_spread_add 0.008 - -set g_balance_uzi_burst 3 // # of bullets in a burst (if set to 2 or more) -set g_balance_uzi_burst_refire 0.05 // refire between burst bullets -set g_balance_uzi_burst_refire2 0.4 // refire after burst -set g_balance_uzi_burst_spread 0.03 -set g_balance_uzi_burst_damage 18 // 90 dps (but 90 dmg deliverd in .25s) -set g_balance_uzi_burst_force 50 -set g_balance_uzi_burst_ammo 3 - -set g_balance_uzi_first 1 -set g_balance_uzi_first_damage 30 -set g_balance_uzi_first_force 50 -set g_balance_uzi_first_spread 0.015 -set g_balance_uzi_first_refire 0.2 -set g_balance_uzi_first_ammo 1 - -set g_balance_uzi_sustained_damage 14 // 120 dps -set g_balance_uzi_sustained_force 12 -set g_balance_uzi_sustained_spread 0.02 -set g_balance_uzi_sustained_refire 0.1 -set g_balance_uzi_sustained_ammo 1 - -set g_balance_uzi_speed 18000 -set g_balance_uzi_bulletconstant 115 // 13.1qu -// }}} -// {{{ mortar -set g_balance_grenadelauncher_primary_type 0 -set g_balance_grenadelauncher_primary_damage 50 -set g_balance_grenadelauncher_primary_edgedamage 30 -set g_balance_grenadelauncher_primary_force 250 -set g_balance_grenadelauncher_primary_radius 140 -set g_balance_grenadelauncher_primary_speed 2000 -set g_balance_grenadelauncher_primary_speed_up 200 -set g_balance_grenadelauncher_primary_speed_z 0 -set g_balance_grenadelauncher_primary_spread 0 -set g_balance_grenadelauncher_primary_lifetime 30 -set g_balance_grenadelauncher_primary_lifetime2 1 -set g_balance_grenadelauncher_primary_refire 0.8 -set g_balance_grenadelauncher_primary_animtime 0.3 -set g_balance_grenadelauncher_primary_ammo 2 -set g_balance_grenadelauncher_primary_health 25 -set g_balance_grenadelauncher_primary_damageforcescale 4 -set g_balance_grenadelauncher_primary_remote_minbouncecnt 0 - -set g_balance_grenadelauncher_secondary_type 1 -set g_balance_grenadelauncher_secondary_damage 60 -set g_balance_grenadelauncher_secondary_edgedamage 35 -set g_balance_grenadelauncher_secondary_force 300 -set g_balance_grenadelauncher_secondary_radius 140 -set g_balance_grenadelauncher_secondary_speed 1400 -set g_balance_grenadelauncher_secondary_speed_up 200 -set g_balance_grenadelauncher_secondary_speed_z 0 -set g_balance_grenadelauncher_secondary_spread 0 -set g_balance_grenadelauncher_secondary_lifetime 2.5 -set g_balance_grenadelauncher_secondary_lifetime2 0 -set g_balance_grenadelauncher_secondary_refire 0.7 -set g_balance_grenadelauncher_secondary_animtime 0.3 -set g_balance_grenadelauncher_secondary_ammo 2 -set g_balance_grenadelauncher_secondary_health 10 -set g_balance_grenadelauncher_secondary_damageforcescale 4 -set g_balance_grenadelauncher_secondary_remote_detonateprimary 0 - -set g_balance_grenadelauncher_bouncefactor 0.5 -set g_balance_grenadelauncher_bouncestop 0.075 -// }}} -// {{{ minelayer // TODO -set g_balance_minelayer_damage 35 -set g_balance_minelayer_edgedamage 30 -set g_balance_minelayer_force 250 -set g_balance_minelayer_radius 175 -set g_balance_minelayer_proximityradius 150 -set g_balance_minelayer_speed 750 -set g_balance_minelayer_lifetime 60 -set g_balance_minelayer_refire 1.5 -set g_balance_minelayer_animtime 0.4 -set g_balance_minelayer_ammo 5 -set g_balance_minelayer_health 15 -set g_balance_minelayer_limit 4 // 0 disables the limit -set g_balance_minelayer_protection 1 // don't explode if the mine would hurt the owner or a team mate -set g_balance_minelayer_damageforcescale 0 -set g_balance_minelayer_detonatedelay -1 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time -set g_balance_minelayer_time 0.5 -set g_balance_minelayer_remote_damage 45 -set g_balance_minelayer_remote_edgedamage 40 -set g_balance_minelayer_remote_radius 200 -set g_balance_minelayer_remote_force 300 -// }}} -// {{{ electro -set g_balance_electro_lightning 0 -set g_balance_electro_primary_damage 35 -set g_balance_electro_primary_edgedamage 0 -set g_balance_electro_primary_force 150 -set g_balance_electro_primary_force_up 0 -set g_balance_electro_primary_radius 155 -set g_balance_electro_primary_comboradius 0 -set g_balance_electro_primary_speed 2000 -set g_balance_electro_primary_spread 0 -set g_balance_electro_primary_lifetime 30 -set g_balance_electro_primary_refire 0.65 -set g_balance_electro_primary_animtime 0.3 -set g_balance_electro_primary_ammo 2 -set g_balance_electro_primary_range 0 -set g_balance_electro_primary_falloff_mindist 255 // 0.3 * radius -set g_balance_electro_primary_falloff_maxdist 850 -set g_balance_electro_primary_falloff_halflifedist 425 - -set g_balance_electro_secondary_damage 25 -set g_balance_electro_secondary_edgedamage 0 -set g_balance_electro_secondary_force 50 -set g_balance_electro_secondary_radius 25 -set g_balance_electro_secondary_speed 750 -set g_balance_electro_secondary_speed_up 150 -set g_balance_electro_secondary_speed_z 0 -set g_balance_electro_secondary_spread 0.025 -set g_balance_electro_secondary_lifetime 5 -set g_balance_electro_secondary_refire 0.1 -set g_balance_electro_secondary_refire2 2 -set g_balance_electro_secondary_animtime 0.15 -set g_balance_electro_secondary_ammo 2 -set g_balance_electro_secondary_health 10 -set g_balance_electro_secondary_damageforcescale 2 -set g_balance_electro_secondary_count 3 -set g_balance_electro_secondary_bouncefactor 0.5 -set g_balance_electro_secondary_bouncestop 0.075 - -set g_balance_electro_combo_damage 80 -set g_balance_electro_combo_edgedamage 10 -set g_balance_electro_combo_force 150 -set g_balance_electro_combo_radius 250 -set g_balance_electro_combo_comboradius 0 -set g_balance_electro_combo_speed 1000 -// }}} -// {{{ crylink -set g_balance_crylink_primary_damage 5 -set g_balance_crylink_primary_edgedamage 3 -set g_balance_crylink_primary_force 10 -set g_balance_crylink_primary_radius 15 -set g_balance_crylink_primary_speed 1500 -set g_balance_crylink_primary_spread 0.1 -set g_balance_crylink_primary_shots 8 -set g_balance_crylink_primary_bounces 1 -set g_balance_crylink_primary_refire 1 -set g_balance_crylink_primary_animtime 0.4 -set g_balance_crylink_primary_ammo 2 -set g_balance_crylink_primary_bouncedamagefactor 0.2 -set g_balance_crylink_primary_joinspread 0.1 -set g_balance_crylink_primary_jointime 0 -set g_balance_crylink_primary_joinexplode 1 //if != 0 do a extra damage pass when projectiles join -set g_balance_crylink_primary_joinexplode_damage 100 //Max demage (Determined by % of _primary_shots that joins) -set g_balance_crylink_primary_joinexplode_edgedamage 20 -set g_balance_crylink_primary_joinexplode_radius 200 -set g_balance_crylink_primary_joinexplode_force 400 -set g_balance_crylink_primary_linkexplode 0 -set g_balance_crylink_primary_middle_lifetime 5 -set g_balance_crylink_primary_middle_fadetime 0.25 -set g_balance_crylink_primary_other_lifetime 2 // range: 800 full, fades to 1300 -set g_balance_crylink_primary_other_fadetime 0.25 - -set g_balance_crylink_secondary 1 -set g_balance_crylink_secondary_damage 2 -set g_balance_crylink_secondary_edgedamage 0 -set g_balance_crylink_secondary_force -20 -set g_balance_crylink_secondary_radius 5 -set g_balance_crylink_secondary_speed 1600 -set g_balance_crylink_secondary_spread 0.03 -set g_balance_crylink_secondary_shots 3 -set g_balance_crylink_secondary_bounces 0 -set g_balance_crylink_secondary_refire 0.15 -set g_balance_crylink_secondary_animtime 0.15 -set g_balance_crylink_secondary_ammo 1 -set g_balance_crylink_secondary_bouncedamagefactor 0.5 -set g_balance_crylink_secondary_joinspread 0 -set g_balance_crylink_secondary_jointime 0 -set g_balance_crylink_secondary_joinexplode 0 -set g_balance_crylink_secondary_joinexplode_damage 0 -set g_balance_crylink_secondary_joinexplode_edgedamage 0 -set g_balance_crylink_secondary_joinexplode_radius 0 -set g_balance_crylink_secondary_joinexplode_force 0 -set g_balance_crylink_secondary_linkexplode 0 - -set g_balance_crylink_secondary_middle_lifetime 5 // range: 10000 full, fades to 10000 -set g_balance_crylink_secondary_middle_fadetime 5 -set g_balance_crylink_secondary_line_lifetime 2 // range: 4000 full, fades to 8000 -set g_balance_crylink_secondary_line_fadetime 2 -// }}} -// {{{ nex -set g_balance_nex_primary_damage 100 -set g_balance_nex_primary_force 600 -set g_balance_nex_primary_refire 1 -set g_balance_nex_primary_animtime 0.3 -set g_balance_nex_primary_ammo 5 -set g_balance_nex_primary_damagefalloff_mindist 0 -set g_balance_nex_primary_damagefalloff_maxdist 0 -set g_balance_nex_primary_damagefalloff_halflife 0 -set g_balance_nex_primary_damagefalloff_forcehalflife 0 - -set g_balance_nex_secondary 1 -set g_balance_nex_secondary_charge 1 -set g_balance_nex_secondary_charge_rate 0.55 -set g_balance_nex_secondary_chargepool 0 -set g_balance_nex_secondary_chargepool_regen 0.15 -set g_balance_nex_secondary_chargepool_pause_regen 1 -set g_balance_nex_secondary_chargepool_pause_health_regen 1 -set g_balance_nex_secondary_damage 100 -set g_balance_nex_secondary_force 600 -set g_balance_nex_secondary_refire 1.5 -set g_balance_nex_secondary_animtime 0.3 -set g_balance_nex_secondary_ammo 5 -set g_balance_nex_secondary_damagefalloff_mindist 0 -set g_balance_nex_secondary_damagefalloff_maxdist 0 -set g_balance_nex_secondary_damagefalloff_halflife 0 -set g_balance_nex_secondary_damagefalloff_forcehalflife 0 - -set g_balance_nex_charge 1 -set g_balance_nex_charge_mindmg 10 -set g_balance_nex_charge_start 0 -set g_balance_nex_charge_rate 0.35 -set g_balance_nex_charge_limit 0.5 -set g_balance_nex_charge_rot_rate 0.1 -set g_balance_nex_charge_rot_pause 1 // Dont rot down untill this long after release of charge button -set g_balance_nex_charge_shot_multiplier 0 -set g_balance_nex_charge_velocity_rate 0 -set g_balance_nex_charge_minspeed 400 -set g_balance_nex_charge_maxspeed 1000 -// }}} -// {{{ minstanex -set g_balance_minstanex_refire 1 -set g_balance_minstanex_animtime 0.3 -set g_balance_minstanex_ammo 10 -// }}} -// {{{ hagar -set g_balance_hagar_primary_damage 25 -set g_balance_hagar_primary_edgedamage 5 -set g_balance_hagar_primary_force 70 -set g_balance_hagar_primary_radius 60 -set g_balance_hagar_primary_spread 0.010 -set g_balance_hagar_primary_speed 2500 -set g_balance_hagar_primary_lifetime 30 -set g_balance_hagar_primary_refire 0.2 -set g_balance_hagar_primary_ammo 1 -set g_balance_hagar_secondary 1 -set g_balance_hagar_secondary_damage 30 -set g_balance_hagar_secondary_edgedamage 15 -set g_balance_hagar_secondary_force 50 -set g_balance_hagar_secondary_radius 65 -set g_balance_hagar_secondary_spread 0.015 -set g_balance_hagar_secondary_speed 1400 -set g_balance_hagar_secondary_lifetime_min 30 -set g_balance_hagar_secondary_lifetime_rand 0 -set g_balance_hagar_secondary_refire 0.15 -set g_balance_hagar_secondary_ammo 1 -// }}} -// {{{ rocketlauncher // TODO -set g_balance_rocketlauncher_damage 120 -set g_balance_rocketlauncher_edgedamage 25 -set g_balance_rocketlauncher_force 350 -set g_balance_rocketlauncher_radius 130 -set g_balance_rocketlauncher_speed 900 -set g_balance_rocketlauncher_speedaccel 0 -set g_balance_rocketlauncher_speedstart 900 -set g_balance_rocketlauncher_lifetime 9 -set g_balance_rocketlauncher_refire 1.2 -set g_balance_rocketlauncher_animtime 0.4 -set g_balance_rocketlauncher_ammo 3 -set g_balance_rocketlauncher_health 10 -set g_balance_rocketlauncher_damageforcescale 0 -set g_balance_rocketlauncher_detonatedelay -1 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time -set g_balance_rocketlauncher_guiderate 25 // max degrees per second -set g_balance_rocketlauncher_guideratedelay 0.01 // immediate -set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic) -set g_balance_rocketlauncher_guidedelay 0.15 // delay before guiding kicks in -set g_balance_rocketlauncher_guidestop 0 // stop guiding when firing again -set g_balance_rocketlauncher_remote_damage 90 -set g_balance_rocketlauncher_remote_edgedamage 20 -set g_balance_rocketlauncher_remote_radius 125 -set g_balance_rocketlauncher_remote_force 350 -// }}} -// {{{ porto -set g_balance_porto_primary_refire 1.5 -set g_balance_porto_primary_animtime 0.3 -set g_balance_porto_primary_speed 2000 -set g_balance_porto_primary_lifetime 30 -set g_balance_portal_health 200 // these get recharged whenever the portal is used -set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used -// }}} -// {{{ hook -set g_balance_hook_primary_fuel 5 // hook monkeys set 0 -set g_balance_hook_primary_refire 0 // hook monkeys set 0 -set g_balance_hook_primary_animtime 0.3 // good shoot anim -set g_balance_hook_primary_hooked_time_max 0 // infinite -set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free -set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked -set g_balance_hook_secondary_damage 25 // not much -set g_balance_hook_secondary_edgedamage 5 // not much -set g_balance_hook_secondary_radius 500 // LOTS -set g_balance_hook_secondary_force -2000 // LOTS -set g_balance_hook_secondary_ammo 50 // a whole pack -set g_balance_hook_secondary_lifetime 5 // infinite -set g_balance_hook_secondary_speed 0 // not much throwing -set g_balance_hook_secondary_gravity 5 // fast falling -set g_balance_hook_secondary_refire 3 // don't drop too many bombs... -set g_balance_hook_secondary_animtime 0.3 // good shoot anim -set g_balance_hook_secondary_power 3 // effect behaves like a square function -set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds -// }}} -// {{{ hlac -set g_balance_hlac_primary_spread_min 0.01 -set g_balance_hlac_primary_spread_max 0.6 -set g_balance_hlac_primary_spread_add 0.01 -set g_balance_hlac_primary_spread_crouchmod 0.5 - -set g_balance_hlac_primary_damage 22 -set g_balance_hlac_primary_edgedamage 2 -set g_balance_hlac_primary_force -100 -set g_balance_hlac_primary_radius 100 -set g_balance_hlac_primary_speed 15000 -set g_balance_hlac_primary_lifetime 3 - -set g_balance_hlac_primary_refire 0.1 -set g_balance_hlac_primary_animtime 0.4 -set g_balance_hlac_primary_ammo 1 - -set g_balance_hlac_secondary 1 -set g_balance_hlac_secondary_spread 0.2 -set g_balance_hlac_secondary_spread_crouchmod 0.5 - -set g_balance_hlac_secondary_damage 20 -set g_balance_hlac_secondary_edgedamage 3 -set g_balance_hlac_secondary_force 100 -set g_balance_hlac_secondary_radius 50 -set g_balance_hlac_secondary_speed 15000 -set g_balance_hlac_secondary_lifetime 3 -set g_balance_hlac_secondary_refire 1 -set g_balance_hlac_secondary_animtime 0.7 -set g_balance_hlac_secondary_ammo 10 -set g_balance_hlac_secondary_shots 6 -// }}} -// {{{ campingrifle -set g_balance_campingrifle_magazinecapacity 8 // make it pretty much useless in close combat -set g_balance_campingrifle_reloadtime 2 // matches reload anim -set g_balance_campingrifle_auto_reload_on_switch 0 -set g_balance_campingrifle_bursttime 0 -set g_balance_campingrifle_primary_tracer 1 -set g_balance_campingrifle_primary_damage 40 -set g_balance_campingrifle_primary_headshotaddeddamage 100 -set g_balance_campingrifle_primary_spread 0 -set g_balance_campingrifle_primary_force 2 -set g_balance_campingrifle_primary_speed 40000 -set g_balance_campingrifle_primary_lifetime 5 -set g_balance_campingrifle_primary_refire 0.65 -set g_balance_campingrifle_primary_animtime 0.6 -set g_balance_campingrifle_primary_ammo 10 -set g_balance_campingrifle_primary_bulletconstant 110 // 62.2qu -set g_balance_campingrifle_primary_burstcost 0 -set g_balance_campingrifle_primary_bullethail 0 // empty magazine on shot -set g_balance_campingrifle_secondary 1 -set g_balance_campingrifle_secondary_tracer 0 -set g_balance_campingrifle_secondary_damage 50 -set g_balance_campingrifle_secondary_headshotaddeddamage 50 // 50 damage only on head -set g_balance_campingrifle_secondary_spread 0 -set g_balance_campingrifle_secondary_force 2 -set g_balance_campingrifle_secondary_speed 20000 -set g_balance_campingrifle_secondary_lifetime 5 -set g_balance_campingrifle_secondary_refire 1.5 -set g_balance_campingrifle_secondary_animtime 0.6 -set g_balance_campingrifle_secondary_ammo 10 -set g_balance_campingrifle_secondary_bulletconstant 110 // 15.5qu -set g_balance_campingrifle_secondary_burstcost 0 -set g_balance_campingrifle_secondary_bullethail 0 // empty magazine on shot -// }}} -// {{{ tuba -set g_balance_tuba_refire 0.05 -set g_balance_tuba_animtime 0.05 -set g_balance_tuba_attenuation 0.5 -set g_balance_tuba_volume 1 -set g_balance_tuba_fadetime 0.25 -set g_balance_tuba_damage 5 -set g_balance_tuba_edgedamage 0 -set g_balance_tuba_radius 200 -set g_balance_tuba_force 40 -// }}} -// {{{ fireball -set g_balance_fireball_primary_ammo 40 -set g_balance_fireball_primary_animtime 0.15 -set g_balance_fireball_primary_bfgdamage 150 -set g_balance_fireball_primary_bfgforce 0 -set g_balance_fireball_primary_bfgradius 1000 -set g_balance_fireball_primary_damage 200 -set g_balance_fireball_primary_damageforcescale 4 -set g_balance_fireball_primary_edgedamage 0 -set g_balance_fireball_primary_force 700 -set g_balance_fireball_primary_health 50 -set g_balance_fireball_primary_laserburntime 0.5 -set g_balance_fireball_primary_laserdamage 80 -set g_balance_fireball_primary_laseredgedamage 20 -set g_balance_fireball_primary_laserradius 256 -set g_balance_fireball_primary_lifetime 15 -set g_balance_fireball_primary_radius 200 -set g_balance_fireball_primary_refire 5 -set g_balance_fireball_primary_refire2 0 -set g_balance_fireball_primary_speed 650 -set g_balance_fireball_primary_spread 0 -set g_balance_fireball_secondary_ammo 5 -set g_balance_fireball_secondary_animtime 0.3 -set g_balance_fireball_secondary_damage 40 -set g_balance_fireball_secondary_damageforcescale 4 -set g_balance_fireball_secondary_damagetime 5 -set g_balance_fireball_secondary_force 100 -set g_balance_fireball_secondary_laserburntime 0.5 -set g_balance_fireball_secondary_laserdamage 50 -set g_balance_fireball_secondary_laseredgedamage 20 -set g_balance_fireball_secondary_laserradius 110 -set g_balance_fireball_secondary_lifetime 7 -set g_balance_fireball_secondary_refire 2 -set g_balance_fireball_secondary_speed 900 -set g_balance_fireball_secondary_speed_up 100 -set g_balance_fireball_secondary_speed_z 0 -set g_balance_fireball_secondary_spread 0 -// }}} -// {{{ seeker -set g_balance_seeker_flac_ammo 0.5 -set g_balance_seeker_flac_animtime 0.1 -set g_balance_seeker_flac_damage 15 -set g_balance_seeker_flac_edgedamage 10 -set g_balance_seeker_flac_force 50 -set g_balance_seeker_flac_lifetime 0.05 -set g_balance_seeker_flac_lifetime_rand 0.02 -set g_balance_seeker_flac_radius 100 -set g_balance_seeker_flac_refire 0.1 -set g_balance_seeker_flac_speed 5000 -set g_balance_seeker_flac_speed_up 500 -set g_balance_seeker_flac_speed_z 0 -set g_balance_seeker_flac_spread 0.25 - -set g_balance_seeker_missile_accel 1400 -set g_balance_seeker_missile_ammo 2 -set g_balance_seeker_missile_animtime 0.3 -set g_balance_seeker_missile_count 4 -set g_balance_seeker_missile_damage 50 -set g_balance_seeker_missile_damageforcescale 2 -set g_balance_seeker_missile_decel 1400 -set g_balance_seeker_missile_delay 0.25 -set g_balance_seeker_missile_edgedamage 10 -set g_balance_seeker_missile_force 250 -set g_balance_seeker_missile_health 5 -set g_balance_seeker_missile_lifetime 15 -set g_balance_seeker_missile_proxy 0 -set g_balance_seeker_missile_proxy_delay 0.2 -set g_balance_seeker_missile_proxy_maxrange 45 -set g_balance_seeker_missile_radius 80 -set g_balance_seeker_missile_refire 0.5 -set g_balance_seeker_missile_smart 1 -set g_balance_seeker_missile_smart_mindist 800 -set g_balance_seeker_missile_smart_trace_max 2500 -set g_balance_seeker_missile_smart_trace_min 1000 -set g_balance_seeker_missile_speed 700 -set g_balance_seeker_missile_speed_up 300 -set g_balance_seeker_missile_speed_z 0 -set g_balance_seeker_missile_speed_max 1400 -set g_balance_seeker_missile_spread 0 -set g_balance_seeker_missile_turnrate 0.65 - -set g_balance_seeker_tag_ammo 1 -set g_balance_seeker_tag_animtime 0.3 -set g_balance_seeker_tag_damageforcescale 4 -set g_balance_seeker_tag_health 5 -set g_balance_seeker_tag_lifetime 15 -set g_balance_seeker_tag_refire 1 -set g_balance_seeker_tag_speed 9000 -set g_balance_seeker_tag_spread 0 -// End new seeker diff --git a/check-cvars.sh b/check-cvars.sh new file mode 100755 index 0000000000..78985b8194 --- /dev/null +++ b/check-cvars.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +errord=false + +check_files() +{ + countw=`awk ''"$3"' { print $2; }' "$1" | sort -u | tr -d '\r' | git hash-object --stdin | cut -c 1-32` + for b in $2; do + countb=`awk ''"$3"' { print $2; }' "$b" | sort -u | tr -d '\r' | git hash-object --stdin | cut -c 1-32` + if [ "$countw" != "$countb" ]; then + echo "Mismatch between "$1" and $b. Aborting." + echo "Differences are:" + echo "< missing in $b" + echo "> must get removed from $b" + A=`mktemp || echo a.tmp` + B=`mktemp || echo b.tmp` + awk ''"$3"' { print $2; }' "$1" | sort -u | tr -d '\r' > "$A" + awk ''"$3"' { print $2; }' "$b" | sort -u | tr -d '\r' > "$B" + diff "$A" "$B" | grep '^[<>]' | sort + rm -f "$A" "$B" + errord=true + fi + done +} + +check_files "balanceXonotic.cfg" "balance*.cfg" "/^seta? g_/" +check_files "_hud_descriptions.cfg" "hud_*.cfg" "/^seta? hud_/" + +if $errord; then + echo "Please wait for 30 seconds, so you have had enough time to read this..." + sleep 30 +fi diff --git a/check-translations.sh b/check-translations.sh new file mode 100755 index 0000000000..99882291af --- /dev/null +++ b/check-translations.sh @@ -0,0 +1,174 @@ +#!/bin/sh + +case "$1" in + pot) + mode=pot + mail=false + ;; + po) + mode=po + mail=true + language= + ;; + '') + echo "Sorry, you are not supposed to use this script." + echo "This script is solely for use by the Xonotic Core Team." + echo "Unauthorized use of it can cause HIGHLY annoying merge" + echo "conflicts." + exit 1 + ;; + *) + mode=po + mail=false + language=$1 + ;; +esac + +for VM in menu csprogs; do + case "$VM" in + csprogs) + VMD=client + ;; + *) + VMD=$VM + ;; + esac + + if [ x"$mode" = x"pot" ]; then + { + find qcsrc/"$VMD" -type f -not -name \*.po -not -name \*.txt + find qcsrc/common -type f -not -name \*.po -not -name \*.txt + if [ x"$VM" = x"csprogs" ]; then + find qcsrc/server -type f -name w_\*.qc + elif [ x"$VM" = x"menu" ]; then + find qcsrc/server -type f -name w_\*.qc | xargs grep ^REGISTER_WEAPON > weapons.qc.tmp + echo "weapons.qc.tmp" + fi + } | xgettext -LC -k_ -f- --from-code utf-8 -o "$VM".dat.pot >&2 + fi + + if [ x"$mode" = x"po" ]; then + for X in "$VM".dat.*.po; do + [ -f "$X" ] || continue + if [ -n "$language" ]; then + if [ x"${X#*.dat.}" != x"$language.po" ]; then + continue + fi + fi + for Y in ~/check-translations/"$X".*; do + [ -f "$Y" ] || continue + msgcat -F --use-first "$Y" "$X" > "$X".new + mv "$X".new "$X" + done + msgmerge -F -U "$X" "$VM".dat.pot >&2 + msgattrib --untranslated "$X" | grep . > "$X".untranslated || rm -f "$X".untranslated + msgattrib --fuzzy "$X" | grep . > "$X".fuzzy || rm -f "$X".fuzzy + nu=$((`grep -c ^#: "$X".untranslated` + 0)) + nf=$((`grep -c ^#: "$X".fuzzy` + 0)) + n=$(($nu + $nf)) + if [ $n -gt 0 ]; then + echo "TODO for translation $X:" + echo "Untranslated: $nu" + echo "Fuzzy: $nf" + ltr=`grep '^"Last-Translator: ' "$X" | cut -d ' ' -f 2- | cut -d '\\' -f 1 | egrep -v '|'` + ltm=`grep '^"Language-Team: ' "$X" | cut -d ' ' -f 2- | cut -d '\\' -f 1 | egrep -v '|'` + echo "Translators: $ltr, $ltm" + case "$ltr" in + '') + to=$ltm + cc= + ;; + *) + to=$ltr + if [ x"$ltr" = x"$ltm" ]; then + cc= + else + cc=$ltm + fi + ;; + esac + if [ -n "$to" ]; then + echo "To: $to" + fi + if [ -n "$cc" ]; then + echo "Cc: $cc" + fi + if [ -n "$to" ]; then + while $mail; do + echo "Send mail? [y/n]" + read -r yesno + case "$yesno" in + y) + attach= + if [ $nu -gt 0 ]; then + attach="$attach $X.untranslated" + fi + if [ $nf -gt 0 ]; then + attach="$attach $X.fuzzy" + fi + { + cat </dev/null 2>&1 + done + fi +done diff --git a/commands.cfg b/commands.cfg new file mode 100644 index 0000000000..1f7e684588 --- /dev/null +++ b/commands.cfg @@ -0,0 +1,292 @@ +// ================================================================= +// Master config for managing various command aliases and settings +// ================================================================= + +// Execute commands based on whether it is dedicated a server or a client. +alias "_detect_dedicated_$qport" "${* asis}" +alias "_detect_dedicated_0" "" +alias _if_dedicated "_detect_dedicated_$qport ${* asis}" +alias if_client "${* asis}" +alias if_dedicated "${* asis}" +_if_dedicated alias if_client "" +if_client alias if_dedicated "" + +if_dedicated "alias" qc_cmd_sv "sv_cmd $$*" +if_client "alias" qc_cmd_sv "echo This command only works on servers: sv_cmd $${* !}" +if_dedicated "alias" qc_cmd_cl "echo This command only works on clients: cl_cmd $${* !}" +if_client "alias" qc_cmd_cl "cl_cmd $$*" +if_dedicated "alias" qc_cmd_cmd "echo This command only works on clients: cmd $${* !}" +if_client "alias" qc_cmd_cmd "cmd $$*" + +if_dedicated "alias" qc_cmd_svmenu "sv_cmd $$*" +if_client "alias" qc_cmd_svmenu "menu_cmd $$*" +if_dedicated "alias" qc_cmd_svcl "sv_cmd $$*" +if_client "alias" qc_cmd_svcl "cl_cmd $$*" +if_dedicated "alias" qc_cmd_svcmd "sv_cmd $$*" +if_client "alias" qc_cmd_svcmd "cmd $$*" + +if_dedicated "alias" help "sv_cmd help" +if_client "alias" help "cl_cmd help; cmd help" + + +// ======== +// common +// ======== +// networked/server common commands +alias cvar_changes "qc_cmd_svcmd cvar_changes ${* ?}" // Prints a list of all changed server cvars +alias cvar_purechanges "qc_cmd_svcmd cvar_purechanges ${* ?}" // Prints a list of all changed gameplay cvars +alias info "qc_cmd_svcmd info ${* ?}" // Request for unique server information set up by admin +alias ladder "qc_cmd_svcmd ladder ${* ?}" // Get information about top players if supported +alias lsmaps "qc_cmd_svcmd lsmaps ${* ?}" // List maps which can be used with the current game mode +alias lsnewmaps "qc_cmd_svcmd lsnewmaps ${* ?}" // List maps which have no records or are seemingly unplayed yet +alias printmaplist "qc_cmd_svcmd printmaplist ${* ?}" // Display full server maplist reply +alias rankings "qc_cmd_svcmd rankings ${* ?}" // Print information about rankings +alias records "qc_cmd_svcmd records ${* ?}" // List top 10 records for the current map +alias teamstatus "qc_cmd_svcmd teamstatus ${* ?}" // Show information about player and team scores +alias time "qc_cmd_svcmd time ${* ?}" // Print different formats/readouts of time +alias timein "qc_cmd_svcmd timein ${* ?}" // Resume the game from being paused with a timeout +alias timeout "qc_cmd_svcmd timeout ${* ?}" // Call a timeout which pauses the game for certain amount of time unless unpaused +alias vote "qc_cmd_svcmd vote ${* ?}" // Request an action to be voted upon by players +alias who "qc_cmd_svcmd who ${* ?}" // Display detailed client information about all players + +// generic commands (across all programs) +alias addtolist "qc_cmd_svmenu addtolist ${* ?}" // Add a string to a cvar +alias dumpcommands "qc_cmd_svmenu dumpcommands ${* ?}" // Dump all commands on the program to *_cmd_dump.txt +alias maplist "qc_cmd_svmenu maplist ${* ?}" // Automatic control of maplist +alias removefromlist "qc_cmd_svmenu removefromlist ${* ?}" // Remove a string from a cvar +alias rpn "qc_cmd_svmenu rpn ${* ?}" // RPN calculator +//alias settemp "qc_cmd_svmenu settemp ${* ?}" // Temporarily set a value to a cvar which is restored later +//alias settemp_restore "qc_cmd_svmenu settemp_restore ${* ?}" // Restore all cvars set by settemp command + +// other aliases for common commands +alias g_hitplots_add "qc_cmd_svmenu rpn /g_hitplots_individuals g_hitplots_individuals ${1 !} union def" +alias g_hitplots_remove "qc_cmd_svmenu rpn /g_hitplots_individuals g_hitplots_individuals ${1 !} difference def" + +alias g_maplist_add "qc_cmd_svmenu maplist add ${* ?}" +alias g_maplist_remove "qc_cmd_svmenu maplist remove ${* ?}" +alias g_maplist_putfirst "qc_cmd_svmenu maplist remove ${* ?} ; qc_cmd maplist add ${* ?}" +alias g_maplist_shufflenow "qc_cmd_svmenu maplist shuffle" +alias g_maplist_cleanup "qc_cmd_svmenu maplist cleanup" // removes maps that don't exist from the map list + +alias addfav "qc_cmd_svmenu addtolist net_slist_favorites ${* ?}" +alias addvote "qc_cmd_svmenu addtolist sv_vote_commands ${* ?}" + + +// ======================== +// engine command aliases +// ======================== +alias bsp "ls maps/*.bsp" +alias chmap "changelevel ${* ?}" +alias clearmap "disconnect" +alias ply "playdemo $1" +alias rec "record demos/${1 !}" +alias search "apropos ${* ?}" +alias sv_loadconfig "exec $serverconfig" +alias sv_restart "say \"Server will restart at the end of the match, you will all be reconnected automatically. ${* ?} \"; quit_and_redirect self" +alias tdem "timedemo $1" + + +// =============================================== +// menu_cmd (menu command) - menu/command/menu_cmd.qc +// =============================================== +alias menu_showteamselect "menu_cmd directmenu TeamSelect" +alias menu_showhudexit "menu_cmd directmenu HUDExit" +alias menu_showhudoptions "menu_cmd directpanelhudmenu ${* ?}" +alias menu_showsandboxtools "menu_cmd directmenu SandboxTools" +alias menu_showquitdialog "menu_cmd directmenu Quit" + +// command executed before loading a map by the menu +// makes sure maxplayers is at least minplayers or bot_number + 1 +alias _menu_loadmap_prepare_maxpl "maxplayers $_menu_loadmap_maxplayers" +alias menu_loadmap_prepare "disconnect; wait; g_campaign 0; menu_cmd rpn /_menu_loadmap_maxplayers menu_maxplayers minplayers bot_number 1 add max max def; _menu_loadmap_prepare_maxpl; g_maplist_shufflenow" + + +// ========================================================== +// cl_cmd (client local command) - client/command/cl_cmd.qc +// ========================================================== +// commented out commands are really only intended for internal use +alias blurtest "qc_cmd_cl blurtest ${* ?}" // Feature for testing blur postprocessing +alias debugmodel "qc_cmd_cl debugmodel ${* ?}" // Spawn a debug model manually +//alias handlevote "qc_cmd_cl handlevote ${* ?}" // System to handle selecting a vote or option +alias hud "qc_cmd_cl hud ${* ?}" // Commands regarding/controlling the HUD system +alias localprint "qc_cmd_cl localprint ${* ?}" // Create your own centerprint sent to yourself +//alias mv_download "qc_cmd_cl mv_download ${* ?}" // Retrieve mapshot picture from the server +alias sendcvar "qc_cmd_cl sendcvar ${* ?}" // Send a cvar to the server (like weaponpriority) +//alias vyes "qc_cmd_cl vyes ${* ?}" // COMPATIBILITY COMMAND FOR 0.5 CLIENTS +//alias vno "qc_cmd_cl vno ${* ?}" // COMPATIBILITY COMMAND FOR 0.5 CLIENTS + +// other aliases for local commands +alias hud_configure "qc_cmd_cl hud configure" +alias hud_save "qc_cmd_cl hud save ${* ?}" +alias radar "qc_cmd_cl hud radar ${* ?}" +alias scoreboard_columns_help "qc_cmd_cl hud scoreboard_columns_help" +alias scoreboard_columns_set "qc_cmd_cl hud scoreboard_columns_set ${* ?}" + +// changes a cvar and reports it to the server (for the client to notify the server about changes) +alias setreport "set \"$1\" \"$2\" ; sendcvar \"$1\"" + + +// ======================================================== +// cmd (client-to-server command) - server/command/cmd.qc +// ======================================================== +set sv_clientcommand_antispam_time 1 "Amount of seconds after a command before another command can be called again without being considered spam. (Use -1 for no antispam limit)" +set sv_clientcommand_antispam_count 8 "Amount of commands considered spam before commands are rejected." +seta sv_status_privacy 1 "hide IP addresses from \"status\" and \"who\" replies shown to clients" +seta cl_autoswitch 1 "automatically switch to newly picked up weapons if they are better than what you are carrying" + +// commented out commands are really only intended for internal use, or already have declaration in the engine +alias autoswitch "qc_cmd_cmd autoswitch ${* ?}" // Whether or not to switch automatically when getting a better weapon +alias checkfail "qc_cmd_cmd checkfail ${* ?}" // Report if a client-side check failed +alias clientversion "qc_cmd_cmd clientversion ${* ?}" // Release version of the game +//alias mv_getpicture "qc_cmd_cmd mv_getpicture ${* ?}" // Retrieve mapshot picture from the server +alias join "qc_cmd_cmd join ${* ?}" // Become a player in the game +alias ready "qc_cmd_cmd ready ${* ?}" // Qualify as ready to end warmup stage (or restart server if allowed) +alias reportcvar "qc_cmd_cmd reportcvar ${* ?}" // Old system for sending a client cvar to the server +//alias say "qc_cmd_cmd say ${* ?}" // Print a message to chat to all players +//alias say_team "qc_cmd_cmd say_team ${* ?}" // Print a message to chat to all team mates +alias selectteam "qc_cmd_cmd selectteam ${* ?}" // Attempt to choose a team to join into +alias selfstuff "qc_cmd_cmd selfstuff ${* ?}" // Stuffcmd a command to your own client +alias sentcvar "qc_cmd_cmd sentcvar ${* ?}" // New system for sending a client cvar to the server +alias spectate "qc_cmd_cmd spectate ${* ?}" // Become an observer +alias suggestmap "qc_cmd_cmd suggestmap ${* ?}" // Suggest a map to the mapvote at match end +//alias tell "qc_cmd_cmd tell ${* ?}" // Send a message directly to a player +alias voice "qc_cmd_cmd voice ${* ?}" // Send voice message via sound + +// other aliases for client-to-server commands +alias autoswitch "set cl_autoswitch ${1 ?} ; cmd autoswitch ${1 ?}" // todo + +alias team_red "cmd selectteam red; cmd join" +alias team_blue "cmd selectteam blue; cmd join" +alias team_pink "cmd selectteam pink; cmd join" +alias team_yellow "cmd selectteam yellow; cmd join" +alias team_auto "cmd selectteam auto; cmd join" + +alias spec "spectate" + +// mutator aliases +alias sandbox "cmd g_sandbox ${* ?}" + + +// ============================================================ +// sv_cmd (server console command) - server/command/sv_cmd.qc +// ============================================================ +alias adminmsg "qc_cmd_sv adminmsg ${* ?}" // Send an admin message to a client directly +alias allready "qc_cmd_sv allready ${* ?}" // Restart the server and reset the players +alias allspec "qc_cmd_sv allspec ${* ?}" // Force all players to spectate +alias anticheat "qc_cmd_sv anticheat ${* ?}" // Create an anticheat report for a client +alias bbox "qc_cmd_sv bbox ${* ?}" // Print detailed information about world size +alias bot_cmd "qc_cmd_sv bot_cmd ${* ?}" // Control and send commands to bots +alias cointoss "qc_cmd_sv cointoss ${* ?}" // Flip a virtual coin and give random result +alias database "qc_cmd_sv database ${* ?}" // Extra controls of the serverprogs database +alias defer_clear "qc_cmd_sv defer_clear ${* ?}" // Clear all queued defer commands for a specific client +alias defer_clear_all "qc_cmd_sv defer_clear_all ${* ?}" // Clear all queued defer commands for all clients +alias delrec "qc_cmd_sv delrec ${* ?}" // Delete race time record for a map +alias effectindexdump "qc_cmd_sv effectindexdump ${* ?}" // Dump list of effects from code and effectinfo.txt +alias extendmatchtime "qc_cmd_sv extendmatchtime ${* ?}" // Increase the timelimit value incrementally +alias find "qc_cmd_sv find ${* ?}" // Search through entities for matching classname +alias gametype "qc_cmd_sv gametype ${* ?}" // Simple command to change the active gametype +alias gettaginfo "qc_cmd_sv gettaginfo ${* ?}" // Get specific information about a weapon model +alias gotomap "qc_cmd_sv gotomap ${* ?}" // Simple command to switch to another map +alias lockteams "qc_cmd_sv lockteams ${* ?}" // Disable the ability for players to switch or enter teams +alias make_mapinfo "qc_cmd_sv make_mapinfo ${* ?}" // Automatically rebuild mapinfo files +alias moveplayer "qc_cmd_sv moveplayer ${* ?}" // Change the team/status of a player +alias nospectators "qc_cmd_sv nospectators ${* ?}" // Automatically remove spectators from a match +alias playerdemo "qc_cmd_sv playerdemo ${* ?}" // Control the ability to save demos of players +alias printstats "qc_cmd_sv printstats ${* ?}" // Dump eventlog player stats and other score information +alias radarmap "qc_cmd_sv radarmap ${* ?}" // Generate a radar image of the map +alias reducematchtime "qc_cmd_sv reducematchtime ${* ?}" // Decrease the timelimit value incrementally +alias setbots "qc_cmd_sv setbots ${* ?}" // Adjust how many bots are in the match +alias shuffleteams "qc_cmd_sv shuffleteams ${* ?}" // Randomly move players to different teams +alias stuffto "qc_cmd_sv stuffto ${* ?}" // Send a command to be executed on a client +alias trace "qc_cmd_sv trace ${* ?}" // Various debugging tools with tracing +alias unlockteams "qc_cmd_sv unlockteams ${* ?}" // Enable the ability for players to switch or enter teams +alias warp "qc_cmd_sv warp ${* ?}" // Choose different level in campaign + +// other aliases for server commands +alias endmatch "timelimit -1" + +alias savedb "sv_cmd database save \"${1 ?}\"" +alias dumpdb "sv_cmd database dump \"${1 ?}\"" +alias loaddb "sv_cmd database load \"${1 ?}\"" + +alias movetored "moveplayer ${1 ?} red" +alias movetoblue "moveplayer ${1 ?} blue" +alias movetopink "moveplayer ${1 ?} pink" +alias movetoyellow "moveplayer ${1 ?} yellow" +alias movetoauto "moveplayer ${1 ?} auto" + + +// ======================================================= +// Aliases for settemp subsystem. Warning: Do not touch. +// Usage: settemp variable value, next map resets it. +// ======================================================= +alias settemp "qc_cmd_svcl settemp $$*" +alias settemp_restore "qc_cmd_svcl settemp_restore" + + +// =================================== +// banning - server/command/ipban.qc +// =================================== +alias ban "qc_cmd_sv ban ${* ?}" // Ban an IP address or a range of addresses (like 1.2.3) +alias banlist "qc_cmd_sv banlist ${* ?}" // List all existing bans +alias bans "qc_cmd_sv bans ${* ?}" // COMPATIBILITY COMMAND FOR 0.5 CLIENTS +alias kickban "qc_cmd_sv kickban ${* ?}" // Disconnect a client and ban it at the same time +alias unban "qc_cmd_sv unban ${* ?}" // Remove an existing ban + +// other aliases for ban commands +alias bans "banlist" + + +// ================================= +// voting - server/command/vote.qc +// ================================= +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" "these commands can be voted" +set sv_vote_only_commands "" +set sv_vote_master_commands "movetored movetoblue movetoyellow movetopink" "Extra commands which vote masters can execute by themselves, along with the normal sv_vote_commands." // maybe add kickban here (but then sv_vote_master 0) +set sv_vote_master 1 "Allows the use of the vote master system" +set sv_vote_master_callable 1 "When set, users can use \"vmaster\" to call a vote to become master of voting commands" +set sv_vote_master_password "" "when set, users can use \"vlogin PASSWORD\" to log in as master" +set sv_vote_master_playerlimit 2 "Minimum number of players needed for a player to be allowed to vote for master" +set sv_vote_no_stops_vote 1 "Allow the vote caller to stop his own vote simply by voting no" +set sv_vote_singlecount 0 "set to 1 to count votes once after timeout or to 0 to count with every vote" +set sv_vote_timeout 30 "a vote will timeout after this many seconds" +set sv_vote_wait 120 "a player can not call a vote again for this many seconds when his vote was not accepted" +set sv_vote_stop 15 "a player can not call a vote again for this many seconds when he stopped this vote (e.g. to correct it)" +set sv_vote_majority_factor 0.5 "What percentage of the PLAYERS constitute a majority? (Must be at least 0.5, recommended: 0.5)" +set sv_vote_majority_factor_of_voted 0.5 "What percentage of the VOTERS constitute a majority too? (Must be at least 0.5, recommended: 0.5)" +// when disabled, don't allow game type changes "note: set these two equal to JUST support simple majorities" +set sv_vote_override_mostrecent 0 + +// aliases for client only +alias vmaster "qc_cmd_cmd vote master" +alias vlogin "qc_cmd_cmd vote master login ${* ?}" +alias vdo "qc_cmd_cmd vote master do ${* ?}" +alias vyes "qc_cmd_cl handlevote yes; cl_cmd vyes" // NOTE: COMPATIBILITY FOR 0.5 IS ADDED HERE WITH "VYES", REMOVE LATER +alias vno "qc_cmd_cl handlevote no; cl_cmd vno" // ^^^ same, see above +alias vdontcare "qc_cmd_cmd vote abstain" +alias vabstain "qc_cmd_cmd vote abstain" + +// aliases for both client and server +alias vcall "qc_cmd_svcmd vote call ${* ?}" +alias vhelp "qc_cmd_svcmd vote help" +alias vstatus "qc_cmd_svcmd vote status" +alias vstop "qc_cmd_svcmd vote stop" + +// general +alias vmap "vcall gotomap ${1 ?}" +alias vnextmap "vcall nextmap ${1 ?}" +alias vkick "vcall kick ${1 ?}" +alias vkickban "vcall kickban ${1 ?}" +alias vend "vcall endmatch" +alias vdomap "vdo gotomap ${1 ?}" +alias vdokick "vdo kick ${* ?}" +alias vdokickban "vdo kickban ${* ?}" +alias vdoend "vdo endmatch" + +// ====================== +// rcon server commands +// ====================== +rcon_secure 1 +set rcon_restricted_commands "restart fraglimit chmap gotomap endmatch reducematchtime extendmatchtime allready kick kickban \"sv_cmd bans\" \"sv_cmd unban *\" status \"sv_cmd teamstatus\" movetoauto movetored movetoblue movetoyellow movetopink" \ No newline at end of file diff --git a/config_update.cfg b/config_update.cfg index 372784dd78..a998031361 100644 --- a/config_update.cfg +++ b/config_update.cfg @@ -1,25 +1,27 @@ -// load engine's idea of vid_con* -seta menu_vid_conwidth $vid_conwidth -seta menu_vid_conheight $vid_conheight +// updates for Nexuiz $OLD to 2.4 (also run on first startup, so be careful with what you put in here) +alias _update_configversion_0 "_update_configversion_1" -// fix cvar settings of the engine that Xonotic is not compatible with -alias _update_generic_r_dynamic_0 "r_dynamic 1; r_shadow_realtime_dlight 1" -alias _update_generic_r_dynamic_1 "" -alias _update_generic "_update_generic_r_dynamic_$r_dynamic" +// Updates for Nexuiz 2.4.1 to 2.4.2 +alias _update_configversion_1 "_update_configversion_2" -// updates for ... to 2.4 (also run on first startup, so be careful with what you put in here) -alias _update_configversion_0 "" +// Updates for Nexuiz to Xonotic +alias _update_configversion_2 "volume 1; cl_gunalign 1; _update_configversion_3" -// Updates for 2.4.1 to 2.4.2 -alias _update_configversion_1 "" +// Updates for gunalign fix +alias _update_configversion_3 "cl_gunalign 3; menu_cl_gunalign 3; _update_configversion_4" -// Updates for 2.5 to ... -alias _update_configversion_2 "" +// place to put further updates +alias _update_configversion_4 "snd_entchannel0volume 1; snd_entchannel1volume 1; snd_entchannel2volume 1; snd_entchannel3volume 1; snd_entchannel4volume 1; snd_entchannel5volume 1; snd_entchannel6volume 1; snd_entchannel7volume 1; snd_playerchannel0volume 1; snd_playerchannel1volume 1; snd_playerchannel2volume 1; snd_playerchannel3volume 1; snd_playerchannel4volume 1; snd_playerchannel5volume 1; snd_playerchannel6volume 1; snd_playerchannel7volume 1; snd_worldchannel0volume 1; snd_worldchannel1volume 1; snd_worldchannel2volume 1; snd_worldchannel3volume 1; snd_worldchannel4volume 1; snd_worldchannel5volume 1; snd_worldchannel6volume 1; snd_worldchannel7volume 1; snd_csqcchannel0volume 1; snd_csqcchannel1volume 1; snd_csqcchannel2volume 1; snd_csqcchannel3volume 1; snd_csqcchannel4volume 1; snd_csqcchannel5volume 1; snd_csqcchannel6volume 1; snd_csqcchannel7volume 1; _update_configversion_5" -_update_configversion_$g_configversion -_update_generic +// fix for common broken config for unknown reason +alias _update_configversion_5 "r_shadow_realtime_world_lightmaps 1; _update_configversion_6" + +// some people have freetype issues, weird +alias _update_configversion_6 "r_font_disable_freetype 0; utf8_enable 1; _update_configversion_7" -set g_configversion 2 +// place to put further updates +alias _update_configversion_7 "" + +_update_configversion_$g_configversion -// we now use mastervolume -volume 1 +set g_configversion 7 diff --git a/csprogs.dat.de.po b/csprogs.dat.de.po new file mode 100644 index 0000000000..a53553547a --- /dev/null +++ b/csprogs.dat.de.po @@ -0,0 +1,2113 @@ +# Xonotic CSQC +# Copyright (C) 2011 Team Xonotic +# This file is distributed under the same license as the Xonotic package. +# Rudolf Polzer , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: 0.1preview\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-12-25 22:57+0100\n" +"PO-Revision-Date: 2011-04-20 10:46+0200\n" +"Last-Translator: Rudolf Polzer \n" +"Language-Team: Rudolf Polzer \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: qcsrc/client/Main.qc:30 +msgid "ERROR - MENU IS VISIBLE BUT NO MENU WAS DEFINED!" +msgstr "FEHLER - MENÜ IST SICHTBAR ABER KEIN MENÜ WURDE DEFINIERT!" + +#: qcsrc/client/Main.qc:104 +msgid "" +"^3Your engine build is outdated\n" +"^3This Server uses a newer QC VM. Please update!\n" +msgstr "" +"^3Diese Engine ist veraltet.\n" +"^3Dieser Server verwendet eine neuere QC VM. Bitte updaten!\n" + +#: qcsrc/client/Main.qc:114 +#, c-format +msgid "^4CSQC Build information: ^1%s\n" +msgstr "^4CSQC Build-Information: ^1%s (deutsch)\n" + +#: qcsrc/client/Main.qc:293 qcsrc/client/Main.qc:309 +#, c-format +msgid "trying to switch to unsupported team %d\n" +msgstr "es wurde versucht, in das nicht unterstützte Team %d zu wechseln" + +#: qcsrc/client/Main.qc:424 qcsrc/client/scoreboard.qc:241 +msgid "Usage:\n" +msgstr "Syntax:\n" + +#: qcsrc/client/Main.qc:425 +msgid "hud_save configname (saves to hud_skinname_configname.cfg)\n" +msgstr "hud_save configname (speichert als hud_skinname_configname.cfg)\n" + +#: qcsrc/client/Main.qc:549 +msgid "Usage: cl_cmd COMMAND..., where possible commands are:\n" +msgstr "Syntax: cl_cmd BEFEHL..., wobei mögliche Befehle sind:\n" + +#: qcsrc/client/Main.qc:550 +msgid " settemp cvar value\n" +msgstr " settemp Cvar Wert\n" + +#: qcsrc/client/Main.qc:551 +msgid " scoreboard_columns_set ...\n" +msgstr " scoreboard_columns_set ...\n" + +#: qcsrc/client/Main.qc:552 +msgid " scoreboard_columns_help\n" +msgstr " scoreboard_columns_help\n" + +#: qcsrc/client/Main.qc:788 +#, c-format +msgid "A CSQC entity changed its owner! (edict: %d, classname: %s)\n" +msgstr "" +"Ein CSQC-Entity hat seinen Besitzer gewechselt! (edict: %d, classname: %s)\n" + +#: qcsrc/client/Main.qc:1029 +#, c-format +msgid "" +"A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n" +msgstr "" +"Ein CSQC-Entity hat seinen Typ gewechselt! (edict: %d, server: %d, type: %d -" +"> %d)\n" + +#: qcsrc/client/Main.qc:1038 +#, c-format +msgid "" +"A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n" +msgstr "" +"Ein CSQC-Entity kam aus dem Nichts! (edict: %d, server: %d, type: %d)\n" + +#: qcsrc/client/Main.qc:1080 +#, c-format +msgid "" +"Unknown entity type in CSQC_Ent_Update (enttype: %d, edict: %d, classname: " +"%s)\n" +msgstr "" +"Unbekannter Entity-Typ in CSQC_Ent_Update (enttype: %d, edict: %d, " +"classname: %s)\n" + +#: qcsrc/client/Main.qc:1526 +#, c-format +msgid "%s (not bound)" +msgstr "%s (nicht zugewiesen)" + +#: qcsrc/client/Main.qc:1531 qcsrc/client/hud.qc:230 +#, c-format +msgid "%s (%s)" +msgstr "%s (%s)" + +#: qcsrc/client/announcer.qc:31 +msgid "^1Begin!" +msgstr "^1Los!" + +#: qcsrc/client/announcer.qc:41 +#, c-format +msgid "^1Game starts in %d seconds" +msgstr "^1Das Spiel startet in %d Sekunden" + +#: qcsrc/client/announcer.qc:153 +msgid "^1RED^7 flag" +msgstr "^1ROTE^7 Flagge" + +#: qcsrc/client/announcer.qc:158 +msgid "^4BLUE^7 flag" +msgstr "^4BLAUE^7 Flagge" + +#: qcsrc/client/announcer.qc:166 +#, c-format +msgid "You picked up the %s!" +msgstr "Du hast die %s genommen!" + +#: qcsrc/client/announcer.qc:170 +#, c-format +msgid "You got the %s!" +msgstr "Du hast die %s!" + +#: qcsrc/client/csqcmodel_hooks.qc:17 +#, c-format +msgid "Trying to use non existing model %s. " +msgstr "Modell %s existiert nicht! " + +#: qcsrc/client/csqcmodel_hooks.qc:19 +#, c-format +msgid "Reverted to %s.\n" +msgstr "Es wird stattdessen %s verwendet.\n" + +#: qcsrc/client/hud.qc:160 +msgid "1st" +msgstr "1." + +#: qcsrc/client/hud.qc:162 +msgid "2nd" +msgstr "2." + +#: qcsrc/client/hud.qc:164 +msgid "3rd" +msgstr "3." + +#: qcsrc/client/hud.qc:166 +#, c-format +msgid "%dth" +msgstr "%d." + +#: qcsrc/client/hud.qc:198 +#, c-format +msgid " (-%dL)" +msgstr " (-%dR)" + +#: qcsrc/client/hud.qc:203 +#, c-format +msgid " (+%dL)" +msgstr " (+%dR)" + +#: qcsrc/client/hud.qc:219 +msgid "Start line" +msgstr "Start" + +#: qcsrc/client/hud.qc:221 qcsrc/client/hud.qc:225 +msgid "Finish line" +msgstr "Ziel" + +#: qcsrc/client/hud.qc:223 +#, c-format +msgid "Intermediate %d" +msgstr "Zwischenzeit %d" + +#: qcsrc/client/hud.qc:232 +#, c-format +msgid "%s (%s %s)" +msgstr "%s (%s %s)" + +#: qcsrc/client/hud.qc:786 +msgid "Out of ammo" +msgstr "Keine Munition mehr." + +#: qcsrc/client/hud.qc:790 +msgid "Don't have" +msgstr "nicht vorhanden" + +#: qcsrc/client/hud.qc:794 +msgid "Unavailable" +msgstr "nicht verfügbar" + +#: qcsrc/client/hud.qc:1534 +#, c-format +msgid "^1%s^1 couldn't take it anymore\n" +msgstr "^1%s^1 konnte es nicht mehr ertragen\n" + +#: qcsrc/client/hud.qc:1538 qcsrc/client/hud.qc:1887 +#, c-format +msgid "^1%s^1 died\n" +msgstr "^1%s^1 ist gestorben\n" + +#: qcsrc/client/hud.qc:1542 +#, c-format +msgid "^7%s^7 committed suicide. What's the point of living without ammo?\n" +msgstr "^7%s^7 hat sich erhängt. Was ist schon ein Leben ohne Munition?\n" + +#: qcsrc/client/hud.qc:1546 +#, c-format +msgid "^1%s^1 thought they found a nice camping ground\n" +msgstr "^1%s^1 dachte, einen tollen Campingplatz gefunden zu haben\n" + +#: qcsrc/client/hud.qc:1550 +#, c-format +msgid "^1%s^1 didn't become friends with the Lord of Teamplay\n" +msgstr "^1%s^1 bekam Probleme mit dem Lord of Teamplay\n" + +#: qcsrc/client/hud.qc:1554 +#, c-format +msgid "^1%s^1 unfairly eliminated themself\n" +msgstr "^1%s^1 hat sich selbst auf unfaire Weise erledigt\n" + +#: qcsrc/client/hud.qc:1558 +#, c-format +msgid "^1%s^1 burned to death\n" +msgstr "^1%s^1 brannte zu Tode\n" + +#: qcsrc/client/hud.qc:1562 +#, c-format +msgid "^1%s^1 couldn't resist the urge to self-destruct\n" +msgstr "" +"^1%s^1 konnte dem Drang zur Selbstzerstörung einfach nicht widerstehen\n" + +#: qcsrc/client/hud.qc:1566 +#, c-format +msgid "^1%s^1 ended it all after a %d kill spree\n" +msgstr "^1%s^1 machte seinem %d-Amoklauf ein Ende\n" + +#: qcsrc/client/hud.qc:1583 +#, c-format +msgid "^1%s^1 took action against a team mate\n" +msgstr "^1%s^1 ergriff Maßnahmen gegen einen Mitspieler\n" + +#: qcsrc/client/hud.qc:1585 +#, c-format +msgid "^1%s^1 mows down a team mate\n" +msgstr "^1%s^1 mähte einen Mitspieler nieder\n" + +#: qcsrc/client/hud.qc:1590 +#, c-format +msgid "^1%s^1 ended a %d scoring spree by going against a team mate\n" +msgstr "" +"^1%s^1 dachte, %d Punkte hintereinander reichen, und trug dies an einem " +"Mitspieler aus\n" + +#: qcsrc/client/hud.qc:1592 +#, c-format +msgid "^1%s^1 ended a %d kill spree by killing a team mate\n" +msgstr "^1%s^1 beendete seinen %d-Amoklauf, indem er einen Mitspieler tötete\n" + +#: qcsrc/client/hud.qc:1596 +#, c-format +msgid "^1%s^1's %s scoring spree was ended by a team mate!\n" +msgstr "" +"^1%s^1s %s Punkte hintereinander wurden von einem Mitspieler gestört!\n" + +#: qcsrc/client/hud.qc:1598 +#, c-format +msgid "^1%s^1's %s kill spree was ended by a team mate!\n" +msgstr "^1%s^1s %s-Amoklauf wurde von einem Mitspieler beendet!\n" + +#: qcsrc/client/hud.qc:1602 +#, c-format +msgid "^1%s^1 drew first blood\n" +msgstr "^1%s^1 war der Erste\n" + +#: qcsrc/client/hud.qc:1606 +#, c-format +msgid "^1%s^1 tried to occupy %s^1's teleport destination space\n" +msgstr "^1%s^1 dachte, %s^1 am Teleportieren hindern zu können\n" + +#: qcsrc/client/hud.qc:1608 +#, c-format +msgid "^1%s^1 was telefragged by %s\n" +msgstr "^1%s^1 wurde von %s^1 telefragged\n" + +#: qcsrc/client/hud.qc:1613 +#, c-format +msgid "^1%s^1 was drowned by %s\n" +msgstr "^1%s^1 wurde von %s^1 etränkt\n" + +#: qcsrc/client/hud.qc:1618 +#, c-format +msgid "^1%s^1 was slimed by %s\n" +msgstr "^1%s^1 wurde von %s^1 im Schleim versenkt\n" + +#: qcsrc/client/hud.qc:1623 +#, c-format +msgid "^1%s^1 was cooked by %s\n" +msgstr "^1%s^1 wurde von %s^1 gebraten\n" + +#: qcsrc/client/hud.qc:1628 +#, c-format +msgid "^1%s^1 was grounded by %s\n" +msgstr "^1%s^1 wurde von %s^1 geerdet\n" + +#: qcsrc/client/hud.qc:1633 +#, c-format +msgid "^1%s^1 was shot into space by %s\n" +msgstr "^1%s^1 wurde von %s^1 ins All geschossen\n" + +#: qcsrc/client/hud.qc:1638 +#, c-format +msgid "^1%s^1 was conserved by %s\n" +msgstr "^1%s^1 wurde von %s^1 konserviert\n" + +#: qcsrc/client/hud.qc:1644 +#, c-format +msgid "^1%s^1 was thrown into a world of hurt by %s\n" +msgstr "^1%s^1 wurde von %s^1 in eine Welt des Schmerzes geworfen\n" + +#: qcsrc/client/hud.qc:1648 +#, c-format +msgid "^1%s^1 was crushed by %s\n" +msgstr "^1%s^1 wurde von %s^1 zerquetscht\n" + +#: qcsrc/client/hud.qc:1652 +#, c-format +msgid "^1%s^1 got shredded by %s\n" +msgstr "^1%s^1 wurde von %s^1 zerstückelt\n" + +#: qcsrc/client/hud.qc:1656 +#, c-format +msgid "^1%s^1 was blasted to bits by %s\n" +msgstr "^1%s^1 wurde von %s^1 in die Luft gejagt\n" + +#: qcsrc/client/hud.qc:1660 +#, c-format +msgid "^1%s^1 got caught in the destruction of %s^1's vehicle\n" +msgstr "^1%s^1 wurde von der Explosion von %s^1s Fahrzeug erwischt\n" + +#: qcsrc/client/hud.qc:1664 +#, c-format +msgid "^1%s^1 was bolted down by %s\n" +msgstr "^1%s^1 wurde von %s^1 niedergeschmettert\n" + +#: qcsrc/client/hud.qc:1668 +#, c-format +msgid "^1%s^1 could find no shelter from %s^1's rockets\n" +msgstr "^1%s^1 fand keine Deckung vor %s^1s Raketen\n" + +#: qcsrc/client/hud.qc:1672 +#, c-format +msgid "^1%s^1 dies when %s^1's wakizashi dies.\n" +msgstr "^1%s^1 starb zusammen mit %s^1's Wakizashi.\n" + +#: qcsrc/client/hud.qc:1676 +#, c-format +msgid "^1%s^1 nailed to hell by %s\n" +msgstr "^1%s^1 wurde von %s^1 in die Hölle geschossen\n" + +#: qcsrc/client/hud.qc:1680 +#, c-format +msgid "^1%s^1 cluster crushed by %s\n" +msgstr "^1%s^1 wurde von %s^1 total zerstört\n" + +#: qcsrc/client/hud.qc:1684 +#, c-format +msgid "^1%s^1 dies when %s^1's raptor dies.\n" +msgstr "^1%s^1 starb zusammen mit %s^1's Raptor.\n" + +#: qcsrc/client/hud.qc:1688 +#, c-format +msgid "^1%s^1 was pushed into the line of fire by %s\n" +msgstr "^1%s^1 wurde von %s^1 ins offene Feuer geschubst\n" + +#: qcsrc/client/hud.qc:1692 +#, c-format +msgid "^1%s^1 was pushed into an accident by %s\n" +msgstr "^1%s^1 wurde von %s^1 in einen unglücklichen Unfall geschubst\n" + +#: qcsrc/client/hud.qc:1696 +#, c-format +msgid "^1%s^1 was unfairly eliminated by %s\n" +msgstr "^1%s^1 wurde von %s auf unfaire Weise erledigt\n" + +#: qcsrc/client/hud.qc:1700 +#, c-format +msgid "^1%s^1 was burnt to death by %s\n" +msgstr "^1%s^1 wurde von %s verbrannt\n" + +#: qcsrc/client/hud.qc:1712 +#, c-format +msgid "^1%s^1 was fragged by %s\n" +msgstr "^1%s^1 wurde von %s^1 gefraggt\n" + +#: qcsrc/client/hud.qc:1717 +#, c-format +msgid "^1%s^1's %s scoring spree was ended by %s\n" +msgstr "^1%s^1's Punkte-Folge wurde von %s^1 beendet\n" + +#: qcsrc/client/hud.qc:1719 +#, c-format +msgid "^1%s^1's %s kill spree was ended by %s\n" +msgstr "^1%s^1's Kill-Spree wurde von %s^1 beendet\n" + +#: qcsrc/client/hud.qc:1722 +#, c-format +msgid "^1%s^1 made %s scores in a row\n" +msgstr "^1%s^1 machte %s Punkte hintereinander\n" + +#: qcsrc/client/hud.qc:1724 +#, c-format +msgid "^1%s^1 has %s frags in a row\n" +msgstr "^1%s^1 hat %s Frags hintereinander\n" + +#: qcsrc/client/hud.qc:1727 +#, c-format +msgid "%s^7 made a ^1TRIPLE SCORE\n" +msgstr "%s^7 hat einen ^1TRIPLE SCORE\n" + +#: qcsrc/client/hud.qc:1729 +#, c-format +msgid "%s^7 made a ^1TRIPLE FRAG\n" +msgstr "%s^7 hat einen ^1TRIPLE FRAG\n" + +#: qcsrc/client/hud.qc:1732 +#, c-format +msgid "%s^7 unleashes ^1SCORING RAGE\n" +msgstr "%s^7 hat ^1PUNKTE-RASEN\n" + +#: qcsrc/client/hud.qc:1734 +#, c-format +msgid "%s^7 unleashes ^1RAGE\n" +msgstr "%s^7 ^1RAST VOR ZORN\n" + +#: qcsrc/client/hud.qc:1737 +#, c-format +msgid "%s^7 made ^1TEN SCORES IN A ROW!\n" +msgstr "%s^7 hat ^1ZEHN PUNKTE HINTEREINANDER!\n" + +#: qcsrc/client/hud.qc:1739 +#, c-format +msgid "%s^7 starts the ^1MASSACRE!\n" +msgstr "%s^7 beginnt das ^1MASSAKER!\n" + +#: qcsrc/client/hud.qc:1742 +#, c-format +msgid "%s^7 made ^1FIFTEEN SCORES IN A ROW!\n" +msgstr "%s^7 hat ^1FÜNFZEHN PUNKTE HINTEREINANDER\n" + +#: qcsrc/client/hud.qc:1744 +#, c-format +msgid "%s^7 executes ^1MAYHEM!\n" +msgstr "%s^7 erzeugt das ^1CHAOS!\n" + +#: qcsrc/client/hud.qc:1747 +#, c-format +msgid "%s^7 made ^1TWENTY SCORES IN A ROW!\n" +msgstr "%s^7 hat ^1ZWANZIG PUNKTE HINTEREINANDER\n" + +#: qcsrc/client/hud.qc:1749 +#, c-format +msgid "%s^7 is a ^1BERSERKER!\n" +msgstr "%s^7 ist ein ^1BERSERKER!\n" + +#: qcsrc/client/hud.qc:1752 +#, c-format +msgid "%s^7 made ^1TWENTY FIVE SCORES IN A ROW!\n" +msgstr "%s^7 hat ^1FÜNFUNDZWANZIG PUNKTE HINTEREINANDER!\n" + +#: qcsrc/client/hud.qc:1754 +#, c-format +msgid "%s^7 inflicts ^1CARNAGE!\n" +msgstr "%s^7 hält ein ^1BLUTBAD!\n" + +#: qcsrc/client/hud.qc:1757 +#, c-format +msgid "%s^7 made ^1THIRTY SCORES IN A ROW!\n" +msgstr "%s^7 hat ^1DREISSIG PUNKTE HINTEREINANDER\n" + +#: qcsrc/client/hud.qc:1759 +#, c-format +msgid "%s^7 unleashes ^1ARMAGEDDON!\n" +msgstr "%s^7 lässt die ^1APOKALYPSE^7 los!\n" + +#: qcsrc/client/hud.qc:1767 +#, c-format +msgid "^1%s^1 was in the water for too long\n" +msgstr "^1%s^1 war zu lange im Wasser\n" + +#: qcsrc/client/hud.qc:1769 +#, c-format +msgid "^1%s^1 drowned\n" +msgstr "^1%s^1 ertrank\n" + +#: qcsrc/client/hud.qc:1774 +#, c-format +msgid "^1%s^1 was slimed\n" +msgstr "^1%s^1 wurde im Schleim versenkt\n" + +#: qcsrc/client/hud.qc:1780 +#, c-format +msgid "^1%s^1 found a hot place\n" +msgstr "^1%s^1 fand einen heißen Ort\n" + +#: qcsrc/client/hud.qc:1782 +#, c-format +msgid "^1%s^1 turned into hot slag\n" +msgstr "^1%s^1 verwandelte sich in heiße Schlacke\n" + +#: qcsrc/client/hud.qc:1789 +#, c-format +msgid "^1%s^1 tested gravity (and it worked)\n" +msgstr "^1%s^1 probierte die Gravitation aus (und sie funktionierte)\n" + +#: qcsrc/client/hud.qc:1791 +#, c-format +msgid "^1%s^1 hit the ground with a crunch\n" +msgstr "^1%s^1 landete mit einem Knall auf dem Boden\n" + +#: qcsrc/client/hud.qc:1796 +#, c-format +msgid "^1%s^1 became a shooting star\n" +msgstr "^1%s^1 wurde zu einer Sternschnuppe\n" + +#: qcsrc/client/hud.qc:1802 +#, c-format +msgid "^1%s^1 discovered a swamp\n" +msgstr "^1%s^1 entdeckte einen Sumpf\n" + +#: qcsrc/client/hud.qc:1804 +#, c-format +msgid "^1%s^1 is now conserved for centuries to come\n" +msgstr "^1%s^1 ist jetzt für Jahrhunderte konserviert\n" + +#: qcsrc/client/hud.qc:1811 +#, c-format +msgid "^1%s^1 ran into a turret\n" +msgstr "^1%s^1 probierte die Selbstschussanlage aus\n" + +#: qcsrc/client/hud.qc:1817 +#, c-format +msgid "^1%s^1 was laserd down by a eWheel turret \n" +msgstr "^1%s^1 wurde von einem eWheel gelasert\n" + +#: qcsrc/client/hud.qc:1820 +#, c-format +msgid "^1%s^1 got caught in the flac \n" +msgstr "^1%s^1 fraß Flac\n" + +#: qcsrc/client/hud.qc:1823 +#, c-format +msgid "^1%s^1 was riddeld full of riddled by a machinegun turret \n" +msgstr "" +"^1%s^1 wurde von einer Maschinengewehr-Selbstschussanlage durchlöchert\n" + +#: qcsrc/client/hud.qc:1826 +#, c-format +msgid "^1%s^1 got served a led enrichment by a walker turret \n" +msgstr "^1%s^1 bekam eine Blei-Überdosis von einem Walker\n" + +#: qcsrc/client/hud.qc:1829 +#, c-format +msgid "^1%s^1 was impaled by a walker turret \n" +msgstr "^1%s^1 wurde von einem Walker aufgepiekst\n" + +#: qcsrc/client/hud.qc:1832 +#, c-format +msgid "^1%s^1 was rocketed to hell by a walker turret \n" +msgstr "^1%s^1 wurde von einem Walker in die Luft gejagt\n" + +#: qcsrc/client/hud.qc:1835 +#, c-format +msgid "^1%s^1 was blasted away hellion turret \n" +msgstr "^1%s^1 wurde von einem Hellion weggeblasen\n" + +#: qcsrc/client/hud.qc:1838 +#, c-format +msgid "^1%s^1 could not hide from the hunter turret \n" +msgstr "" +"%s konnte sich vor der Selbstschussanlage Marke Hunter nicht verstecken" + +#: qcsrc/client/hud.qc:1841 +#, c-format +msgid "^1%s^1 got turned into smoldering gibs by a mlrs turret \n" +msgstr "^1%s^1 wurde von einem MLRS-Turret zerstückelt\n" + +#: qcsrc/client/hud.qc:1844 +#, c-format +msgid "^1%s^1 got served some superheated plasma from a plasma turret \n" +msgstr "^1%s^1 bekam ein wenig heißes Plasma serviert\n" + +#: qcsrc/client/hud.qc:1847 +#, c-format +msgid "^1%s^1 was phased out \n" +msgstr "^1%s^1 verschwand in der Phasenverschiebung\n" + +#: qcsrc/client/hud.qc:1850 +#, c-format +msgid "^1%s^1 was electrocuted by a tesla turret \n" +msgstr "^1%s^1 fand Tesla-Turrets elektrisierend\n" + +#: qcsrc/client/hud.qc:1866 +#, c-format +msgid "^1%s^1 died in an accident\n" +msgstr "^1%s^1 starb an einem Unfall\n" + +#: qcsrc/client/hud.qc:1870 +#, c-format +msgid "^1%s^1 was unfairly eliminated\n" +msgstr "^1%s^1 wurde auf unfaire Weise eliminiert\n" + +#: qcsrc/client/hud.qc:1876 +#, c-format +msgid "^1%s^1 felt a little hot\n" +msgstr "^1%s^1 fand es ein wenig zu warm\n" + +#: qcsrc/client/hud.qc:1878 +#, c-format +msgid "^1%s^1 burnt to death\n" +msgstr "^1%s^1 verbrannte\n" + +#: qcsrc/client/hud.qc:1885 +#, c-format +msgid "^1%s^1 needs a restart\n" +msgstr "^1%s^1 braucht einen Neustart\n" + +#: qcsrc/client/hud.qc:1892 +#, c-format +msgid "^1%s^1 needs a restart after a %d scoring spree\n" +msgstr "^1%s^1 braucht einen Neustart nach %d Punkten in Folge\n" + +#: qcsrc/client/hud.qc:1894 +#, c-format +msgid "^1%s^1 died with a %d kill spree\n" +msgstr "^1%s^1 starb mit einer %d-Kill-Spree\n" + +#: qcsrc/client/hud.qc:1898 +#, c-format +msgid "%s^7 got the %s\n" +msgstr "%s^7 bekam die %s\n" + +#: qcsrc/client/hud.qc:1901 +#, c-format +msgid "%s^7 lost the %s\n" +msgstr "%s^7 verlor die %s\n" + +#: qcsrc/client/hud.qc:1904 +#, c-format +msgid "%s^7 picked up the %s\n" +msgstr "%s^7 nahm sich die %s\n" + +#: qcsrc/client/hud.qc:1907 +#, c-format +msgid "%s^7 returned the %s\n" +msgstr "%s^7 brachte die %s^7 zurück\n" + +#: qcsrc/client/hud.qc:1910 +#, c-format +msgid "%s^7 captured the %s%s\n" +msgstr "%s^7 eroberte die %s%s\n" + +#: qcsrc/client/hud.qc:1929 +#, c-format +msgid "%s^7 has picked up the ball!\n" +msgstr "%s^7 hat den Ball genommen!\n" + +#: qcsrc/client/hud.qc:1934 +#, c-format +msgid "%s^7 has dropped the ball!\n" +msgstr "%s^7 hat den Ball verloren!\n" + +#: qcsrc/client/hud.qc:1945 +#, c-format +msgid "You are now on: %s" +msgstr "Du bist jetzt im: %s" + +#: qcsrc/client/hud.qc:1947 +#, c-format +msgid "" +"You have been moved into a different team to improve team balance\n" +"You are now on: %s" +msgstr "" +"Du wurdest in ein anderes Team verschoben, um Team-Balance zu verbessern.\n" +"Du bist jetzt im: %s" + +#: qcsrc/client/hud.qc:1950 +msgid "^1Reconsider your tactics, camper!" +msgstr "^1Ändere dein Verhalten, Camper!" + +#: qcsrc/client/hud.qc:1952 +msgid "^1Die camper!" +msgstr "^1Stirb, Camper!" + +#: qcsrc/client/hud.qc:1955 +msgid "^1You are reinserted into the game for running out of ammo..." +msgstr "" +"^1Du wurdest ins Spiel neu eingesetzt, weil dir die Munition ausging..." + +#: qcsrc/client/hud.qc:1957 +msgid "^1You were killed for running out of ammo..." +msgstr "^1Du wurdest getötet, da dir die Munition ausging..." + +#: qcsrc/client/hud.qc:1960 +msgid "^1You need to preserve your health" +msgstr "^1Du solltest deine Gesundheit erhalten" + +#: qcsrc/client/hud.qc:1962 +msgid "^1You grew too old without taking your medicine" +msgstr "^1Du wurdest zu alt, und hast nicht deine Medizin genommen" + +#: qcsrc/client/hud.qc:1965 +msgid "^1Don't go against team mates!" +msgstr "^1Ärgere deine Teamkollegen nicht!" + +#: qcsrc/client/hud.qc:1967 +msgid "^1Don't shoot your team mates!" +msgstr "^1Schieße nicht auf deine Teamkollegen!" + +#: qcsrc/client/hud.qc:1972 +msgid "^1You need to be more careful!" +msgstr "^1Sei vorsichtiger!" + +#: qcsrc/client/hud.qc:1974 +msgid "^1You killed your own dumb self!" +msgstr "^1Du hast dich selbst umgebracht. Wie blöd." + +#: qcsrc/client/hud.qc:1979 +#, c-format +msgid "^1Moron! You went against ^7%s^1, a team mate!" +msgstr "^1Idiot! Du hast %s getroffen, also einen Teamkollegen von dir!" + +#: qcsrc/client/hud.qc:1981 +#, c-format +msgid "^1Moron! You fragged ^7%s^1, a team mate!" +msgstr "^1Idiot! Du hast %s getötet, also einen Teamkollegen von dir!" + +#: qcsrc/client/hud.qc:1985 +msgid "^1First score" +msgstr "^1Erster Punkt" + +#: qcsrc/client/hud.qc:1987 +msgid "^1First blood" +msgstr "^1Erstes Blut" + +#: qcsrc/client/hud.qc:1991 +msgid "^1First casualty" +msgstr "^1Erster Kollateralschaden" + +#: qcsrc/client/hud.qc:1993 +msgid "^1First victim" +msgstr "^1Erstes Opfer" + +#: qcsrc/client/hud.qc:1997 +#, c-format +msgid "^1You scored against ^7%s^1 who was typing!" +msgstr "^1Du hast gegen ^7%s^1 gepunktet, während er am Tippen war!" + +#: qcsrc/client/hud.qc:1999 +#, c-format +msgid "^1You typefragged ^7%s" +msgstr "^1Du hast ^7%s^1 beim Tippen erschossen" + +#: qcsrc/client/hud.qc:2003 +#, c-format +msgid "^1You were scored against by ^7%s^1 while you were typing!" +msgstr "^1Gegen dich hat ^7%s^1 gepunktet, während du am Tippen warst!" + +#: qcsrc/client/hud.qc:2005 +#, c-format +msgid "^1You were typefragged by ^7%s" +msgstr "^1Du wurdest von ^7%s^1 erschossen, während du am Tippen warst" + +#: qcsrc/client/hud.qc:2009 +#, c-format +msgid "^4You scored against ^7%s" +msgstr "^4Du hast gegen ^7%s^4 gepunktet" + +#: qcsrc/client/hud.qc:2011 +#, c-format +msgid "^4You fragged ^7%s" +msgstr "^4Du hast ^7%s^4 getötet" + +#: qcsrc/client/hud.qc:2015 +#, c-format +msgid "^1You were scored against by ^7%s" +msgstr "^1Gegen dich hat ^7%s^1 gepunktet" + +#: qcsrc/client/hud.qc:2017 +#, c-format +msgid "^1You were fragged by ^7%s" +msgstr "^1Du wurdest von ^7%s^1 getötet" + +#: qcsrc/client/hud.qc:2022 +msgid "^1Watch your step!" +msgstr "^1Achte, wo du hintrittst!" + +#: qcsrc/client/hud.qc:2091 qcsrc/client/hud.qc:2092 qcsrc/client/hud.qc:2598 +#, c-format +msgid "Player %d" +msgstr "Spieler %d" + +#: qcsrc/client/hud.qc:2907 +msgid "^1Intermediate 1 (+15.42)" +msgstr "^1Intermediate 1 (+15.42)" + +#: qcsrc/client/hud.qc:2909 qcsrc/client/hud.qc:2951 qcsrc/client/hud.qc:2992 +#, c-format +msgid "^1PENALTY: %.1f (%s)" +msgstr "^1STRAFE: %.1f (%s)" + +#: qcsrc/client/hud.qc:2994 +#, c-format +msgid "^2PENALTY: %.1f (%s)" +msgstr "^2STRAFE: %.1f (%s)" + +#: qcsrc/client/hud.qc:3022 +msgid "^1You must answer before entering hud configure mode\n" +msgstr "^1Du musst antworten, bevore das HUD konfiguriert werden kann\n" + +#: qcsrc/client/hud.qc:3027 +msgid "^2Name ^7instead of \"^1Anonymous player^7\" in stats" +msgstr "^2Name^7 statt \"^1Anonymous player^7\" in den Statistiken" + +#: qcsrc/client/hud.qc:3109 +msgid "A vote has been called for:" +msgstr "Eine Abstimmung wurde initiiert für:" + +#: qcsrc/client/hud.qc:3111 +msgid "Allow servers to store and display your name?" +msgstr "Erlaube Servern, deinen Namen zu speichern und später zu zeigen?" + +#: qcsrc/client/hud.qc:3115 +msgid "^1Configure the HUD" +msgstr "^1Das HUD konfigurieren" + +#: qcsrc/client/hud.qc:3119 +#, c-format +msgid "Yes (%s): %d" +msgstr "Ja (%s): %d" + +#: qcsrc/client/hud.qc:3121 +#, c-format +msgid "No (%s): %d" +msgstr "Nein (%s): %d" + +#: qcsrc/client/hud.qc:3624 qcsrc/client/hud.qc:3627 qcsrc/client/hud.qc:3629 +msgid "Personal best" +msgstr "Persönliche Bestzeit" + +#: qcsrc/client/hud.qc:3642 qcsrc/client/hud.qc:3645 qcsrc/client/hud.qc:3647 +msgid "Server best" +msgstr "Server-Bestzeit" + +#: qcsrc/client/hud.qc:3993 +msgid "^3Player^7: This is the chat area." +msgstr "^3Player^7: Das ist der Chat-Bereich." + +#: qcsrc/client/hud.qc:4061 +#, c-format +msgid "FPS: %.*f" +msgstr "FPS: %.*f" + +#: qcsrc/client/hud.qc:4128 +msgid "^1Observing" +msgstr "^1Beobachten" + +#: qcsrc/client/hud.qc:4131 qcsrc/client/hud.qc:4133 +#, c-format +msgid "^1Spectating: ^7%s" +msgstr "^1Zuschauen bei: ^7%s" + +#: qcsrc/client/hud.qc:4138 +#, c-format +msgid "^1Press ^3%s^1 to spectate" +msgstr "^1Drücke ^3%s^1, um bei jemandem zuzuschauen" + +#: qcsrc/client/hud.qc:4140 +#, c-format +msgid "^1Press ^3%s^1 for another player" +msgstr "^1Drücke ^3%s^1 für einen anderen Spieler" + +#: qcsrc/client/hud.qc:4144 +#, c-format +msgid "^1Use ^3%s^1 or ^3%s^1 to change the speed" +msgstr "^1Benutze ^3%s^1 oder ^3%s^1 zum Ändern der Geschwindigkeit" + +#: qcsrc/client/hud.qc:4146 +#, c-format +msgid "^1Press ^3%s^1 to observe" +msgstr "^1Drücke ^3%s^1 zum Beobachten" + +#: qcsrc/client/hud.qc:4149 +#, c-format +msgid "^1Press ^3%s^1 for gamemode info" +msgstr "^1Drücke ^3%s^1 für Spielmodus-Info" + +#: qcsrc/client/hud.qc:4153 +msgid "^1Wait for your turn to join" +msgstr "^1Warte, bis du dran bist" + +#: qcsrc/client/hud.qc:4159 +msgid "^1Match has already begun" +msgstr "^1Das Match hat bereits begonnen" + +#: qcsrc/client/hud.qc:4161 +msgid "^1You have no more lives left" +msgstr "^1Du hast keine Leben mehr übrig" + +#: qcsrc/client/hud.qc:4163 qcsrc/client/hud.qc:4166 +#, c-format +msgid "^1Press ^3%s^1 to join" +msgstr "^1Drücke ^3%s^1 zum Mitspielen" + +#: qcsrc/client/hud.qc:4174 +#, c-format +msgid "^1Game starts in ^3%d^1 seconds" +msgstr "^1Das Spiel beginnt in ^3%d^1 Sekunden" + +#: qcsrc/client/hud.qc:4181 +msgid "^2Currently in ^1warmup^2 stage!" +msgstr "^2Momentan in der ^1Aufwärmphase!" + +#: qcsrc/client/hud.qc:4196 +#, c-format +msgid "%sPress ^3%s%s to end warmup" +msgstr "%sDrücke ^3%s%s um die Aufwärmphase zu beenden" + +#: qcsrc/client/hud.qc:4198 +#, c-format +msgid "%sPress ^3%s%s once you are ready" +msgstr "%sDrücke ^3%s%s sobald du soweit bist" + +#: qcsrc/client/hud.qc:4203 +msgid "^2Waiting for others to ready up to end warmup..." +msgstr "^2Warte, bis andere bereit sind, um die Aufwärmphase zu beenden" + +#: qcsrc/client/hud.qc:4205 +msgid "^2Waiting for others to ready up..." +msgstr "^2Warte, bis andere bereit sind..." + +#: qcsrc/client/hud.qc:4211 +#, c-format +msgid "^2Press ^3%s^2 to end warmup" +msgstr "^2Drücke ^3%s^2 um die Aufwärmphase zu beenden" + +#: qcsrc/client/hud.qc:4232 +msgid "Teamnumbers are unbalanced!" +msgstr "Die Teams sind unbalanciert!" + +#: qcsrc/client/hud.qc:4237 +#, c-format +msgid " Press ^3%s%s to adjust" +msgstr "Drücke ^3%s%s um dies zu korrigieren" + +#: qcsrc/client/hud.qc:4245 +msgid "^7Press ^3ESC ^7to show HUD options." +msgstr "^7Drücke ^3ESC^7 um die HUD-Optionen zu zeigen" + +#: qcsrc/client/hud.qc:4247 +msgid "^3Doubleclick ^7a panel for panel-specific options." +msgstr "^3Doppelklick^7 auf ein Panel für Panel-spezifische Optionen." + +#: qcsrc/client/hud.qc:4249 +msgid "^3CTRL ^7to disable collision testing, ^3SHIFT ^7and" +msgstr "^3CTRL^7 um Kollisionstests zu deaktivieren, ^3SHIFT^7 und" + +#: qcsrc/client/hud.qc:4251 +msgid "^3ALT ^7+ ^3ARROW KEYS ^7for fine adjustments." +msgstr "^3ALT^7 + ^3PFEILTASTEN^7 für Feinjustierungen" + +#: qcsrc/client/hud.qc:4289 +msgid " qu/s" +msgstr "qu/s" + +#: qcsrc/client/hud.qc:4293 +msgid " m/s" +msgstr "m/s" + +#: qcsrc/client/hud.qc:4297 +msgid " km/h" +msgstr "km/h" + +#: qcsrc/client/hud.qc:4301 +msgid " mph" +msgstr "mph" + +#: qcsrc/client/hud.qc:4305 +msgid " knots" +msgstr "Knoten" + +#: qcsrc/client/hud.qc:4968 +msgid "Automatically fixed wrong/missing panel numbers in _hud_panelorder\n" +msgstr "Falsche Panel-Nummern in _hud_panelorder wurden automatisch behoben" + +#: qcsrc/client/hud_config.qc:185 +#, c-format +msgid "^2Successfully exported to %s! (Note: It's saved in data/data/)\n" +msgstr "" +"^2Erfolgreich als %s exportiert! (Hinweis: die Datei wurde in data/data/ " +"abgelegt)\n" + +#: qcsrc/client/hud_config.qc:189 +#, c-format +msgid "^1Couldn't write to %s\n" +msgstr "^1Konnte nicht nach %s schreiben\n" + +#: qcsrc/client/mapvoting.qc:28 +msgid " (1 vote)" +msgstr "(1 Stimme)" + +#: qcsrc/client/mapvoting.qc:30 +#, c-format +msgid " (%d votes)" +msgstr "(%d Stimmen)" + +#: qcsrc/client/mapvoting.qc:113 +msgid "Don't care" +msgstr "Egal" + +#: qcsrc/client/mapvoting.qc:194 +msgid "Vote for a map" +msgstr "Wähle eine Map" + +#: qcsrc/client/mapvoting.qc:200 +#, c-format +msgid "%d seconds left" +msgstr "%d Sekunden übrig" + +#: qcsrc/client/mapvoting.qc:263 +msgid "" +"mv_mapdownload: ^3You're not supposed to use this command on your own!\n" +msgstr "" +"mv_mapdownload: ^3Dieser Befehl darf nur vom Server verwendet werden!\n" + +#: qcsrc/client/mapvoting.qc:273 +msgid "^1Error:^7 Couldn't find pak index.\n" +msgstr "^1Fehler:^7 konnte den pak-Index nicht finden.\n" + +#: qcsrc/client/mapvoting.qc:282 +msgid "Requesting preview...\n" +msgstr "Vorschau wird angefordert...\n" + +#: qcsrc/client/miscfunctions.qc:100 +msgid "Trying to remove a team which is not in the teamlist!" +msgstr "Versuchte, ein Team zu löschen, das nicht in der Teamliste ist!" + +#: qcsrc/client/movetypes.qc:163 +#, c-format +msgid "Can't unstick an entity (edict: %d, classname: %s, origin: %s)\n" +msgstr "" +"Kann ein Objekt nicht befreien (edict: %d, classname: %s, origin: %s)\n" + +#: qcsrc/client/movetypes.qc:166 +#, c-format +msgid "Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)\n" +msgstr "" +"Ein Objekt wurde erfolgreich befreit (edict: %d, classname: %s, origin: %s)\n" + +#: qcsrc/client/scoreboard.qc:19 +msgid "SCO^bckills" +msgstr "BC getötet" + +#: qcsrc/client/scoreboard.qc:20 +msgid "SCO^bctime" +msgstr "Ballbesitz" + +#: qcsrc/client/scoreboard.qc:21 +msgid "SCO^caps" +msgstr "Caps" + +#: qcsrc/client/scoreboard.qc:22 +msgid "SCO^deaths" +msgstr "Deaths" + +#: qcsrc/client/scoreboard.qc:23 +msgid "SCO^destroyed" +msgstr "zerstört" + +#: qcsrc/client/scoreboard.qc:24 +msgid "SCO^drops" +msgstr "verloren" + +#: qcsrc/client/scoreboard.qc:25 +msgid "SCO^faults" +msgstr "Fehler" + +#: qcsrc/client/scoreboard.qc:26 +msgid "SCO^fckills" +msgstr "FC getötet" + +#: qcsrc/client/scoreboard.qc:27 +msgid "SCO^goals" +msgstr "Tore" + +#: qcsrc/client/scoreboard.qc:28 +msgid "SCO^kckills" +msgstr "KC getötet" + +#: qcsrc/client/scoreboard.qc:29 +msgid "SCO^kdratio" +msgstr "kdratio" + +#: qcsrc/client/scoreboard.qc:30 +msgid "SCO^k/d" +msgstr "k/d" + +#: qcsrc/client/scoreboard.qc:31 +msgid "SCO^kd" +msgstr "kd" + +#: qcsrc/client/scoreboard.qc:32 +msgid "SCO^kdr" +msgstr "kdr" + +#: qcsrc/client/scoreboard.qc:33 +msgid "SCO^kills" +msgstr "Kills" + +#: qcsrc/client/scoreboard.qc:34 +msgid "SCO^laps" +msgstr "Runden" + +#: qcsrc/client/scoreboard.qc:35 +msgid "SCO^lives" +msgstr "Leben" + +#: qcsrc/client/scoreboard.qc:36 +msgid "SCO^losses" +msgstr "verloren" + +#: qcsrc/client/scoreboard.qc:37 +msgid "SCO^name" +msgstr "Name" + +#: qcsrc/client/scoreboard.qc:38 +msgid "SCO^nick" +msgstr "Nick" + +#: qcsrc/client/scoreboard.qc:39 +msgid "SCO^objectives" +msgstr "Objectives" + +#: qcsrc/client/scoreboard.qc:40 +msgid "SCO^pickups" +msgstr "Flaggen" + +#: qcsrc/client/scoreboard.qc:41 +msgid "SCO^ping" +msgstr "Ping" + +#: qcsrc/client/scoreboard.qc:42 +msgid "SCO^pl" +msgstr "PL" + +#: qcsrc/client/scoreboard.qc:43 +msgid "SCO^pushes" +msgstr "Pushes" + +#: qcsrc/client/scoreboard.qc:44 +msgid "SCO^rank" +msgstr "Rang" + +#: qcsrc/client/scoreboard.qc:45 +msgid "SCO^returns" +msgstr "Returns" + +#: qcsrc/client/scoreboard.qc:46 +msgid "SCO^revivals" +msgstr "Wiederbelebt" + +#: qcsrc/client/scoreboard.qc:47 +msgid "SCO^score" +msgstr "Punkte" + +#: qcsrc/client/scoreboard.qc:48 +msgid "SCO^suicides" +msgstr "Suiz." + +#: qcsrc/client/scoreboard.qc:49 +msgid "SCO^takes" +msgstr "Übernahmen" + +#: qcsrc/client/scoreboard.qc:50 +msgid "SCO^ticks" +msgstr "Ticks" + +#: qcsrc/client/scoreboard.qc:239 +msgid "" +"You can modify the scoreboard using the ^2scoreboard_columns_set command.\n" +msgstr "" +"Sie können die Tabelle mit dem ^2scoreboard_columns_set Befehl ändern.\n" + +#: qcsrc/client/scoreboard.qc:240 +msgid "^3|---------------------------------------------------------------|\n" +msgstr "^3|---------------------------------------------------------------|\n" + +#: qcsrc/client/scoreboard.qc:242 +msgid "^2scoreboard_columns_set default\n" +msgstr "^2scoreboard_columns_set default\n" + +#: qcsrc/client/scoreboard.qc:243 +msgid "^2scoreboard_columns_set ^7field1 field2 ...\n" +msgstr "^2scoreboard_columns_set ^7field1 field2 ...\n" + +#: qcsrc/client/scoreboard.qc:244 +msgid "The following field names are recognized (case insensitive):\n" +msgstr "Die folgenden Feldnamen werden akzeptiert:\n" + +#: qcsrc/client/scoreboard.qc:245 +msgid "" +"You can use a ^3|^7 to start the right-aligned fields.\n" +"\n" +msgstr "Mit ^3|^7 werden die rechtsbündigen Felder gestartet.\n" + +#: qcsrc/client/scoreboard.qc:247 +msgid "^3name^7 or ^3nick^7 Name of a player\n" +msgstr "^3name^7 oder ^3nick^7 Name des Spielers\n" + +#: qcsrc/client/scoreboard.qc:248 +msgid "^3ping^7 Ping time\n" +msgstr "^3ping^7 Ping\n" + +#: qcsrc/client/scoreboard.qc:249 +msgid "^3pl^7 Packet loss\n" +msgstr "^3pl^7 Paketverlust\n" + +#: qcsrc/client/scoreboard.qc:250 +msgid "^3kills^7 Number of kills\n" +msgstr "^3kills^7 Anzahl Kills\n" + +#: qcsrc/client/scoreboard.qc:251 +msgid "^3deaths^7 Number of deaths\n" +msgstr "^3deaths^7 Anzahl der Tode\n" + +#: qcsrc/client/scoreboard.qc:252 +msgid "^3suicides^7 Number of suicides\n" +msgstr "^3suicides^7 Anzahl der Suizide\n" + +#: qcsrc/client/scoreboard.qc:253 +msgid "^3frags^7 kills - suicides\n" +msgstr "^3frags^7 Kills minus Suizide\n" + +#: qcsrc/client/scoreboard.qc:254 +msgid "^3kd^7 The kill-death ratio\n" +msgstr "^3kd^7 Das Kill/Death-Ratio\n" + +#: qcsrc/client/scoreboard.qc:255 +msgid "" +"^3caps^7 How often a flag (CTF) or a key (KeyHunt) was " +"captured\n" +msgstr "" +"^3caps^7 Wie oft mit der Flagge (CTF) oder den " +"Schlüssels (KeyHunt) gepunktet wurde\n" + +#: qcsrc/client/scoreboard.qc:256 +msgid "" +"^3pickups^7 How often a flag (CTF) or a key (KeyHunt) or a " +"ball (Keepaway) was picked up\n" +msgstr "" +"^3pickups^7 Wie oft die Flagge/Schlüssel aufgenommen " +"wurden\n" + +#: qcsrc/client/scoreboard.qc:257 +msgid "^3fckills^7 Number of flag carrier kills\n" +msgstr "^3fckills^7 Wieviele Flaggenträger getötet wurden\n" + +#: qcsrc/client/scoreboard.qc:258 +msgid "^3returns^7 Number of flag returns\n" +msgstr "^3returns^7 Wie oft die Flagge zurückgebracht wurde\n" + +#: qcsrc/client/scoreboard.qc:259 +msgid "^3drops^7 Number of flag drops\n" +msgstr "^3drops^7 Wie oft die Flagge verloren wurde\n" + +#: qcsrc/client/scoreboard.qc:260 +msgid "^3lives^7 Number of lives (LMS)\n" +msgstr "^3lives^7 Anzahl Leben (LMS)\n" + +#: qcsrc/client/scoreboard.qc:261 +msgid "^3rank^7 Player rank\n" +msgstr "^3rank^7 Rang des Spielers\n" + +#: qcsrc/client/scoreboard.qc:262 +msgid "^3pushes^7 Number of players pushed into void\n" +msgstr "^3pushes^7 Anzahl in die Tiefe geworfener Gegner\n" + +#: qcsrc/client/scoreboard.qc:263 +msgid "" +"^3destroyed^7 Number of keys destroyed by pushing them into " +"void\n" +msgstr "" +"^3destroyed^7 Wie oft ein Gegner mit Schlüssel in die Tiefe " +"geworfen wurde\n" + +#: qcsrc/client/scoreboard.qc:264 +msgid "^3kckills^7 Number of keys carrier kills\n" +msgstr "^3kckills^7 Wie oft Key-Carrier getötet wurden\n" + +#: qcsrc/client/scoreboard.qc:265 +msgid "^3losses^7 Number of times a key was lost\n" +msgstr "^3losses^7 Anzahl verlorener Schlüssel\n" + +#: qcsrc/client/scoreboard.qc:266 +msgid "^3laps^7 Number of laps finished (race/cts)\n" +msgstr "^3laps^7 Anzahl vollendeter Runden (race/cts)\n" + +#: qcsrc/client/scoreboard.qc:267 +msgid "^3time^7 Total time raced (race/cts)\n" +msgstr "^3time^7 Gesamtzeit des Rennens (race/cts)\n" + +#: qcsrc/client/scoreboard.qc:268 +msgid "^3fastest^7 Time of fastest lap (race/cts)\n" +msgstr "^3fastest^7 Zeit der schnellsten Runde (race/cts)\n" + +#: qcsrc/client/scoreboard.qc:269 +msgid "^3ticks^7 Number of ticks (DOM)\n" +msgstr "^3ticks^7 Anzahl der Ticks (DOM)\n" + +#: qcsrc/client/scoreboard.qc:270 +msgid "^3takes^7 Number of domination points taken (DOM)\n" +msgstr "^3takes^7 Anzahl eingenommener Dom-Points (DOM)\n" + +#: qcsrc/client/scoreboard.qc:271 +msgid "^3bckills^7 Number of ball carrier kills\n" +msgstr "^3bckills^7 Wieviele Ballträger getötet wurden\n" + +#: qcsrc/client/scoreboard.qc:272 +msgid "" +"^3bctime^7 Total amount of time holding the ball in " +"Keepaway\n" +msgstr "^3bctime^7 Gesamtzeit des Ballbesitzes\n" + +#: qcsrc/client/scoreboard.qc:273 +msgid "" +"^3score^7 Total score\n" +"\n" +msgstr "" +"^3score^7 Gesamtpunktzahl\n" +"\n" + +#: qcsrc/client/scoreboard.qc:275 +msgid "" +"Before a field you can put a + or - sign, then a comma separated list\n" +"of game types, then a slash, to make the field show up only in these\n" +"or in all but these game types. You can also specify 'all' as a\n" +"field to show all fields available for the current game mode.\n" +"\n" +msgstr "" +"Vor ein Feld können Sie ein Plus- oder Minuszeichen setzen, anschließend\n" +"eine durch Kommata getrennte Liste von Spieltypen, dann einen Slash, so " +"dass\n" +"das Feld nur in diesen, oder in allen außer diesen Spieltypen erscheint.\n" +"Außerdem kann \"all\" als Feldname verwendet werden; in diesem Fall " +"erscheinen\n" +"sämtliche möglichen Felder im aktuellen Spieltyp.\n" +"\n" + +#: qcsrc/client/scoreboard.qc:280 +msgid "" +"The special game type names 'teams' and 'noteams' can be used to\n" +"include/exclude ALL teams/noteams game modes.\n" +"\n" +msgstr "" +"Die speziellen Bezeichner 'teams' und 'noteams' können verwendet werden\n" +"als Gruppierung aller Teamplay- oder Nicht-Teamplay-Spieltypen.\n" +"\n" + +#: qcsrc/client/scoreboard.qc:283 +msgid "Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4\n" +msgstr "Beispiel: scoreboard_columns_set name ping pl < +ctf/feld3 dm/feld4\n" + +#: qcsrc/client/scoreboard.qc:284 +msgid "" +"will display name, ping and pl aligned to the left, and the fields\n" +"right of the vertical bar aligned to the right.\n" +msgstr "" +"wird Name, Ping und Paketverlust linksbündig, und die Felder rechts\n" +"von der Trennlinie (und rechtsbündig) anzeigen.\n" + +#: qcsrc/client/scoreboard.qc:286 +msgid "" +"'field3' will only be shown in CTF, and 'field4' will be shown in all\n" +"other gamemodes except DM.\n" +msgstr "" +"'feld3' wird nur in CTF sichtbar sein, und 'feld4' wird in allen Spieltypen\n" +"außer DM erscheinen.\n" + +#: qcsrc/client/scoreboard.qc:432 qcsrc/client/scoreboard.qc:447 +#: qcsrc/client/scoreboard.qc:457 qcsrc/client/scoreboard.qc:466 +#: qcsrc/client/scoreboard.qc:475 +#, c-format +msgid "fixed missing field '%s'\n" +msgstr "Fehlendes Feld '%s' wurde ergänzt.\n" + +#: qcsrc/client/scoreboard.qc:515 qcsrc/client/scoreboard.qc:522 +msgid "N/A" +msgstr "-" + +#: qcsrc/client/scoreboard.qc:950 +#, c-format +msgid "Accuracy stats (average %d%%)" +msgstr "Genauigkeit (Durchschn.: %d%%)" + +#: qcsrc/client/scoreboard.qc:1015 +#, c-format +msgid "%d%%" +msgstr "%d%%" + +#: qcsrc/client/scoreboard.qc:1085 +msgid "Map stats:" +msgstr "Map-Statistiken:" + +#: qcsrc/client/scoreboard.qc:1101 +msgid "Secrets found:" +msgstr "Geheimnisse:" + +#: qcsrc/client/scoreboard.qc:1128 +msgid "Rankings" +msgstr "Platzierungen" + +#: qcsrc/client/scoreboard.qc:1223 +msgid "Scoreboard" +msgstr "Tabelle" + +#: qcsrc/client/scoreboard.qc:1268 +#, c-format +msgid "Speed award: %d ^7(%s^7)" +msgstr "Höchstgeschwindigkeit: %d ^7(%s^7)" + +#: qcsrc/client/scoreboard.qc:1272 +#, c-format +msgid "All-time fastest: %d ^7(%s^7)" +msgstr "Rekord: %d ^7(%s^7)" + +#: qcsrc/client/scoreboard.qc:1305 qcsrc/client/teamplay.qc:63 +msgid "Spectators" +msgstr "Zuschauer" + +#: qcsrc/client/scoreboard.qc:1311 +#, c-format +msgid "playing on ^2%s^7" +msgstr "es wird auf ^2%s^7 gespielt" + +#: qcsrc/client/scoreboard.qc:1318 qcsrc/client/scoreboard.qc:1323 +#, c-format +msgid " for up to ^1%1.0f minutes^7" +msgstr " für bis zu ^1%.1f Minuten^7" + +#: qcsrc/client/scoreboard.qc:1327 qcsrc/client/scoreboard.qc:1346 +msgid " or" +msgstr " oder" + +#: qcsrc/client/scoreboard.qc:1330 qcsrc/client/scoreboard.qc:1337 +#, c-format +msgid " until ^3%s %s^7" +msgstr " bis ^3%s %s^7" + +#: qcsrc/client/scoreboard.qc:1331 qcsrc/client/scoreboard.qc:1338 +#: qcsrc/client/scoreboard.qc:1350 qcsrc/client/scoreboard.qc:1357 +msgid "SCO^points" +msgstr "Punkte" + +#: qcsrc/client/scoreboard.qc:1332 qcsrc/client/scoreboard.qc:1339 +#: qcsrc/client/scoreboard.qc:1351 qcsrc/client/scoreboard.qc:1358 +msgid "SCO^is beaten" +msgstr "geschlagen wird" + +#: qcsrc/client/scoreboard.qc:1349 qcsrc/client/scoreboard.qc:1356 +#, c-format +msgid " until a lead of ^3%s %s^7" +msgstr " bis zu einem Vorsprung von ^3%s %s^7" + +#: qcsrc/client/target_music.qc:93 qcsrc/client/target_music.qc:181 +#, c-format +msgid "Cannot initialize sound %s\n" +msgstr "Kann Sound %s nicht initialisieren\n" + +#: qcsrc/client/teamplay.qc:64 +msgid "Red Team" +msgstr "Rotes Team" + +#: qcsrc/client/teamplay.qc:65 +msgid "Blue Team" +msgstr "Blaues Team" + +#: qcsrc/client/teamplay.qc:66 +msgid "Yellow Team" +msgstr "Gelbes Team" + +#: qcsrc/client/teamplay.qc:67 +msgid "Pink Team" +msgstr "Pinkes Team" + +#: qcsrc/client/tturrets.qc:285 qcsrc/client/waypointsprites.qc:590 +msgid "Spam" +msgstr "Frühstücksfleisch" + +#: qcsrc/client/tturrets.qc:294 +#, c-format +msgid "%s under attack!" +msgstr "%s wird angegriffen!" + +#: qcsrc/client/waypointsprites.qc:254 +msgid "Push" +msgstr "Drücken" + +#: qcsrc/client/waypointsprites.qc:255 +msgid "Destroy" +msgstr "Zerstören" + +#: qcsrc/client/waypointsprites.qc:256 +msgid "Defend" +msgstr "Verteidigen" + +#: qcsrc/client/waypointsprites.qc:257 +msgid "Blue base" +msgstr "Blaue Basis" + +#: qcsrc/client/waypointsprites.qc:258 +msgid "DANGER" +msgstr "GEFAHR" + +#: qcsrc/client/waypointsprites.qc:259 +msgid "Flag carrier" +msgstr "Flaggenträger" + +#: qcsrc/client/waypointsprites.qc:260 +msgid "Dropped flag" +msgstr "Flagge" + +#: qcsrc/client/waypointsprites.qc:261 +msgid "Help me!" +msgstr "Hilfe!" + +#: qcsrc/client/waypointsprites.qc:262 +msgid "Here" +msgstr "Hier" + +#: qcsrc/client/waypointsprites.qc:263 +msgid "Dropped key" +msgstr "Schlüssel" + +#: qcsrc/client/waypointsprites.qc:264 qcsrc/client/waypointsprites.qc:266 +#: qcsrc/client/waypointsprites.qc:267 qcsrc/client/waypointsprites.qc:268 +#: qcsrc/client/waypointsprites.qc:269 +msgid "Key carrier" +msgstr "Schlüsselträger" + +#: qcsrc/client/waypointsprites.qc:265 +msgid "Run here" +msgstr "Hier her!" + +#: qcsrc/client/waypointsprites.qc:270 +msgid "Red base" +msgstr "Rote Basis" + +#: qcsrc/client/waypointsprites.qc:271 +msgid "Waypoint" +msgstr "Wegpunkt" + +#: qcsrc/client/waypointsprites.qc:272 qcsrc/client/waypointsprites.qc:273 +#: qcsrc/client/waypointsprites.qc:274 +msgid "Generator" +msgstr "Generator" + +#: qcsrc/client/waypointsprites.qc:275 qcsrc/client/waypointsprites.qc:276 +#: qcsrc/client/waypointsprites.qc:277 qcsrc/client/waypointsprites.qc:278 +#: qcsrc/client/waypointsprites.qc:279 qcsrc/client/waypointsprites.qc:280 +#: qcsrc/client/waypointsprites.qc:281 qcsrc/client/waypointsprites.qc:282 +#: qcsrc/client/waypointsprites.qc:306 qcsrc/client/waypointsprites.qc:307 +#: qcsrc/client/waypointsprites.qc:308 qcsrc/client/waypointsprites.qc:309 +#: qcsrc/client/waypointsprites.qc:310 +msgid "Control point" +msgstr "Kontrollpunkt" + +#: qcsrc/client/waypointsprites.qc:283 +msgid "Checkpoint" +msgstr "Checkpoint" + +#: qcsrc/client/waypointsprites.qc:284 qcsrc/client/waypointsprites.qc:286 +msgid "Finish" +msgstr "Ziel" + +#: qcsrc/client/waypointsprites.qc:285 qcsrc/client/waypointsprites.qc:286 +msgid "Start" +msgstr "Start" + +#: qcsrc/client/waypointsprites.qc:287 qcsrc/client/waypointsprites.qc:288 +msgid "Ball" +msgstr "Ball" + +#: qcsrc/client/waypointsprites.qc:289 +msgid "Ball carrier" +msgstr "Ballbesitzer" + +#: qcsrc/client/waypointsprites.qc:290 qcsrc/server/w_laser.qc:2 +msgid "Laser" +msgstr "Laser" + +#: qcsrc/client/waypointsprites.qc:291 qcsrc/server/w_shotgun.qc:2 +msgid "Shotgun" +msgstr "Shotgun" + +#: qcsrc/client/waypointsprites.qc:292 qcsrc/server/w_uzi.qc:2 +msgid "Machine Gun" +msgstr "Machine Gun" + +#: qcsrc/client/waypointsprites.qc:293 qcsrc/server/w_grenadelauncher.qc:2 +msgid "Mortar" +msgstr "Mortar" + +#: qcsrc/client/waypointsprites.qc:294 qcsrc/server/w_electro.qc:2 +msgid "Electro" +msgstr "Electro" + +#: qcsrc/client/waypointsprites.qc:295 qcsrc/server/w_crylink.qc:2 +msgid "Crylink" +msgstr "Crylink" + +#: qcsrc/client/waypointsprites.qc:296 qcsrc/server/w_nex.qc:2 +msgid "Nex" +msgstr "Nex" + +#: qcsrc/client/waypointsprites.qc:297 qcsrc/server/w_hagar.qc:2 +msgid "Hagar" +msgstr "Hagar" + +#: qcsrc/client/waypointsprites.qc:298 qcsrc/server/w_rocketlauncher.qc:2 +msgid "Rocket Launcher" +msgstr "Rocket Launcher" + +#: qcsrc/client/waypointsprites.qc:299 qcsrc/server/w_porto.qc:2 +msgid "Port-O-Launch" +msgstr "Port-O-Launch" + +#: qcsrc/client/waypointsprites.qc:300 +msgid "Minstanex" +msgstr "MinstaNex" + +#: qcsrc/client/waypointsprites.qc:301 +msgid "Hook" +msgstr "Enterhaken" + +#: qcsrc/client/waypointsprites.qc:302 qcsrc/server/w_fireball.qc:2 +msgid "Fireball" +msgstr "Fireball" + +#: qcsrc/client/waypointsprites.qc:303 +msgid "HLAC" +msgstr "HLAC" + +#: qcsrc/client/waypointsprites.qc:304 qcsrc/server/w_rifle.qc:2 +msgid "Rifle" +msgstr "Gewehr" + +#: qcsrc/client/waypointsprites.qc:305 qcsrc/server/w_minelayer.qc:2 +msgid "Mine Layer" +msgstr "Mine Layer" + +#: qcsrc/client/waypointsprites.qc:311 +msgid "Invisibility" +msgstr "Unsichtbarkeit" + +#: qcsrc/client/waypointsprites.qc:312 +msgid "Extra life" +msgstr "Extraleben" + +#: qcsrc/client/waypointsprites.qc:313 +msgid "Speed" +msgstr "Geschwindigkeit" + +#: qcsrc/client/waypointsprites.qc:314 +msgid "Strength" +msgstr "Stärke" + +#: qcsrc/client/waypointsprites.qc:315 +msgid "Shield" +msgstr "Schutzschild" + +#: qcsrc/client/waypointsprites.qc:316 +msgid "Fuel regen" +msgstr "Treibstoff-Regeneration" + +#: qcsrc/client/waypointsprites.qc:317 +msgid "Jet Pack" +msgstr "Jetpack" + +#: qcsrc/client/waypointsprites.qc:318 +msgid "Frozen!" +msgstr "Eingefroren!" + +#: qcsrc/client/waypointsprites.qc:319 +msgid "Tagged" +msgstr "Getaggt!" + +#: qcsrc/client/waypointsprites.qc:320 +msgid "Vehicle" +msgstr "Fahrzeug" + +#: qcsrc/client/waypointsprites.qc:594 +#, c-format +msgid "%s needing help!" +msgstr "%s braucht Hilfe!" + +#: qcsrc/common/mapinfo.qc:1097 +#, c-format +msgid "%s: %s" +msgstr "%s: %s" + +#: qcsrc/server/w_crylink.qc:666 +#, c-format +msgid "%s succeeded at self-destructing themself with the Crylink" +msgstr "%s zerstörte sich selbst erfolgreich mit der Crylink" + +#: qcsrc/server/w_crylink.qc:671 +#, c-format +msgid "%s could not hide from %s's Crylink" +msgstr "%s konnte sich nicht vor %ss Crylink verstecken" + +#: qcsrc/server/w_crylink.qc:673 +#, c-format +msgid "%s was too close to %s's Crylink" +msgstr "%s trat %ss Crylink zu nahe" + +#: qcsrc/server/w_crylink.qc:675 +#, c-format +msgid "%s took a close look at %s's Crylink" +msgstr "%s schaute sich %ss Crylink sehr genau an" + +#: qcsrc/server/w_electro.qc:581 +#, c-format +msgid "%s could not remember where they put their electro plasma" +msgstr "%s vergaß, wo er das Plasma hingetan hatte" + +#: qcsrc/server/w_electro.qc:583 +#, c-format +msgid "%s played with electro plasma" +msgstr "%s spielte mit Plasma" + +#: qcsrc/server/w_electro.qc:590 +#, c-format +msgid "%s just noticed %s's electro plasma" +msgstr "%s hat gerade %ss Plasma bemerkt" + +#: qcsrc/server/w_electro.qc:592 +#, c-format +msgid "%s got in touch with %s's electro plasma" +msgstr "%s kam mit %ss Plasma in Kontakt" + +#: qcsrc/server/w_electro.qc:597 +#, c-format +msgid "%s felt the electrifying air of %s's electro combo" +msgstr "%s hat gespürt, wie %ss Combo die Luft elektrisierte" + +#: qcsrc/server/w_electro.qc:599 +#, c-format +msgid "%s got too close to %s's blue electro bolt" +msgstr "%s kam zu nah an %ss blauen Strahl" + +#: qcsrc/server/w_electro.qc:601 +#, c-format +msgid "%s was blasted by %s's blue electro bolt" +msgstr "%s wurde von %ss blauen Strahl erwischt" + +#: qcsrc/server/w_fireball.qc:421 +#, c-format +msgid "%s forgot about some firemine" +msgstr "%s hat den Platz einer Feuermine vergessen" + +#: qcsrc/server/w_fireball.qc:423 qcsrc/server/w_hlac.qc:240 +#, c-format +msgid "%s should have used a smaller gun" +msgstr "%s hätte eine kleinere Waffe nehmen sollen" + +#: qcsrc/server/w_fireball.qc:430 +#, c-format +msgid "%s tried to catch %s's firemine" +msgstr "%s hat versucht %ss Feuermine zu fangen" + +#: qcsrc/server/w_fireball.qc:432 +#, c-format +msgid "%s fatefully ignored %s's firemine" +msgstr "%s hat tragischerweise %ss Feuermine ignoriert" + +#: qcsrc/server/w_fireball.qc:439 +#, c-format +msgid "%s could not hide from %s's fireball" +msgstr "%s konnte sich nicht vor %ss Feuerball verstecken" + +#: qcsrc/server/w_fireball.qc:441 +#, c-format +msgid "%s saw the pretty lights of %s's fireball" +msgstr "%s hat die hübschen Lichter von %ss Feuerball gesehen" + +#: qcsrc/server/w_fireball.qc:444 +#, c-format +msgid "%s got too close to %s's fireball" +msgstr "%s ist %ss Feuerball zu nahe getreten" + +#: qcsrc/server/w_fireball.qc:446 +#, c-format +msgid "%s tasted %s's fireball" +msgstr "%s hat von %ss Feuerball probiert" + +#: qcsrc/server/w_grenadelauncher.qc:388 +#, c-format +msgid "%s didn't see their own grenade" +msgstr "%s hat die eigene Granate übersehen" + +#: qcsrc/server/w_grenadelauncher.qc:390 +#, c-format +msgid "%s blew themself up with their grenadelauncher" +msgstr "%s hat sich mit einem Granatenwerfer selbst in die Luft gejagt" + +#: qcsrc/server/w_grenadelauncher.qc:396 +#, c-format +msgid "%s didn't see %s's grenade" +msgstr "%s hat %ss Granate nicht gesehen" + +#: qcsrc/server/w_grenadelauncher.qc:398 +#, c-format +msgid "%s almost dodged %s's grenade" +msgstr "%s ist fast %ss Granate ausgewichen" + +#: qcsrc/server/w_grenadelauncher.qc:400 +#, c-format +msgid "%s ate %s's grenade" +msgstr "%s nahm %ss Granate in den Mund" + +#: qcsrc/server/w_hagar.qc:462 +#, c-format +msgid "%s played with tiny hagar rockets" +msgstr "%s hat mit kleinen Raketen gespielt" + +#: qcsrc/server/w_hagar.qc:466 +#, c-format +msgid "%s was pummeled with a burst of hagar rockets by %s" +msgstr "%s ist von %s durchlöchert worden wie ein Schweizer Käse" + +#: qcsrc/server/w_hagar.qc:468 +#, c-format +msgid "%s was pummeled with hagar rockets by %s" +msgstr "%s wurde von %ss Hagar-Raketen erwischt" + +#: qcsrc/server/w_hlac.qc:2 +msgid "Heavy Laser Assault Cannon" +msgstr "Heavy Laser Assault Cannon" + +#: qcsrc/server/w_hlac.qc:242 +#, c-format +msgid "%s was cut down with a HLAC by %s" +msgstr "%s wurde von %ss HLAC niedergehauen" + +#: qcsrc/server/w_hook.qc:2 +msgid "Grappling Hook" +msgstr "Enterhaken" + +#: qcsrc/server/w_hook.qc:286 qcsrc/server/w_porto.qc:296 +#, c-format +msgid "%s did the impossible" +msgstr "%s hat das Unmögliche geschafft" + +#: qcsrc/server/w_hook.qc:288 +#, c-format +msgid "%s was caught in %s's hook gravity bomb" +msgstr "%s ist in %ss Gravitationsbombe reingelaufen" + +#: qcsrc/server/w_laser.qc:312 +#, c-format +msgid "%s lasered themself to hell" +msgstr "%s hat sich in die Hölle gelasert" + +#: qcsrc/server/w_laser.qc:316 +#, c-format +msgid "%s was cut in half by %s's gauntlet" +msgstr "%s ist von %ss Gauntlet halbiert worden" + +#: qcsrc/server/w_laser.qc:318 +#, c-format +msgid "%s was lasered to death by %s" +msgstr "^1%s^1 wurde von %s^1 zu Tode gelasert" + +#: qcsrc/server/w_minelayer.qc:533 +#, c-format +msgid "%s blew themself up with their minelayer" +msgstr "%s hat sich mit einem Minenleger selbst in die Luft gejagt" + +#: qcsrc/server/w_minelayer.qc:535 +#, c-format +msgid "%s forgot about their mine" +msgstr "%s hat den Platz einer Mine vergessen" + +#: qcsrc/server/w_minelayer.qc:539 +#, c-format +msgid "%s got too close to %s's mine" +msgstr "%s ist %ss Mine zu nahe getreten" + +#: qcsrc/server/w_minelayer.qc:541 +#, c-format +msgid "%s almost dodged %s's mine" +msgstr "%s ist fast %ss Mine ausgewichen" + +#: qcsrc/server/w_minelayer.qc:543 +#, c-format +msgid "%s stepped on %s's mine" +msgstr "%s ist auf %ss Mine gelatscht" + +#: qcsrc/server/w_minstanex.qc:2 +msgid "MinstaNex" +msgstr "MinstaNex" + +#: qcsrc/server/w_minstanex.qc:293 qcsrc/server/w_nex.qc:253 +#: qcsrc/server/w_rifle.qc:232 qcsrc/server/w_shotgun.qc:271 +#: qcsrc/server/w_uzi.qc:318 +#, c-format +msgid "%s is now thinking with portals" +msgstr "%s kann jetzt mit Portalen denken" + +#: qcsrc/server/w_minstanex.qc:295 +#, c-format +msgid "%s has been vaporized by %s's minstanex" +msgstr "%s^1 wurde von %ss MinstaNex vernichtet" + +#: qcsrc/server/w_nex.qc:255 +#, c-format +msgid "%s has been vaporized by %s's nex" +msgstr "%s^1 wurde von %ss Nex vernichtet" + +#: qcsrc/server/w_porto.qc:298 +#, c-format +msgid "%s felt %s doing the impossible to him" +msgstr "%s hat gespürt, wie %s das Unmögliche für ihn getan hat" + +#: qcsrc/server/w_rifle.qc:239 +#, c-format +msgid "%s failed to hide from %s's rifle bullet hail" +msgstr "%s hat es nicht geschafft, sich vor %ss Kugelhagel zu verstecken" + +#: qcsrc/server/w_rifle.qc:241 +#, c-format +msgid "%s died in %s's rifle bullet hail" +msgstr "%s ist in %ss Kugelhagel gefallen" + +#: qcsrc/server/w_rifle.qc:248 +#, c-format +msgid "%s failed to hide from %s's rifle" +msgstr "%s hat es nicht geschafft, sich vor %ss Gewehr zu verstecken" + +#: qcsrc/server/w_rifle.qc:253 +#, c-format +msgid "%s got shot in the head with a rifle by %s" +msgstr "%s hat ein Loch im Kopf bekommen; schuld war %s" + +#: qcsrc/server/w_rifle.qc:255 +#, c-format +msgid "%s was sniped with a rifle by %s" +msgstr "%s wurde von %s fachmännisch erledigt" + +#: qcsrc/server/w_rocketlauncher.qc:507 +#, c-format +msgid "%s blew themself up with their rocketlauncher" +msgstr "%s hat sich mit einem Raketenwerfer selbst in die Luft gejagt" + +#: qcsrc/server/w_rocketlauncher.qc:511 +#, c-format +msgid "%s got too close to %s's rocket" +msgstr "%s ist %ss Rakete zu nahe getreten" + +#: qcsrc/server/w_rocketlauncher.qc:513 +#, c-format +msgid "%s almost dodged %s's rocket" +msgstr "%s ist fast %ss Rakete ausgewichen" + +#: qcsrc/server/w_rocketlauncher.qc:515 +#, c-format +msgid "%s ate %s's rocket" +msgstr "%s hat %ss Rakete in den Mund genommen" + +#: qcsrc/server/w_seeker.qc:2 +msgid "T.A.G. Seeker" +msgstr "T.A.G. Seeker" + +#: qcsrc/server/w_seeker.qc:661 +#, c-format +msgid "%s played with tiny seeker rockets" +msgstr "%s hat mit kleinen Raketen gespielt" + +#: qcsrc/server/w_seeker.qc:665 +#, c-format +msgid "%s was tagged with a seeker by %s" +msgstr "%s wurde von %s getagged" + +#: qcsrc/server/w_seeker.qc:667 +#, c-format +msgid "%s was pummeled with seeker rockets by %s" +msgstr "%s wurde von %s erwischt" + +#: qcsrc/server/w_shotgun.qc:275 +#, c-format +msgid "%2$s slapped %1$s around a bit with a large shotgun" +msgstr "%2$s hat %1$s ein wenig mit einer großen Schrotflinte geschlagen" + +#: qcsrc/server/w_shotgun.qc:277 +#, c-format +msgid "%s was gunned down with a shotgun by %s" +msgstr "%s wurde von %s erschossen" + +#: qcsrc/server/w_tuba.qc:2 +#, c-format +msgid "@!#%'n Tuba" +msgstr "@!#%'n Tuba" + +#: qcsrc/server/w_tuba.qc:444 +#, c-format +msgid "%s hurt his own ears with the @!#%%'n Tuba" +msgstr "" +"%s haben die Ohren geschmerzt von seinem eigenen Spiel auf der @!#%%'n Tuba" + +#: qcsrc/server/w_tuba.qc:447 +#, c-format +msgid "%s hurt his own ears with the @!#%%'n Accordeon" +msgstr "" +"%s haben die Ohren geschmerzt von seinem eigenen Spiel auf dem @!#%%'n " +"Akkordeon" + +#: qcsrc/server/w_tuba.qc:465 +#, c-format +msgid "%s died of %s's great playing on the @!#%%'n Tuba" +msgstr "" +"%s ist an seinen Ohrenschmerzen, die von %ss großartigem Spiel auf der @!#" +"%%'n Tuba stammten, gestorben" + +#: qcsrc/server/w_tuba.qc:468 +#, c-format +msgid "%s died of %s's great playing on the @!#%%'n Accordeon" +msgstr "" +"%s ist an seinen Ohrenschmerzen, die von %ss großartigem Spiel auf dem @!#" +"%%'n Akkordeon stammten, gestorben" + +#: qcsrc/server/w_uzi.qc:322 +#, c-format +msgid "%s was sniped by %s's machine gun" +msgstr "%s wurde von %ss Maschinengewehr erledigt" + +#: qcsrc/server/w_uzi.qc:324 +#, c-format +msgid "%s was riddled full of holes by %s's machine gun" +msgstr "%s ist von %s durchlöchert worden wie ein Schweizer Käse" + +#~ msgid "%s sniped themself somehow" +#~ msgstr "%s hat so scharf geschossen, dass er sich selbst getroffen hat" + +#~ msgid "%s shot themself automatically" +#~ msgstr "%s hat sich vollautomatisch selbst erschossen" + +#~ msgid "%s exploded" +#~ msgstr "%s ist explodiert" + +#~ msgid "%s hoped %s's missiles wouldn't bounce" +#~ msgstr "%s hat gehofft, dass %ss Raketen nicht von Wänden abprallen" + +#~ msgid "%s detonated" +#~ msgstr "%s verfing sich in der eigenen Detonation" + +#~ msgid "%s tried out his own grenade" +#~ msgstr "%s wollte wissen, ob seine Granate funktioniert" + +#~ msgid "Awaiting orders..." +#~ msgstr "Warten auf Auftrag..." + +#~ msgid "You're commander!" +#~ msgstr "Sie sind Befehlshaber!" + +#~ msgid "3) Resign from command." +#~ msgstr "3) Befehlsgewalt abgeben." + +#~ msgid " 2) Defend" +#~ msgstr " 2) Verteidigen" + +#~ msgid " 1) Attack" +#~ msgstr " 1) Angreifen" + +#~ msgid "Issue orders:" +#~ msgstr "Auftrag geben:" + +#~ msgid "----- Command Menu -----" +#~ msgstr "---- Befehlsmenü -----" + +#~ msgid "Couldn't find player %d\n" +#~ msgstr "Kann Spieler %d nicht finden\n" + +#~ msgid "ESC) Exit Menu" +#~ msgstr "ESC) Menü verlassen" + +#~ msgid "2) ^3next page" +#~ msgstr "2) ^3nächste Seite" + +#~ msgid "1) ^3previous page" +#~ msgstr "1) ^3vorherige Seite" + +#~ msgid "Order: %s" +#~ msgstr "Auftrag: %s" + +#~ msgid "----- Order Menu -----" +#~ msgstr "----- Auftragsmenü -----" diff --git a/csprogs.dat.it.po b/csprogs.dat.it.po new file mode 100644 index 0000000000..5ef2982eb9 --- /dev/null +++ b/csprogs.dat.it.po @@ -0,0 +1,1996 @@ +# Xonotic CSQC +# Copyright (C) 2011 Team Xonotic +# This file is distributed under the same license as the Xonotic package. +# Felice Sallustio , 2011. +# Antonio 'terencehill' Piu , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: 0.1preview\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-09-02 07:51+0200\n" +"PO-Revision-Date: 2011-09-04 01:40+0100\n" +"Last-Translator: Antonio 'terencehill' Piu \n" +"Language-Team: Antonio 'terencehill' Piu \n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Italian\n" + +#: qcsrc/client/Main.qc:30 +msgid "ERROR - MENU IS VISIBLE BUT NO MENU WAS DEFINED!" +msgstr "ERRORE - IL MENU E' VISIBILE MA NESSUN MENU E' STATO DEFINITO!" + +#: qcsrc/client/Main.qc:56 +msgid "" +"^3Your engine build is outdated\n" +"^3This Server uses a newer QC VM. Please update!\n" +msgstr "" +"^3La tua versione del motore logico è vecchia\n" +"^3Questo server usa un nuovo QC VM. Per favore aggiornalo!\n" + +#: qcsrc/client/Main.qc:66 +#, c-format +msgid "^4CSQC Build information: ^1%s\n" +msgstr "^4Informazioni sulla build CSQC: ^1%s\n" + +#: qcsrc/client/Main.qc:237 qcsrc/client/Main.qc:253 +#, c-format +msgid "trying to switch to unsupported team %d\n" +msgstr "tentando di passare al team non supportato %d\n" + +#: qcsrc/client/Main.qc:369 qcsrc/client/scoreboard.qc:241 +msgid "Usage:\n" +msgstr "Uso:\n" + +#: qcsrc/client/Main.qc:370 +msgid "hud_save configname (saves to hud_skinname_configname.cfg)\n" +msgstr "hud_save configname (salva in hud_skinname_configname.cfg)\n" + +#: qcsrc/client/Main.qc:494 +msgid "Usage: cl_cmd COMMAND..., where possible commands are:\n" +msgstr "Uso: cl_cmd COMANDO..., dove i possibili comandi sono:\n" + +#: qcsrc/client/Main.qc:495 +msgid " settemp cvar value\n" +msgstr " settemp cvar value\n" + +#: qcsrc/client/Main.qc:496 +msgid " scoreboard_columns_set ...\n" +msgstr " scoreboard_columns_set ...\n" + +#: qcsrc/client/Main.qc:497 +msgid " scoreboard_columns_help\n" +msgstr " scoreboard_columns_help\n" + +#: qcsrc/client/Main.qc:726 +#, c-format +msgid "A CSQC entity changed its owner! (edict: %d, classname: %s)\n" +msgstr "" +"Un'entity CSQC ha cambiato il suo proprietario! (edict: %d, classname: %s)\n" + +#: qcsrc/client/Main.qc:964 +#, c-format +msgid "A CSQC entity changed its type! (edict: %d, classname: %s)\n" +msgstr "Un'entity CSQC ha cambiato il suo tipo! (edict: %d, classname: %s)\n" + +#: qcsrc/client/Main.qc:1005 +#, c-format +msgid "" +"Unknown entity type in CSQC_Ent_Update (enttype: %d, edict: %d, classname: " +"%s)\n" +msgstr "" +"Tipo di entity sconosciuta in CSQC_Ent_Update (enttype: %d, edict: %d, " +"classname: %s)\n" + +#: qcsrc/client/Main.qc:1451 +#, c-format +msgid "%s (not bound)" +msgstr "%s (nessun tasto)" + +#: qcsrc/client/Main.qc:1456 qcsrc/client/hud.qc:230 +#, c-format +msgid "%s (%s)" +msgstr "%s (%s)" + +#: qcsrc/client/ctf.qc:35 +msgid "----- Order Menu -----" +msgstr "----- Menu degli ordini -----" + +#: qcsrc/client/ctf.qc:36 +#, c-format +msgid "Order: %s" +msgstr "Ordine: %s" + +#: qcsrc/client/ctf.qc:37 +msgid "1) ^3previous page" +msgstr "1) ^3pagina precedente" + +#: qcsrc/client/ctf.qc:38 +msgid "2) ^3next page" +msgstr "2) ^3pagina successiva" + +#: qcsrc/client/ctf.qc:55 qcsrc/client/ctf.qc:161 +msgid "ESC) Exit Menu" +msgstr "ESC) Esci dal menu" + +#: qcsrc/client/ctf.qc:126 +#, c-format +msgid "Couldn't find player %d\n" +msgstr "Impossibile trovare il giocatore %d\n" + +#: qcsrc/client/ctf.qc:154 +msgid "----- Command Menu -----" +msgstr "----- Menu dei comandi -----" + +#: qcsrc/client/ctf.qc:155 +msgid "Issue orders:" +msgstr "Impartisci ordini:" + +#: qcsrc/client/ctf.qc:156 +msgid " 1) Attack" +msgstr " 1) Attacca" + +#: qcsrc/client/ctf.qc:158 +msgid " 2) Defend" +msgstr " 2) Difendi" + +#: qcsrc/client/ctf.qc:160 +msgid "3) Resign from command." +msgstr "3) Dimettiti dal commando." + +#: qcsrc/client/ctf.qc:212 +msgid "You're commander!" +msgstr "Sei il comandante!" + +#: qcsrc/client/ctf.qc:215 +msgid "Awaiting orders..." +msgstr "Attendendo ordini..." + +#: qcsrc/client/hud.qc:160 +msgid "1st" +msgstr "1°" + +#: qcsrc/client/hud.qc:162 +msgid "2nd" +msgstr "2°" + +#: qcsrc/client/hud.qc:164 +msgid "3rd" +msgstr "3°" + +#: qcsrc/client/hud.qc:166 +#, c-format +msgid "%dth" +msgstr "%d°" + +#: qcsrc/client/hud.qc:198 +#, c-format +msgid " (-%dL)" +msgstr " (-%dG)" + +#: qcsrc/client/hud.qc:203 +#, c-format +msgid " (+%dL)" +msgstr " (+%dG)" + +#: qcsrc/client/hud.qc:219 +msgid "Start line" +msgstr "Linea di partenza" + +#: qcsrc/client/hud.qc:221 qcsrc/client/hud.qc:225 +msgid "Finish line" +msgstr "Linea d'arrivo" + +#: qcsrc/client/hud.qc:223 +#, c-format +msgid "Intermediate %d" +msgstr "Intermedio %d" + +#: qcsrc/client/hud.qc:232 +#, c-format +msgid "%s (%s %s)" +msgstr "%s (%s %s)" + +#: qcsrc/client/hud.qc:735 +msgid "Out of ammo" +msgstr "Scarica" + +#: qcsrc/client/hud.qc:739 +msgid "Don't have" +msgstr "Mancante" + +#: qcsrc/client/hud.qc:743 +msgid "Unavailable" +msgstr "Non disponibile" + +#: qcsrc/client/hud.qc:1483 +#, c-format +msgid "^1%s^1 couldn't take it anymore\n" +msgstr "^1%s^1 non ne poteva più\n" + +#: qcsrc/client/hud.qc:1487 qcsrc/client/hud.qc:1791 +#, c-format +msgid "^1%s^1 died\n" +msgstr "^1%s^1 è morto\n" + +#: qcsrc/client/hud.qc:1491 +#, c-format +msgid "^7%s^7 committed suicide. What's the point of living without ammo?\n" +msgstr "" +"^7%s^7 ha commesso suicidio. Qual'è il motivo di vivere senza munizioni?\n" + +#: qcsrc/client/hud.qc:1495 +#, c-format +msgid "^1%s^1 thought they found a nice camping ground\n" +msgstr "^1%s^1 pensava di trovare un bel campeggio\n" + +#: qcsrc/client/hud.qc:1499 +#, c-format +msgid "^1%s^1 didn't become friends with the Lord of Teamplay\n" +msgstr "^1%s^1 non è diventato amico del Signore del Teamplay\n" + +#: qcsrc/client/hud.qc:1503 +#, c-format +msgid "^1%s^1 unfairly eliminated themself\n" +msgstr "^1%s^1 si è eliminato ingiustamente\n" + +#: qcsrc/client/hud.qc:1507 +#, c-format +msgid "^1%s^1 burned to death\n" +msgstr "^1%s^1 è morto bruciato\n" + +#: qcsrc/client/hud.qc:1511 +#, c-format +msgid "^1%s^1 couldn't resist the urge to self-destruct\n" +msgstr "^1%s^1 non ha resistito allo stimolo di autodistruggersi\n" + +#: qcsrc/client/hud.qc:1515 +#, c-format +msgid "^1%s^1 ended it all after a %d kill spree\n" +msgstr "^1%s^1 l'ha fatta finita con una serie di %d uccisioni\n" + +#: qcsrc/client/hud.qc:1532 +#, c-format +msgid "^1%s^1 took action against a team mate\n" +msgstr "^1%s^1 ha agito contro un compagno di squadra\n" + +#: qcsrc/client/hud.qc:1534 +#, c-format +msgid "^1%s^1 mows down a team mate\n" +msgstr "^1%s^1 ha falciato un compagno di squadra\n" + +#: qcsrc/client/hud.qc:1539 +#, c-format +msgid "^1%s^1 ended a %d scoring spree by going against a team mate\n" +msgstr "" +"^1%s^1 ha concluso una serie di %d punti per esser andato contro un compagno " +"di squadra\n" + +#: qcsrc/client/hud.qc:1541 +#, c-format +msgid "^1%s^1 ended a %d kill spree by killing a team mate\n" +msgstr "" +"^1%s^1 ha concluso una serie di %d uccisioni per aver ammazzato un compagno " +"di squadra\n" + +#: qcsrc/client/hud.qc:1545 +#, c-format +msgid "^1%s^1's %s scoring spree was ended by a team mate!\n" +msgstr "" +"^1La serie di ^1%s^1 di ^1%s^1 punti è stata conclusa da un compagno di " +"squadra!\n" + +#: qcsrc/client/hud.qc:1547 +#, c-format +msgid "^1%s^1's %s kill spree was ended by a team mate!\n" +msgstr "" +"^1La serie di ^1%s ^1di ^1%s ^1uccisioni è stata conclusa da un compagno di " +"squadra!\n" + +#: qcsrc/client/hud.qc:1551 +#, c-format +msgid "^1%s^1 drew first blood\n" +msgstr "^1%s^1 ha tratto la prima uccisione\n" + +#: qcsrc/client/hud.qc:1555 +#, c-format +msgid "^1%s^1 tried to occupy %s^1's teleport destination space\n" +msgstr "" +"^1%s^1 ha provato a occupare lo spazio di destinazione della teleporta di " +"%s\n" + +#: qcsrc/client/hud.qc:1557 +#, c-format +msgid "^1%s^1 was telefragged by %s\n" +msgstr "^1%s^1 è stato telefraggato da %s\n" + +#: qcsrc/client/hud.qc:1562 +#, c-format +msgid "^1%s^1 was drowned by %s\n" +msgstr "^1%s^1 è stato annegato da %s\n" + +#: qcsrc/client/hud.qc:1567 +#, c-format +msgid "^1%s^1 was slimed by %s\n" +msgstr "^1%s^1 è stato coperto di melma da %s\n" + +#: qcsrc/client/hud.qc:1572 +#, c-format +msgid "^1%s^1 was cooked by %s\n" +msgstr "^1%s^1 è stato cucinato da %s\n" + +#: qcsrc/client/hud.qc:1577 +#, c-format +msgid "^1%s^1 was grounded by %s\n" +msgstr "^1%s^1 è stato messo a terra da %s\n" + +#: qcsrc/client/hud.qc:1582 +#, c-format +msgid "^1%s^1 was shot into space by %s\n" +msgstr "^1%s^1 è stato buttato nello spazio da %s\n" + +#: qcsrc/client/hud.qc:1587 +#, c-format +msgid "^1%s^1 was conserved by %s\n" +msgstr "^1%s^1 è stato conservato da %s\n" + +#: qcsrc/client/hud.qc:1593 +#, c-format +msgid "^1%s^1 was thrown into a world of hurt by %s\n" +msgstr "^1%s^1 è stato lanciato in un mondo di dolore da %s\n" + +#: qcsrc/client/hud.qc:1597 +#, c-format +msgid "^1%s^1 was crushed by %s\n" +msgstr "^1%s^1 è stato schiacciato da %s\n" + +#: qcsrc/client/hud.qc:1601 +#, c-format +msgid "^1%s^1 got shredded by %s\n" +msgstr "^1%s^1 è stato triturato da %s\n" + +#: qcsrc/client/hud.qc:1605 +#, c-format +msgid "^1%s^1 was blasted to bits by %s\n" +msgstr "^1%s^1 è stato disintegrato da %s\n" + +#: qcsrc/client/hud.qc:1609 +#, c-format +msgid "^1%s^1 got caught in the destruction of %s^1's vehicle\n" +msgstr "^1%s^1 è caduto nella distruzione del veicolo di %s\n" + +#: qcsrc/client/hud.qc:1613 +#, c-format +msgid "^1%s^1 was bolted down by %s\n" +msgstr "^1%s^1 è stato imbullonato da %s\n" + +#: qcsrc/client/hud.qc:1617 +#, c-format +msgid "^1%s^1 could find no shelter from %s^1's rockets\n" +msgstr "^1%s^1 non ha trovato riparo dai razzi di %s\n" + +#: qcsrc/client/hud.qc:1621 +#, c-format +msgid "^1%s^1 dies when %s^1's wakizashi dies.\n" +msgstr "^1%s^1 muore mentre il wakizashi di %s^1 muore.\n" + +#: qcsrc/client/hud.qc:1625 +#, c-format +msgid "^1%s^1 nailed to hell by %s\n" +msgstr "^1%s^1 è stato inchiodato all'inferno da %s\n" + +#: qcsrc/client/hud.qc:1629 +#, c-format +msgid "^1%s^1 cluster crushed by %s\n" +msgstr "^1L'ammasso di ^1%s^1 è stato schiacciato da %s\n" + +#: qcsrc/client/hud.qc:1633 +#, c-format +msgid "^1%s^1 dies when %s^1's raptor dies.\n" +msgstr "^1%s^1 muore mentre il raptor di %s^1 muore.\n" + +#: qcsrc/client/hud.qc:1637 +#, c-format +msgid "^1%s^1 was pushed into the line of fire by %s\n" +msgstr "^1%s^1 è stato spinto nella linea di fuoco da %s\n" + +#: qcsrc/client/hud.qc:1641 +#, c-format +msgid "^1%s^1 was pushed into an accident by %s\n" +msgstr "^1%s^1 è stato spinto in un incidente da %s\n" + +#: qcsrc/client/hud.qc:1645 +#, c-format +msgid "^1%s^1 was unfairly eliminated by %s\n" +msgstr "^1%s^1 è stato ingiustamente eliminato da %s\n" + +#: qcsrc/client/hud.qc:1649 +#, c-format +msgid "^1%s^1 was burnt to death by %s\n" +msgstr "^1%s^1 è stato bruciato a morte da %s\n" + +#: qcsrc/client/hud.qc:1661 +#, c-format +msgid "^1%s^1 was fragged by %s\n" +msgstr "^1%s^1 è stato fraggato da %s\n" + +#: qcsrc/client/hud.qc:1666 +#, c-format +msgid "^1%s^1's %s scoring spree was ended by %s\n" +msgstr "^1La serie di ^1%s ^1di ^1%s^1 punti è stata conclusa da %s\n" + +#: qcsrc/client/hud.qc:1668 +#, c-format +msgid "^1%s^1's %s kill spree was ended by %s\n" +msgstr "^1La serie di %s^1 di ^1%s^1 uccisioni è stata conclusa da %s\n" + +#: qcsrc/client/hud.qc:1671 +#, c-format +msgid "^1%s^1 made %s scores in a row\n" +msgstr "^1%s^1 ha fatto %s punti di fila\n" + +#: qcsrc/client/hud.qc:1673 +#, c-format +msgid "^1%s^1 has %s frags in a row\n" +msgstr "^1%s^1 ha %s frag di fila\n" + +#: qcsrc/client/hud.qc:1676 +#, c-format +msgid "%s^7 made a ^1TRIPLE SCORE\n" +msgstr "%s^7 ha realizzato un ^1TRIPLO PUNTO\n" + +#: qcsrc/client/hud.qc:1678 +#, c-format +msgid "%s^7 made a ^1TRIPLE FRAG\n" +msgstr "%s^7 ha realizzato un ^1FRAG TRIPLO\n" + +#: qcsrc/client/hud.qc:1681 +#, c-format +msgid "%s^7 unleashes ^1SCORING RAGE\n" +msgstr "%s^7 scatena una ^1FURIA DI PUNTI\n" + +#: qcsrc/client/hud.qc:1683 +#, c-format +msgid "%s^7 unleashes ^1RAGE\n" +msgstr "%s^7 scatena la propria ^1FURIA\n" + +#: qcsrc/client/hud.qc:1686 +#, c-format +msgid "%s^7 made ^1TEN SCORES IN A ROW!\n" +msgstr "%s^7 ha realizzato ^1DIECI PUNTI DI FILA!\n" + +#: qcsrc/client/hud.qc:1688 +#, c-format +msgid "%s^7 starts the ^1MASSACRE!\n" +msgstr "%s^7 ha iniziato il ^1MASSACRO!\n" + +#: qcsrc/client/hud.qc:1691 +#, c-format +msgid "%s^7 made ^1FIFTEEN SCORES IN A ROW!\n" +msgstr "%s^7 ha realizzato ^QUINDICI PUNTI DI FILA!\n" + +#: qcsrc/client/hud.qc:1693 +#, c-format +msgid "%s^7 executes ^1MAYHEM!\n" +msgstr "%s^7 ha eseguito un ^1MAYHEM!\n" + +#: qcsrc/client/hud.qc:1696 +#, c-format +msgid "%s^7 made ^1TWENTY SCORES IN A ROW!\n" +msgstr "%s^7 ha realizzato ^1VENTI PUNTI DI FILA!\n" + +#: qcsrc/client/hud.qc:1698 +#, c-format +msgid "%s^7 is a ^1BERSERKER!\n" +msgstr "%s^7 è un ^1FEROCE GUERRIERO!\n" + +#: qcsrc/client/hud.qc:1701 +#, c-format +msgid "%s^7 made ^1TWENTY FIVE SCORES IN A ROW!\n" +msgstr "%s^7 ha realizzato ^1VENTICINQUE PUNTI DI FILA!\n" + +#: qcsrc/client/hud.qc:1703 +#, c-format +msgid "%s^7 inflicts ^1CARNAGE!\n" +msgstr "%s^7 ha fatto una ^1CARNEFICINA!\n" + +#: qcsrc/client/hud.qc:1706 +#, c-format +msgid "%s^7 made ^1THIRTY SCORES IN A ROW!\n" +msgstr "%s^7 ha realizzato ^1TRENTA PUNTI DI FILA!\n" + +#: qcsrc/client/hud.qc:1708 +#, c-format +msgid "%s^7 unleashes ^1ARMAGEDDON!\n" +msgstr "%s^7 scatena un ^1ARMAGEDDON!\n" + +#: qcsrc/client/hud.qc:1716 +#, c-format +msgid "^1%s^1 was in the water for too long\n" +msgstr "^1%s^1 è stato in acqua per troppo tempo\n" + +#: qcsrc/client/hud.qc:1718 +#, c-format +msgid "^1%s^1 drowned\n" +msgstr "^1%s^1 è annegato\n" + +#: qcsrc/client/hud.qc:1723 +#, c-format +msgid "^1%s^1 was slimed\n" +msgstr "^1%s^1 è stato coperto di melma\n" + +#: qcsrc/client/hud.qc:1729 +#, c-format +msgid "^1%s^1 found a hot place\n" +msgstr "^1%s^1 ha trovato un posto caldo\n" + +#: qcsrc/client/hud.qc:1731 +#, c-format +msgid "^1%s^1 turned into hot slag\n" +msgstr "^1%s^1 è finito dentro la lava bollente\n" + +#: qcsrc/client/hud.qc:1738 +#, c-format +msgid "^1%s^1 tested gravity (and it worked)\n" +msgstr "^1%s^1 ha testato la gravità (e ha funzionato)\n" + +#: qcsrc/client/hud.qc:1740 +#, c-format +msgid "^1%s^1 hit the ground with a crunch\n" +msgstr "^1%s^1 ha fatto scricchiolare il terreno\n" + +#: qcsrc/client/hud.qc:1745 +#, c-format +msgid "^1%s^1 became a shooting star\n" +msgstr "^1%s^1 è diventato una stella cadente\n" + +#: qcsrc/client/hud.qc:1751 +#, c-format +msgid "^1%s^1 discovered a swamp\n" +msgstr "^1%s^1 ha scoperto una palude\n" + +#: qcsrc/client/hud.qc:1753 +#, c-format +msgid "^1%s^1 is now conserved for centuries to come\n" +msgstr "^1%s^1 è ora conservato per i secoli a venire\n" + +#: qcsrc/client/hud.qc:1758 +#, c-format +msgid "^1%s^1 was mowed down by a turret \n" +msgstr "^1%s^1 è stato falciato da una torretta \n" + +#: qcsrc/client/hud.qc:1770 +#, c-format +msgid "^1%s^1 died in an accident\n" +msgstr "^1%s^1 è morto in un incidente\n" + +#: qcsrc/client/hud.qc:1774 +#, c-format +msgid "^1%s^1 was unfairly eliminated\n" +msgstr "^1%s^1 è stato ingiustamente eliminato\n" + +#: qcsrc/client/hud.qc:1780 +#, c-format +msgid "^1%s^1 felt a little hot\n" +msgstr "^1%s^1 ha sentito un pò di caldo\n" + +#: qcsrc/client/hud.qc:1782 +#, c-format +msgid "^1%s^1 burnt to death\n" +msgstr "^1%s^1 è morto bruciato\n" + +#: qcsrc/client/hud.qc:1789 +#, c-format +msgid "^1%s^1 needs a restart\n" +msgstr "^1%s^1 ha bisogno di una ripresa\n" + +#: qcsrc/client/hud.qc:1796 +#, c-format +msgid "^1%s^1 needs a restart after a %d scoring spree\n" +msgstr "^1%s^1 ha bisogno di una ripresa dopo una serie di %d punti\n" + +#: qcsrc/client/hud.qc:1798 +#, c-format +msgid "^1%s^1 died with a %d kill spree\n" +msgstr "^1%s^1 è morto dopo una serie di %d uccisioni\n" + +#: qcsrc/client/hud.qc:1802 +#, c-format +msgid "%s^7 got the %s\n" +msgstr "%s^7 ha preso la %s\n" + +#: qcsrc/client/hud.qc:1805 +#, c-format +msgid "%s^7 lost the %s\n" +msgstr "%s^7 ha perso la %s\n" + +#: qcsrc/client/hud.qc:1808 +#, c-format +msgid "%s^7 picked up the %s\n" +msgstr "%s^7 ha raccolto la %s\n" + +#: qcsrc/client/hud.qc:1811 +#, c-format +msgid "%s^7 returned the %s\n" +msgstr "%s^7 ha fatto ritornare la %s\n" + +#: qcsrc/client/hud.qc:1814 +#, c-format +msgid "%s^7 captured the %s%s\n" +msgstr "%s^7 ha catturato la %s%s\n" + +#: qcsrc/client/hud.qc:1833 +#, c-format +msgid "%s^7 has picked up the ball!\n" +msgstr "%s^7 ha raccolto la palla!\n" + +#: qcsrc/client/hud.qc:1838 +#, c-format +msgid "%s^7 has dropped the ball!\n" +msgstr "%s^7 ha rilasciato la palla!\n" + +#: qcsrc/client/hud.qc:1849 +#, c-format +msgid "You are now on: %s" +msgstr "Sei ora in: %s" + +#: qcsrc/client/hud.qc:1851 +#, c-format +msgid "" +"You have been moved into a different team to improve team balance\n" +"You are now on: %s" +msgstr "" +"Sei stato spostato in una squadra differente per migliorare il bilanciamento " +"delle squadre\n" +"Sei ora in: %s" + +#: qcsrc/client/hud.qc:1854 +msgid "^1Reconsider your tactics, camper!" +msgstr "^1Riconsidera le tue tattiche, camper!" + +#: qcsrc/client/hud.qc:1856 +msgid "^1Die camper!" +msgstr "^1Muori camper!" + +#: qcsrc/client/hud.qc:1859 +msgid "^1You are reinserted into the game for running out of ammo..." +msgstr "^1Sei reinserito nel gioco per mancanza di munizioni..." + +#: qcsrc/client/hud.qc:1861 +msgid "^1You were killed for running out of ammo..." +msgstr "^1Sei stato ucciso per mancanza di munizioni..." + +#: qcsrc/client/hud.qc:1864 +msgid "^1You need to preserve your health" +msgstr "^1Hai bisogno di preservare la tua vita" + +#: qcsrc/client/hud.qc:1866 +msgid "^1You grew too old without taking your medicine" +msgstr "^1Sei diventato troppo vecchio senza prendere le tue medicine" + +#: qcsrc/client/hud.qc:1869 +msgid "^1Don't go against team mates!" +msgstr "^1Non andare contro i tuoi compagni di squadra!" + +#: qcsrc/client/hud.qc:1871 +msgid "^1Don't shoot your team mates!" +msgstr "^1Non sparare ai tuoi compagni di squadra!" + +#: qcsrc/client/hud.qc:1876 +msgid "^1You need to be more careful!" +msgstr "^1Hai bisogno di essere più prudente!" + +#: qcsrc/client/hud.qc:1878 +msgid "^1You killed your own dumb self!" +msgstr "^1Ti sei ammazzato da solo, stupido!" + +#: qcsrc/client/hud.qc:1883 +#, c-format +msgid "^1Moron! You went against ^7%s^1, a team mate!" +msgstr "^1Idiota! Sei andato contro ^7%s^1, un compagno di squadra!" + +#: qcsrc/client/hud.qc:1885 +#, c-format +msgid "^1Moron! You fragged ^7%s^1, a team mate!" +msgstr "^1Idiota! Hai fraggato ^7%s^1, un compagno di squadra!" + +#: qcsrc/client/hud.qc:1889 +msgid "^1First score" +msgstr "^1Primo punto" + +#: qcsrc/client/hud.qc:1891 +msgid "^1First blood" +msgstr "^1Primo sangue" + +#: qcsrc/client/hud.qc:1895 +msgid "^1First casualty" +msgstr "^1Primo incidente" + +#: qcsrc/client/hud.qc:1897 +msgid "^1First victim" +msgstr "^1Prima vittima" + +#: qcsrc/client/hud.qc:1901 +#, c-format +msgid "^1You scored against ^7%s^1 who was typing!" +msgstr "^1Hai segnato contro ^7%s^1 che stava scrivendo!" + +#: qcsrc/client/hud.qc:1903 +#, c-format +msgid "^1You typefragged ^7%s" +msgstr "^1Hai \"typefraggato\" ^7%s" + +#: qcsrc/client/hud.qc:1907 +#, c-format +msgid "^1You were scored against by ^7%s^1 while you were typing!" +msgstr "^1Sei stato segnato da ^7%s^1 mentre stavi scrivendo!" + +#: qcsrc/client/hud.qc:1909 +#, c-format +msgid "^1You were typefragged by ^7%s" +msgstr "^1Sei stato \"typefraggato\" da ^7%s" + +#: qcsrc/client/hud.qc:1913 +#, c-format +msgid "^4You scored against ^7%s" +msgstr "^4Hai segnato contro ^7%s" + +#: qcsrc/client/hud.qc:1915 +#, c-format +msgid "^4You fragged ^7%s" +msgstr "^4Hai fraggato ^7%s" + +#: qcsrc/client/hud.qc:1919 +#, c-format +msgid "^1You were scored against by ^7%s" +msgstr "^1Sei stato segnato da ^7%s" + +#: qcsrc/client/hud.qc:1921 +#, c-format +msgid "^1You were fragged by ^7%s" +msgstr "^1Sei stato fraggato da ^7%s" + +#: qcsrc/client/hud.qc:1926 +msgid "^1Watch your step!" +msgstr "^1Attento a dove metti i piedi!" + +#: qcsrc/client/hud.qc:1995 qcsrc/client/hud.qc:1996 qcsrc/client/hud.qc:2481 +#, c-format +msgid "Player %d" +msgstr "Giocatore %d" + +#: qcsrc/client/hud.qc:2786 +msgid "^1Intermediate 1 (+15.42)" +msgstr "^1Intermedio 1 (+15.42)" + +#: qcsrc/client/hud.qc:2788 qcsrc/client/hud.qc:2830 qcsrc/client/hud.qc:2871 +#, c-format +msgid "^1PENALTY: %.1f (%s)" +msgstr "^1PENALITÀ: %.1f (%s)" + +#: qcsrc/client/hud.qc:2873 +#, c-format +msgid "^2PENALTY: %.1f (%s)" +msgstr "^2PENALITÀ: %.1f (%s)" + +#: qcsrc/client/hud.qc:2901 +msgid "^1You must answer before entering hud configure mode\n" +msgstr "" +"^1Devi rispondere prima di entrare nella modalità di configurazione " +"dell'HUD\n" + +#: qcsrc/client/hud.qc:2904 +msgid "^2Name ^7instead of \"^1Unregistered player^7\" in stats" +msgstr "^2Nome ^7invece di \"^1Giocatore non registrato^7\" nelle statistiche" + +#: qcsrc/client/hud.qc:2986 +msgid "A vote has been called for:" +msgstr "Un voto è stato chiamato per:" + +#: qcsrc/client/hud.qc:2988 +msgid "Allow servers to store and display your name?" +msgstr "Permetti ai server di salvare e visualizzare il tuo nome?" + +#: qcsrc/client/hud.qc:2992 +msgid "^1Configure the HUD" +msgstr "^1Configura l'HUD" + +#: qcsrc/client/hud.qc:2996 +#, c-format +msgid "Yes (%s): %d" +msgstr "Sì (%s): %d" + +#: qcsrc/client/hud.qc:2998 +#, c-format +msgid "No (%s): %d" +msgstr "No (%s): %d" + +#: qcsrc/client/hud.qc:3501 qcsrc/client/hud.qc:3504 qcsrc/client/hud.qc:3506 +msgid "Personal best" +msgstr "Miglior personale" + +#: qcsrc/client/hud.qc:3519 qcsrc/client/hud.qc:3522 qcsrc/client/hud.qc:3524 +msgid "Server best" +msgstr "Migliori del server" + +#: qcsrc/client/hud.qc:3868 +msgid "^3Player^7: This is the chat area." +msgstr "^3Giocatore^7: Questa è l'area della chat." + +#: qcsrc/client/hud.qc:3936 +#, c-format +msgid "FPS: %.*f" +msgstr "FPS: %.*f" + +#: qcsrc/client/hud.qc:4003 +msgid "^1Observing" +msgstr "^1Osservando" + +#: qcsrc/client/hud.qc:4005 +#, c-format +msgid "^1Spectating: ^7%s" +msgstr "^1Assistendo: ^7%s" + +#: qcsrc/client/hud.qc:4009 +#, c-format +msgid "^1Press ^3%s^1 to spectate" +msgstr "^1Premi ^3%s^1 per assistere" + +#: qcsrc/client/hud.qc:4011 +#, c-format +msgid "^1Press ^3%s^1 for another player" +msgstr "^1Premi ^3%s^1 per un altro giocatore" + +#: qcsrc/client/hud.qc:4015 +#, c-format +msgid "^1Use ^3%s^1 or ^3%s^1 to change the speed" +msgstr "^1Usa ^3%s^1 o ^3%s^1 per cambiare velocità" + +#: qcsrc/client/hud.qc:4017 +#, c-format +msgid "^1Press ^3%s^1 to observe" +msgstr "^1Premi ^3%s^1 per osservare" + +#: qcsrc/client/hud.qc:4020 +#, c-format +msgid "^1Press ^3%s^1 for gamemode info" +msgstr "^1Premi ^3%s^1 per informazioni sulla modalità di gioco" + +#: qcsrc/client/hud.qc:4024 +msgid "^1Wait for your turn to join" +msgstr "^1Attendi il tuo turno per entrare" + +#: qcsrc/client/hud.qc:4030 +msgid "^1Match has already begun" +msgstr "^1La partita è già iniziata" + +#: qcsrc/client/hud.qc:4032 +msgid "^1You have no more lives left" +msgstr "^1Non hai più vite a disposizione" + +#: qcsrc/client/hud.qc:4034 qcsrc/client/hud.qc:4037 +#, c-format +msgid "^1Press ^3%s^1 to join" +msgstr "^1Premi ^3%s^1 per entrare" + +#: qcsrc/client/hud.qc:4045 +#, c-format +msgid "^1Game starts in ^3%d^1 seconds" +msgstr "^1La partita inizia tra ^3%d^1 secondi" + +#: qcsrc/client/hud.qc:4052 +msgid "^2Currently in ^1warmup^2 stage!" +msgstr "^2Attualmente in ^1warmup^2!" + +#: qcsrc/client/hud.qc:4067 +#, c-format +msgid "%sPress ^3%s%s to end warmup" +msgstr "%sPremi ^3%s%s per terminare il warmup" + +#: qcsrc/client/hud.qc:4069 +#, c-format +msgid "%sPress ^3%s%s once you are ready" +msgstr "%sPremi ^3%s%s una volta che sei pronto" + +#: qcsrc/client/hud.qc:4074 +msgid "^2Waiting for others to ready up to end warmup..." +msgstr "^2Attendendo che gli altri siano pronti per terminare il warmup..." + +#: qcsrc/client/hud.qc:4076 +msgid "^2Waiting for others to ready up..." +msgstr "^2Attendendo che gli altri siano pronti..." + +#: qcsrc/client/hud.qc:4082 +#, c-format +msgid "^2Press ^3%s^2 to end warmup" +msgstr "^2Premi ^3%s^2 per terminare il warmup" + +#: qcsrc/client/hud.qc:4103 +msgid "Teamnumbers are unbalanced!" +msgstr "Numero di giocatori per squadra sbilanciato!" + +#: qcsrc/client/hud.qc:4108 +#, c-format +msgid " Press ^3%s%s to adjust" +msgstr " Premi ^3%s%s per aggiustare" + +#: qcsrc/client/hud.qc:4116 +msgid "^7Press ^3ESC ^7to show HUD options." +msgstr "^7Premi ^3ESC ^7per mostrare le opzioni dell'HUD." + +#: qcsrc/client/hud.qc:4118 +msgid "^3Doubleclick ^7a panel for panel-specific options." +msgstr "^3Doppio-click ^7su un pannello per le sue specifiche opzioni." + +#: qcsrc/client/hud.qc:4120 +msgid "^3CTRL ^7to disable collision testing, ^3SHIFT ^7and" +msgstr "^3CTRL ^7per disabilitare il test di collisione, ^3SHIFT ^7e" + +#: qcsrc/client/hud.qc:4122 +msgid "^3ALT ^7+ ^3ARROW KEYS ^7for fine adjustments." +msgstr "^3ALT ^7+ ^3ARROW KEYS ^7per fini aggiustamenti" + +#: qcsrc/client/hud.qc:4160 +msgid " qu/s" +msgstr " qu/s" + +#: qcsrc/client/hud.qc:4164 +msgid " m/s" +msgstr " m/s" + +#: qcsrc/client/hud.qc:4168 +msgid " km/h" +msgstr " km/h" + +#: qcsrc/client/hud.qc:4172 +msgid " mph" +msgstr " mph" + +#: qcsrc/client/hud.qc:4176 +msgid " knots" +msgstr " nodi" + +#: qcsrc/client/hud.qc:4823 +msgid "Automatically fixed wrong/missing panel numbers in _hud_panelorder\n" +msgstr "" +"Corretti automaticamente numeri di pannello sbagliati/mancanti in " +"_hud_panelorder\n" + +#: qcsrc/client/hud_config.qc:136 +#, c-format +msgid "^2Successfully exported to %s! (Note: It's saved in data/data/)\n" +msgstr "^2Esportato con successo in %s! (nota: E' salvato in data/data/)\n" + +#: qcsrc/client/hud_config.qc:140 +#, c-format +msgid "^1Couldn't write to %s\n" +msgstr "^1Impossibile scrivere in %s\n" + +#: qcsrc/client/mapvoting.qc:28 +msgid " (1 vote)" +msgstr " (1 voto)" + +#: qcsrc/client/mapvoting.qc:30 +#, c-format +msgid " (%d votes)" +msgstr " (%d voti)" + +#: qcsrc/client/mapvoting.qc:113 +msgid "Don't care" +msgstr "Non importa" + +#: qcsrc/client/mapvoting.qc:194 +msgid "Vote for a map" +msgstr "Vota per una mappa" + +#: qcsrc/client/mapvoting.qc:200 +#, c-format +msgid "%d seconds left" +msgstr "%d secondi rimanenti" + +#: qcsrc/client/mapvoting.qc:263 +msgid "" +"mv_mapdownload: ^3You're not supposed to use this command on your own!\n" +msgstr "mv_mapdownload: ^3Non avrai creduto di poter usare questo comando!\n" + +#: qcsrc/client/mapvoting.qc:273 +msgid "^1Error:^7 Couldn't find pak index.\n" +msgstr "^1Errore:^7 Impossibile trovare il pak index.\n" + +#: qcsrc/client/mapvoting.qc:282 +msgid "Requesting preview...\n" +msgstr "Richiedendo l'anteprima...\n" + +#: qcsrc/client/miscfunctions.qc:23 +msgid "^1Begin!" +msgstr "^1Inizia!" + +#: qcsrc/client/miscfunctions.qc:34 +#, c-format +msgid "^1Game starts in %d seconds" +msgstr "^1Il gioco inizia tra %d secondi" + +#: qcsrc/client/miscfunctions.qc:113 +msgid "^1RED^7 flag" +msgstr "^7Bandiera ^1ROSSA" + +#: qcsrc/client/miscfunctions.qc:118 +msgid "^4BLUE^7 flag" +msgstr "^7Bandiera ^4BLU" + +#: qcsrc/client/miscfunctions.qc:126 +#, c-format +msgid "You picked up the %s!" +msgstr "Hai raccolto la %s!" + +#: qcsrc/client/miscfunctions.qc:130 +#, c-format +msgid "You got the %s!" +msgstr "Hai preso la %s!" + +#: qcsrc/client/miscfunctions.qc:283 +msgid "Trying to remove a team which is not in the teamlist!" +msgstr "Tentando di rimuovere una squadra che non è nella lista delle squadre!" + +#: qcsrc/client/movetypes.qc:163 +#, c-format +msgid "Can't unstick an entity (edict: %d, classname: %s, origin: %s)\n" +msgstr "Can't unstick an entity (edict: %d, classname: %s, origin: %s)\n" + +#: qcsrc/client/movetypes.qc:166 +#, c-format +msgid "Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)\n" +msgstr "Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)\n" + +#: qcsrc/client/scoreboard.qc:19 +msgid "SCO^bckills" +msgstr "uccisioni pp" + +#: qcsrc/client/scoreboard.qc:20 +msgid "SCO^bctime" +msgstr "tempo pp" + +#: qcsrc/client/scoreboard.qc:21 +msgid "SCO^caps" +msgstr "SCO^catture" + +#: qcsrc/client/scoreboard.qc:22 +msgid "SCO^deaths" +msgstr "SCO^morti" + +#: qcsrc/client/scoreboard.qc:23 +msgid "SCO^destroyed" +msgstr "SCO^distrutte" + +#: qcsrc/client/scoreboard.qc:24 +msgid "SCO^drops" +msgstr "SCO^cadute" + +#: qcsrc/client/scoreboard.qc:25 +msgid "SCO^faults" +msgstr "SCO^falli" + +#: qcsrc/client/scoreboard.qc:26 +msgid "SCO^fckills" +msgstr "uccisioni pb" + +#: qcsrc/client/scoreboard.qc:27 +msgid "SCO^goals" +msgstr "SCO^gol" + +#: qcsrc/client/scoreboard.qc:28 +msgid "SCO^kckills" +msgstr "uccisioni pc" + +#: qcsrc/client/scoreboard.qc:29 +msgid "SCO^kdratio" +msgstr "rapporto u/m" + +#: qcsrc/client/scoreboard.qc:30 +msgid "SCO^k/d" +msgstr "u/m" + +#: qcsrc/client/scoreboard.qc:31 +msgid "SCO^kd" +msgstr "um" + +#: qcsrc/client/scoreboard.qc:32 +msgid "SCO^kdr" +msgstr "rum" + +#: qcsrc/client/scoreboard.qc:33 +msgid "SCO^kills" +msgstr "SCO^uccisioni" + +#: qcsrc/client/scoreboard.qc:34 +msgid "SCO^laps" +msgstr "SCO^giri" + +#: qcsrc/client/scoreboard.qc:35 +msgid "SCO^lives" +msgstr "SCO^vite" + +#: qcsrc/client/scoreboard.qc:36 +msgid "SCO^losses" +msgstr "SCO^perdute" + +#: qcsrc/client/scoreboard.qc:37 +msgid "SCO^name" +msgstr "SCO^nome" + +#: qcsrc/client/scoreboard.qc:38 +msgid "SCO^nick" +msgstr "SCO^nick" + +#: qcsrc/client/scoreboard.qc:39 +msgid "SCO^objectives" +msgstr "obiettivi" + +#: qcsrc/client/scoreboard.qc:40 +msgid "SCO^pickups" +msgstr "SCO^raccolte" + +#: qcsrc/client/scoreboard.qc:41 +msgid "SCO^ping" +msgstr "SCO^ping" + +#: qcsrc/client/scoreboard.qc:42 +msgid "SCO^pl" +msgstr "SCO^pl" + +#: qcsrc/client/scoreboard.qc:43 +msgid "SCO^pushes" +msgstr "SCO^spinte" + +#: qcsrc/client/scoreboard.qc:44 +msgid "SCO^rank" +msgstr "SCO^posizione" + +#: qcsrc/client/scoreboard.qc:45 +msgid "SCO^returns" +msgstr "SCO^ritorni" + +#: qcsrc/client/scoreboard.qc:46 +msgid "SCO^revivals" +msgstr "ravvivamenti" + +#: qcsrc/client/scoreboard.qc:47 +msgid "SCO^score" +msgstr "SCO^punti" + +#: qcsrc/client/scoreboard.qc:48 +msgid "SCO^suicides" +msgstr "SCO^suicidi" + +#: qcsrc/client/scoreboard.qc:49 +msgid "SCO^takes" +msgstr "SCO^presi" + +#: qcsrc/client/scoreboard.qc:50 +msgid "SCO^ticks" +msgstr "SCO^tick" + +#: qcsrc/client/scoreboard.qc:239 +msgid "" +"You can modify the scoreboard using the ^2scoreboard_columns_set command.\n" +msgstr "" +"Puoi modificare lo scoreboard usando il comando ^2scoreboard_columns_set.\n" + +#: qcsrc/client/scoreboard.qc:240 +msgid "^3|---------------------------------------------------------------|\n" +msgstr "^3|---------------------------------------------------------------|\n" + +#: qcsrc/client/scoreboard.qc:242 +msgid "^2scoreboard_columns_set default\n" +msgstr "^2scoreboard_columns_set default\n" + +#: qcsrc/client/scoreboard.qc:243 +msgid "^2scoreboard_columns_set ^7filed1 field2 ...\n" +msgstr "^2scoreboard_columns_set ^7campo1 campo2 ...\n" + +#: qcsrc/client/scoreboard.qc:244 +msgid "The following field names are recognized (case insensitive):\n" +msgstr "I seguenti nomi dei campi sono riconosciuti (non case-sensitive):\n" + +#: qcsrc/client/scoreboard.qc:245 +msgid "" +"You can use a ^3|^7 to start the right-aligned fields.\n" +"\n" +msgstr "" +"Puoi usare un ^3|^7 per iniziare i campi allineati a destra.\n" +"\n" + +#: qcsrc/client/scoreboard.qc:247 +msgid "^3name^7 or ^3nick^7 Name of a player\n" +msgstr "^3name^7 o ^3nick^7 Nome di un giocatore\n" + +#: qcsrc/client/scoreboard.qc:248 +msgid "^3ping^7 Ping time\n" +msgstr "^3ping^7 Tempo di ping\n" + +#: qcsrc/client/scoreboard.qc:249 +msgid "^3pl^7 Packet loss\n" +msgstr "^3pl^7 Pacchetti persi\n" + +#: qcsrc/client/scoreboard.qc:250 +msgid "^3kills^7 Number of kills\n" +msgstr "^3kills^7 Numero di uccisioni\n" + +#: qcsrc/client/scoreboard.qc:251 +msgid "^3deaths^7 Number of deaths\n" +msgstr "^3deaths^7 Numero di morti\n" + +#: qcsrc/client/scoreboard.qc:252 +msgid "^3suicides^7 Number of suicides\n" +msgstr "^3suicides^7 Numero di suicidi\n" + +#: qcsrc/client/scoreboard.qc:253 +msgid "^3frags^7 kills - suicides\n" +msgstr "^3frags^7 uccisioni - suicidi\n" + +#: qcsrc/client/scoreboard.qc:254 +msgid "^3kd^7 The kill-death ratio\n" +msgstr "^3kd^7 Rapporto uccisioni-morti\n" + +#: qcsrc/client/scoreboard.qc:255 +msgid "" +"^3caps^7 How often a flag (CTF) or a key (KeyHunt) was " +"captured\n" +msgstr "" +"^3caps^7 Per quante volte una bandiera (CTF) o una " +"chiave (KeyHunt) è stata catturata\n" + +#: qcsrc/client/scoreboard.qc:256 +msgid "" +"^3pickups^7 How often a flag (CTF) or a key (KeyHunt) or a " +"ball (Keepaway) was picked up\n" +msgstr "" +"^3pickups^7 Per quante volte una bandiera (CTF) o una " +"chiave (KeyHunt) o una palla (Keepaway) viene raccolta\n" + +#: qcsrc/client/scoreboard.qc:257 +msgid "^3fckills^7 Number of flag carrier kills\n" +msgstr "" +"^3fckills^7 Numero di uccisioni dei portatori di bandiera\n" + +#: qcsrc/client/scoreboard.qc:258 +msgid "^3returns^7 Number of flag returns\n" +msgstr "^3returns^7 Numbero di ritorni della bandiera\n" + +#: qcsrc/client/scoreboard.qc:259 +msgid "^3drops^7 Number of flag drops\n" +msgstr "^3drops^7 Numero di bandiere cadute\n" + +#: qcsrc/client/scoreboard.qc:260 +msgid "^3lives^7 Number of lives (LMS)\n" +msgstr "^3lives^7 Numero di vite (LMS)\n" + +#: qcsrc/client/scoreboard.qc:261 +msgid "^3rank^7 Player rank\n" +msgstr "^3rank^7 Posizione del giocatore\n" + +#: qcsrc/client/scoreboard.qc:262 +msgid "^3pushes^7 Number of players pushed into void\n" +msgstr "^3pushes^7 Numero di giocatori spinti nel vuoto\n" + +#: qcsrc/client/scoreboard.qc:263 +msgid "" +"^3destroyed^7 Number of keys destroyed by pushing them into " +"void\n" +msgstr "" +"^3destroyed^7 Numero di chiavi distrutte spingendole nel " +"vuoto\n" + +#: qcsrc/client/scoreboard.qc:264 +msgid "^3kckills^7 Number of keys carrier kills\n" +msgstr "" +"^3kckills^7 Numero di uccisioni di portatori di chiavi\n" + +#: qcsrc/client/scoreboard.qc:265 +msgid "^3losses^7 Number of times a key was lost\n" +msgstr "" +"^3losses^7 Numero di volte che una chiave s'è persa\n" + +#: qcsrc/client/scoreboard.qc:266 +msgid "^3laps^7 Number of laps finished (race/cts)\n" +msgstr "^3laps^7 Numero di giri completati (corsa/cts)\n" + +#: qcsrc/client/scoreboard.qc:267 +msgid "^3time^7 Total time raced (race/cts)\n" +msgstr "^3time^7 Tempo totale (corsa/cts)\n" + +#: qcsrc/client/scoreboard.qc:268 +msgid "^3fastest^7 Time of fastest lap (race/cts)\n" +msgstr "^3fastest^7 Tempo del giro più veloce (corsa/cts)\n" + +#: qcsrc/client/scoreboard.qc:269 +msgid "^3ticks^7 Number of ticks (DOM)\n" +msgstr "^3ticks^7 Numero di tick (DOM)\n" + +#: qcsrc/client/scoreboard.qc:270 +msgid "^3takes^7 Number of domination points taken (DOM)\n" +msgstr "^3takes^7 Numero di punti di dominio presi (DOM)\n" + +#: qcsrc/client/scoreboard.qc:271 +msgid "^3bckills^7 Number of ball carrier kills\n" +msgstr "" +"^3bckills^7 Numbero di uccisioni di portatori di palla\n" + +#: qcsrc/client/scoreboard.qc:272 +msgid "" +"^3bctime^7 Total amount of time holding the ball in " +"Keepaway\n" +msgstr "" +"^3bctime^7 Tempo totale di possesso della palla in " +"Keepaway\n" + +#: qcsrc/client/scoreboard.qc:273 +msgid "" +"^3score^7 Total score\n" +"\n" +msgstr "" +"^3score^7 Punteggio totale\n" +"\n" + +#: qcsrc/client/scoreboard.qc:275 +msgid "" +"Before a field you can put a + or - sign, then a comma separated list\n" +"of game types, then a slash, to make the field show up only in these\n" +"or in all but these game types. You can also specify 'all' as a\n" +"field to show all fields available for the current game mode.\n" +"\n" +msgstr "" +"Prima di un campo puoi mettere il segno + o -, seguito da una lista di tipi " +"di gioco\n" +"separati da virgole, seguita dal segno /, per mostrare il campo solo in " +"questi\n" +"o in tutti tranne questi tipi di gioco. Puoi anche specificare " +"'all' (tutti)\n" +"come campo per mostrare tutti i campi disponibili per l'attuale mdo di " +"gioco.\n" +"\n" + +#: qcsrc/client/scoreboard.qc:280 +msgid "" +"The special game type names 'teams' and 'noteams' can be used to\n" +"include/exclude ALL teams/noteams game modes.\n" +"\n" +msgstr "" +"I nomi speciali per il tipo di gioco 'teams' e 'noteams' possono essere " +"usati\n" +"per includere/escludere TUTTE le modalità con team/senza team.\n" +"\n" + +#: qcsrc/client/scoreboard.qc:283 +msgid "Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4\n" +msgstr "" +"Esempio: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4\n" + +#: qcsrc/client/scoreboard.qc:284 +msgid "" +"will display name, ping and pl aligned to the left, and the fields\n" +"right of the vertical bar aligned to the right.\n" +msgstr "" +"farà visualizzare nome, ping e pl allineati a sinistra, e i campi\n" +"a destra della barra verticale allineati a destra.\n" + +#: qcsrc/client/scoreboard.qc:286 +msgid "" +"'field3' will only be shown in CTF, and 'field4' will be shown in all\n" +"other gamemodes except DM.\n" +msgstr "" +"'field3' sarà mostrato solo in CTF, e 'field4' sarà mostrato in tutte\n" +"le altre modalità di gioco eccetto DM.\n" + +#: qcsrc/client/scoreboard.qc:432 qcsrc/client/scoreboard.qc:447 +#: qcsrc/client/scoreboard.qc:457 qcsrc/client/scoreboard.qc:466 +#: qcsrc/client/scoreboard.qc:475 +#, c-format +msgid "fixed missing field '%s'\n" +msgstr "riparato campo mancante '%s'\n" + +#: qcsrc/client/scoreboard.qc:515 qcsrc/client/scoreboard.qc:522 +msgid "N/A" +msgstr "N/D" + +#: qcsrc/client/scoreboard.qc:950 +#, c-format +msgid "Accuracy stats (average %d%%)" +msgstr "Statistiche precisione (media %d%%)" + +#: qcsrc/client/scoreboard.qc:1015 +#, c-format +msgid "%d%%" +msgstr "%d%%" + +#: qcsrc/client/scoreboard.qc:1075 +msgid "Rankings" +msgstr "Classifica" + +#: qcsrc/client/scoreboard.qc:1170 +msgid "Scoreboard" +msgstr "Tabella dei punteggi" + +#: qcsrc/client/scoreboard.qc:1215 +#, c-format +msgid "Speed award: %d ^7(%s^7)" +msgstr "Velocità migliore: %d ^7(%s^7)" + +#: qcsrc/client/scoreboard.qc:1219 +#, c-format +msgid "All-time fastest: %d ^7(%s^7)" +msgstr "Tempo più veloce in assoluto: %d ^7(%s^7)" + +#: qcsrc/client/scoreboard.qc:1246 qcsrc/client/teamplay.qc:63 +msgid "Spectators" +msgstr "Spettatori" + +#: qcsrc/client/scoreboard.qc:1252 +#, c-format +msgid "playing on ^2%s^7" +msgstr "giocando in ^2%s^7" + +#: qcsrc/client/scoreboard.qc:1259 qcsrc/client/scoreboard.qc:1264 +#, c-format +msgid " for up to ^1%1.0f minutes^7" +msgstr " fino a ^1%1.0f minuti^7" + +#: qcsrc/client/scoreboard.qc:1268 qcsrc/client/scoreboard.qc:1287 +msgid " or" +msgstr " o" + +#: qcsrc/client/scoreboard.qc:1271 qcsrc/client/scoreboard.qc:1278 +#, c-format +msgid " until ^3%s %s^7" +msgstr " fino a ^3%s %s^7" + +#: qcsrc/client/scoreboard.qc:1272 qcsrc/client/scoreboard.qc:1279 +#: qcsrc/client/scoreboard.qc:1291 qcsrc/client/scoreboard.qc:1298 +msgid "SCO^points" +msgstr "SCO^punti" + +#: qcsrc/client/scoreboard.qc:1273 qcsrc/client/scoreboard.qc:1280 +#: qcsrc/client/scoreboard.qc:1292 qcsrc/client/scoreboard.qc:1299 +msgid "SCO^is beaten" +msgstr "SCO^è battuto" + +#: qcsrc/client/scoreboard.qc:1290 qcsrc/client/scoreboard.qc:1297 +#, c-format +msgid " until a lead of ^3%s %s^7" +msgstr " fino a che si vince di ^3%s %s^7" + +#: qcsrc/client/target_music.qc:93 qcsrc/client/target_music.qc:181 +#, c-format +msgid "Cannot initialize sound %s\n" +msgstr "Impossibile inizializzare il suono %s\n" + +#: qcsrc/client/teamplay.qc:64 +msgid "Red Team" +msgstr "Team Rosso" + +#: qcsrc/client/teamplay.qc:65 +msgid "Blue Team" +msgstr "Team Blu" + +#: qcsrc/client/teamplay.qc:66 +msgid "Yellow Team" +msgstr "Team Giallo" + +#: qcsrc/client/teamplay.qc:67 +msgid "Pink Team" +msgstr "Team Rosa" + +#: qcsrc/client/waypointsprites.qc:254 +msgid "Push" +msgstr "Spingi" + +#: qcsrc/client/waypointsprites.qc:255 +msgid "Destroy" +msgstr "Distruggi" + +#: qcsrc/client/waypointsprites.qc:256 +msgid "Defend" +msgstr "Difendi" + +#: qcsrc/client/waypointsprites.qc:257 +msgid "Blue base" +msgstr "Base Blu" + +#: qcsrc/client/waypointsprites.qc:258 +msgid "DANGER" +msgstr "PERICOLO" + +#: qcsrc/client/waypointsprites.qc:259 +msgid "Flag carrier" +msgstr "Portatore bandiera" + +#: qcsrc/client/waypointsprites.qc:260 +msgid "Dropped flag" +msgstr "Bandiera rilasciata" + +#: qcsrc/client/waypointsprites.qc:261 +msgid "Help me!" +msgstr "Aiuto!" + +#: qcsrc/client/waypointsprites.qc:262 +msgid "Here" +msgstr "Qui" + +#: qcsrc/client/waypointsprites.qc:263 +msgid "Dropped key" +msgstr "Chiave rilasciata" + +#: qcsrc/client/waypointsprites.qc:264 qcsrc/client/waypointsprites.qc:266 +#: qcsrc/client/waypointsprites.qc:267 qcsrc/client/waypointsprites.qc:268 +#: qcsrc/client/waypointsprites.qc:269 +msgid "Key carrier" +msgstr "Portatore chiave" + +#: qcsrc/client/waypointsprites.qc:265 +msgid "Run here" +msgstr "Corri qui" + +#: qcsrc/client/waypointsprites.qc:270 +msgid "Red base" +msgstr "Base Rossa" + +#: qcsrc/client/waypointsprites.qc:271 +msgid "Waypoint" +msgstr "Waypoint" + +#: qcsrc/client/waypointsprites.qc:272 qcsrc/client/waypointsprites.qc:273 +#: qcsrc/client/waypointsprites.qc:274 +msgid "Generator" +msgstr "Generatore" + +#: qcsrc/client/waypointsprites.qc:275 qcsrc/client/waypointsprites.qc:276 +#: qcsrc/client/waypointsprites.qc:277 qcsrc/client/waypointsprites.qc:278 +#: qcsrc/client/waypointsprites.qc:279 qcsrc/client/waypointsprites.qc:280 +#: qcsrc/client/waypointsprites.qc:281 qcsrc/client/waypointsprites.qc:282 +#: qcsrc/client/waypointsprites.qc:306 qcsrc/client/waypointsprites.qc:307 +#: qcsrc/client/waypointsprites.qc:308 qcsrc/client/waypointsprites.qc:309 +#: qcsrc/client/waypointsprites.qc:310 +msgid "Control point" +msgstr "Punto di controllo" + +#: qcsrc/client/waypointsprites.qc:283 +msgid "Checkpoint" +msgstr "Checkpoint" + +#: qcsrc/client/waypointsprites.qc:284 qcsrc/client/waypointsprites.qc:286 +msgid "Finish" +msgstr "Arrivo" + +#: qcsrc/client/waypointsprites.qc:285 qcsrc/client/waypointsprites.qc:286 +msgid "Start" +msgstr "Partenza" + +#: qcsrc/client/waypointsprites.qc:287 qcsrc/client/waypointsprites.qc:288 +msgid "Ball" +msgstr "Palla" + +#: qcsrc/client/waypointsprites.qc:289 +msgid "Ball carrier" +msgstr "Portatore palla" + +#: qcsrc/client/waypointsprites.qc:290 qcsrc/server/w_laser.qc:2 +msgid "Laser" +msgstr "Laser" + +#: qcsrc/client/waypointsprites.qc:291 qcsrc/server/w_shotgun.qc:2 +msgid "Shotgun" +msgstr "Shotgun" + +#: qcsrc/client/waypointsprites.qc:292 qcsrc/server/w_uzi.qc:2 +msgid "Machine Gun" +msgstr "Machine Gun" + +#: qcsrc/client/waypointsprites.qc:293 qcsrc/server/w_grenadelauncher.qc:2 +msgid "Mortar" +msgstr "Mortar" + +#: qcsrc/client/waypointsprites.qc:294 qcsrc/server/w_electro.qc:2 +msgid "Electro" +msgstr "Electro" + +#: qcsrc/client/waypointsprites.qc:295 qcsrc/server/w_crylink.qc:2 +msgid "Crylink" +msgstr "Crylink" + +#: qcsrc/client/waypointsprites.qc:296 qcsrc/server/w_nex.qc:2 +msgid "Nex" +msgstr "Nex" + +#: qcsrc/client/waypointsprites.qc:297 qcsrc/server/w_hagar.qc:2 +msgid "Hagar" +msgstr "Hagar" + +#: qcsrc/client/waypointsprites.qc:298 qcsrc/server/w_rocketlauncher.qc:2 +msgid "Rocket Launcher" +msgstr "Rocket Launcher" + +#: qcsrc/client/waypointsprites.qc:299 qcsrc/server/w_porto.qc:2 +msgid "Port-O-Launch" +msgstr "Port-O-Launch" + +#: qcsrc/client/waypointsprites.qc:300 +msgid "Minstanex" +msgstr "Minstanex" + +#: qcsrc/client/waypointsprites.qc:301 +msgid "Hook" +msgstr "Hook" + +#: qcsrc/client/waypointsprites.qc:302 qcsrc/server/w_fireball.qc:2 +msgid "Fireball" +msgstr "Fireball" + +#: qcsrc/client/waypointsprites.qc:303 +msgid "HLAC" +msgstr "HLAC" + +#: qcsrc/client/waypointsprites.qc:304 qcsrc/server/w_rifle.qc:2 +msgid "Rifle" +msgstr "Fucile" + +#: qcsrc/client/waypointsprites.qc:305 qcsrc/server/w_minelayer.qc:2 +msgid "Mine Layer" +msgstr "Mine Layer" + +#: qcsrc/client/waypointsprites.qc:311 +msgid "Invisibility" +msgstr "Invisibilità" + +#: qcsrc/client/waypointsprites.qc:312 +msgid "Extra life" +msgstr "Vita extra" + +#: qcsrc/client/waypointsprites.qc:313 +msgid "Speed" +msgstr "Velocità" + +#: qcsrc/client/waypointsprites.qc:314 +msgid "Strength" +msgstr "Forza" + +#: qcsrc/client/waypointsprites.qc:315 +msgid "Shield" +msgstr "Scudo" + +#: qcsrc/client/waypointsprites.qc:316 +msgid "Fuel regen" +msgstr "Rigeneratore di carburante" + +#: qcsrc/client/waypointsprites.qc:317 +msgid "Jet Pack" +msgstr "Jet Pack" + +#: qcsrc/client/waypointsprites.qc:318 +msgid "Frozen!" +msgstr "Congelato!" + +#: qcsrc/client/waypointsprites.qc:319 +msgid "Tagged" +msgstr "Contrassegnato" + +#: qcsrc/client/waypointsprites.qc:320 +msgid "Vehicle" +msgstr "Veicolo" + +#: qcsrc/client/waypointsprites.qc:590 +msgid "Spam" +msgstr "Spam" + +#: qcsrc/client/waypointsprites.qc:594 +#, c-format +msgid "%s needing help!" +msgstr "%s sta chiedendo aiuto!" + +#: qcsrc/common/mapinfo.qc:1092 +#, c-format +msgid "%s: %s" +msgstr "%s: %s" + +#: qcsrc/server/w_crylink.qc:666 +#, c-format +msgid "%s succeeded at self-destructing themself with the Crylink" +msgstr "%s è riuscito ad autodistruggersi col Crylink" + +#: qcsrc/server/w_crylink.qc:671 +#, c-format +msgid "%s could not hide from %s's Crylink" +msgstr "%s non s'è potuto nascondere dal Crylink di %s" + +#: qcsrc/server/w_crylink.qc:673 +#, c-format +msgid "%s was too close to %s's Crylink" +msgstr "%s era troppo vicino al Crylink di %s" + +#: qcsrc/server/w_crylink.qc:675 +#, c-format +msgid "%s took a close look at %s's Crylink" +msgstr "%s ha visto da vicino il Crylink di %s" + +#: qcsrc/server/w_electro.qc:574 +#, c-format +msgid "%s could not remember where they put plasma" +msgstr "%s non s'è ricordato dove aveva messo il plasma" + +#: qcsrc/server/w_electro.qc:576 +#, c-format +msgid "%s played with plasma" +msgstr "%s ha giocato col plasma" + +#: qcsrc/server/w_electro.qc:583 +#, c-format +msgid "%s just noticed %s's blue ball" +msgstr "%s ha appena notato la palla blu di %s" + +#: qcsrc/server/w_electro.qc:585 +#, c-format +msgid "%s got in touch with %s's blue ball" +msgstr "%s è entrato in contatto con la palla blu di %s" + +#: qcsrc/server/w_electro.qc:590 +#, c-format +msgid "%s felt the electrifying air of %s's combo" +msgstr "%s ha sentito l'aria elettrificata della combo di %s" + +#: qcsrc/server/w_electro.qc:592 +#, c-format +msgid "%s got too close to %s's blue beam" +msgstr "%s s'è avvicinato troppo al raggio blu di %s" + +#: qcsrc/server/w_electro.qc:594 +#, c-format +msgid "%s was blasted by %s's blue beam" +msgstr "%s è stato fatto saltare in aria dal raggio blu di %s" + +#: qcsrc/server/w_fireball.qc:417 +#, c-format +msgid "%s forgot about some firemine" +msgstr "%s s'è dimenticato di alcune mine infuocate" + +#: qcsrc/server/w_fireball.qc:419 qcsrc/server/w_hlac.qc:240 +#, c-format +msgid "%s should have used a smaller gun" +msgstr "%s avrebbe dovuto usare un'arma più piccola" + +#: qcsrc/server/w_fireball.qc:426 +#, c-format +msgid "%s tried to catch %s's firemine" +msgstr "%s ha provato a catturare la mina infuocata di %s" + +#: qcsrc/server/w_fireball.qc:428 +#, c-format +msgid "%s fatefully ignored %s's firemine" +msgstr "%s ha fatalmente ignorato la mina infuocata di %s" + +#: qcsrc/server/w_fireball.qc:435 +#, c-format +msgid "%s could not hide from %s's fireball" +msgstr "%s non è riuscito a nascondersi dalla fireball di %s" + +#: qcsrc/server/w_fireball.qc:437 +#, c-format +msgid "%s saw the pretty lights of %s's fireball" +msgstr "%s ha visto le belle luci della fireball di %s" + +#: qcsrc/server/w_fireball.qc:440 +#, c-format +msgid "%s got too close to %s's fireball" +msgstr "%s s'è avvicinato troppo alla fireball di %s" + +#: qcsrc/server/w_fireball.qc:442 +#, c-format +msgid "%s tasted %s's fireball" +msgstr "%s ha assaggiato la fireball di %s" + +#: qcsrc/server/w_grenadelauncher.qc:383 +#, c-format +msgid "%s tried out his own grenade" +msgstr "%s ha provato da solo la propria granata" + +#: qcsrc/server/w_grenadelauncher.qc:385 +#, c-format +msgid "%s detonated" +msgstr "%s è detonato" + +#: qcsrc/server/w_grenadelauncher.qc:391 +#, c-format +msgid "%s didn't see %s's grenade" +msgstr "%s non ha visto la granata di %s" + +#: qcsrc/server/w_grenadelauncher.qc:393 +#, c-format +msgid "%s almost dodged %s's grenade" +msgstr "%s ha quasi schivato la granata di %s" + +#: qcsrc/server/w_grenadelauncher.qc:395 +#, c-format +msgid "%s ate %s's grenade" +msgstr "%s ha mangiato la granata di %s" + +#: qcsrc/server/w_hagar.qc:395 qcsrc/server/w_seeker.qc:655 +#, c-format +msgid "%s played with tiny rockets" +msgstr "%s ha giocato con piccoli razzi" + +#: qcsrc/server/w_hagar.qc:399 +#, c-format +msgid "%s hoped %s's missiles wouldn't bounce" +msgstr "%s ha sperato che il missile di %s non rimbalzasse" + +#: qcsrc/server/w_hagar.qc:401 qcsrc/server/w_seeker.qc:661 +#, c-format +msgid "%s was pummeled by %s" +msgstr "%s è stato preso a pugni da %s" + +#: qcsrc/server/w_hlac.qc:2 +msgid "Heavy Laser Assault Cannon" +msgstr "Heavy Laser Assault Cannon" + +#: qcsrc/server/w_hlac.qc:242 +#, c-format +msgid "%s was cut down by %s" +msgstr "%s è stato abbattuto da %s" + +#: qcsrc/server/w_hook.qc:2 +msgid "Grappling Hook" +msgstr "Grappling Hook" + +#: qcsrc/server/w_hook.qc:266 qcsrc/server/w_porto.qc:296 +#, c-format +msgid "%s did the impossible" +msgstr "%s ha fatto l'impossibile" + +#: qcsrc/server/w_hook.qc:268 +#, c-format +msgid "%s has run into %s's gravity bomb" +msgstr "%s è corso nella bomba di gravità di %s" + +#: qcsrc/server/w_laser.qc:311 +#, c-format +msgid "%s lasered themself to hell" +msgstr "%s si è \"laserato\" all'inferno" + +#: qcsrc/server/w_laser.qc:315 +#, c-format +msgid "%s was cut in half by %s's gauntlet" +msgstr "%s è stato tagliato a metà dal guanto di %s" + +#: qcsrc/server/w_laser.qc:317 +#, c-format +msgid "%s was lasered to death by %s" +msgstr "%s è stato \"laserato\" alla morte da %s" + +#: qcsrc/server/w_minelayer.qc:523 qcsrc/server/w_rocketlauncher.qc:501 +#, c-format +msgid "%s exploded" +msgstr "%s è esploso" + +#: qcsrc/server/w_minelayer.qc:527 +#, c-format +msgid "%s got too close to %s's mine" +msgstr "%s s'è avvicinato troppo alla mina di %s" + +#: qcsrc/server/w_minelayer.qc:529 +#, c-format +msgid "%s almost dodged %s's mine" +msgstr "%s ha quasi schivato la mina di %s" + +#: qcsrc/server/w_minelayer.qc:531 +#, c-format +msgid "%s stepped on %s's mine" +msgstr "%s è passato sopra la mina di %s" + +#: qcsrc/server/w_minstanex.qc:2 +msgid "MinstaNex" +msgstr "MinstaNex" + +#: qcsrc/server/w_minstanex.qc:293 qcsrc/server/w_nex.qc:253 +#: qcsrc/server/w_shotgun.qc:215 qcsrc/server/w_uzi.qc:317 +#, c-format +msgid "%s is now thinking with portals" +msgstr "%s sta ora pensando con i portali" + +#: qcsrc/server/w_minstanex.qc:295 qcsrc/server/w_nex.qc:255 +#, c-format +msgid "%s has been vaporized by %s" +msgstr "%s è stato vaporizzato da %s" + +#: qcsrc/server/w_porto.qc:298 +#, c-format +msgid "%s felt %s doing the impossible to him" +msgstr "%s ha sentito %s fargli l'impossibile" + +#: qcsrc/server/w_rifle.qc:233 +#, c-format +msgid "%s shot themself automatically" +msgstr "%s si è sparato da solo automaticamente" + +#: qcsrc/server/w_rifle.qc:235 +#, c-format +msgid "%s sniped themself somehow" +msgstr "%s si è fucilato da solo in qualche modo" + +#: qcsrc/server/w_rifle.qc:242 +#, c-format +msgid "%s failed to hide from %s's bullet hail" +msgstr "%s non è riuscito a nascondersi dalla raffica di proiettili di %s" + +#: qcsrc/server/w_rifle.qc:244 +#, c-format +msgid "%s died in %s's bullet hail" +msgstr "%s è morto nella raffica di proiettili di %s" + +#: qcsrc/server/w_rifle.qc:251 +#, c-format +msgid "%s failed to hide from %s's rifle" +msgstr "%s non è riuscito a nascondersi dal fucile di %s" + +#: qcsrc/server/w_rifle.qc:256 +#, c-format +msgid "%s got hit in the head by %s" +msgstr "%s ha preso un colpo in testa da %s" + +#: qcsrc/server/w_rifle.qc:258 qcsrc/server/w_uzi.qc:321 +#, c-format +msgid "%s was sniped by %s" +msgstr "%s è stato fucilato da %s" + +#: qcsrc/server/w_rocketlauncher.qc:505 +#, c-format +msgid "%s got too close to %s's rocket" +msgstr "%s s'è avvicinato troppo al razzo di %s" + +#: qcsrc/server/w_rocketlauncher.qc:507 +#, c-format +msgid "%s almost dodged %s's rocket" +msgstr "%s ha quasi schivato il razzo di %s" + +#: qcsrc/server/w_rocketlauncher.qc:509 +#, c-format +msgid "%s ate %s's rocket" +msgstr "%s ha mangiato il razzo di %s" + +#: qcsrc/server/w_seeker.qc:2 +msgid "T.A.G. Seeker" +msgstr "T.A.G. Seeker" + +#: qcsrc/server/w_seeker.qc:659 +#, c-format +msgid "%s was tagged by %s" +msgstr "%s è stato contrassegnato da %s" + +#: qcsrc/server/w_shotgun.qc:219 +#, c-format +msgid "%2$s ^7slapped %1$s ^7around a bit with a large ^2shotgun" +msgstr "%2$s ^7ha schiaffeggiato %1$s ^7un pò con un grosso ^2shotgun" + +#: qcsrc/server/w_shotgun.qc:221 +#, c-format +msgid "%s was gunned by %s" +msgstr "%s è stato sparato da %s" + +#: qcsrc/server/w_tuba.qc:2 +#, c-format +msgid "@!#%'n Tuba" +msgstr "@!#%'n Tuba" + +#: qcsrc/server/w_tuba.qc:252 +#, c-format +msgid "%s hurt his own ears with the @!#%%'n Tuba" +msgstr "%s s'è fatto male alle orecchie con la @!#%%'n Tuba" + +#: qcsrc/server/w_tuba.qc:256 +#, c-format +msgid "%s died of %s's great playing on the @!#%%'n Tuba" +msgstr "%s è morto nella gran esibizione di %s con la @!#%%'n Tuba" + +#: qcsrc/server/w_uzi.qc:323 +#, c-format +msgid "%s was riddled full of holes by %s" +msgstr "%s è stato riempito di buchi da %s" diff --git a/csprogs.dat.pot b/csprogs.dat.pot new file mode 100644 index 0000000000..9b009bda13 --- /dev/null +++ b/csprogs.dat.pot @@ -0,0 +1,2004 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-12-25 22:57+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: qcsrc/client/target_music.qc:93 qcsrc/client/target_music.qc:181 +#, c-format +msgid "Cannot initialize sound %s\n" +msgstr "" + +#: qcsrc/client/hud_config.qc:185 +#, c-format +msgid "^2Successfully exported to %s! (Note: It's saved in data/data/)\n" +msgstr "" + +#: qcsrc/client/hud_config.qc:189 +#, c-format +msgid "^1Couldn't write to %s\n" +msgstr "" + +#: qcsrc/client/miscfunctions.qc:100 +msgid "Trying to remove a team which is not in the teamlist!" +msgstr "" + +#: qcsrc/client/csqcmodel_hooks.qc:17 +#, c-format +msgid "Trying to use non existing model %s. " +msgstr "" + +#: qcsrc/client/csqcmodel_hooks.qc:19 +#, c-format +msgid "Reverted to %s.\n" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:254 +msgid "Push" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:255 +msgid "Destroy" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:256 +msgid "Defend" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:257 +msgid "Blue base" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:258 +msgid "DANGER" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:259 +msgid "Flag carrier" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:260 +msgid "Dropped flag" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:261 +msgid "Help me!" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:262 +msgid "Here" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:263 +msgid "Dropped key" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:264 qcsrc/client/waypointsprites.qc:266 +#: qcsrc/client/waypointsprites.qc:267 qcsrc/client/waypointsprites.qc:268 +#: qcsrc/client/waypointsprites.qc:269 +msgid "Key carrier" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:265 +msgid "Run here" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:270 +msgid "Red base" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:271 +msgid "Waypoint" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:272 qcsrc/client/waypointsprites.qc:273 +#: qcsrc/client/waypointsprites.qc:274 +msgid "Generator" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:275 qcsrc/client/waypointsprites.qc:276 +#: qcsrc/client/waypointsprites.qc:277 qcsrc/client/waypointsprites.qc:278 +#: qcsrc/client/waypointsprites.qc:279 qcsrc/client/waypointsprites.qc:280 +#: qcsrc/client/waypointsprites.qc:281 qcsrc/client/waypointsprites.qc:282 +#: qcsrc/client/waypointsprites.qc:306 qcsrc/client/waypointsprites.qc:307 +#: qcsrc/client/waypointsprites.qc:308 qcsrc/client/waypointsprites.qc:309 +#: qcsrc/client/waypointsprites.qc:310 +msgid "Control point" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:283 +msgid "Checkpoint" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:284 qcsrc/client/waypointsprites.qc:286 +msgid "Finish" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:285 qcsrc/client/waypointsprites.qc:286 +msgid "Start" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:287 qcsrc/client/waypointsprites.qc:288 +msgid "Ball" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:289 +msgid "Ball carrier" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:290 qcsrc/server/w_laser.qc:2 +msgid "Laser" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:291 qcsrc/server/w_shotgun.qc:2 +msgid "Shotgun" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:292 qcsrc/server/w_uzi.qc:2 +msgid "Machine Gun" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:293 qcsrc/server/w_grenadelauncher.qc:2 +msgid "Mortar" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:294 qcsrc/server/w_electro.qc:2 +msgid "Electro" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:295 qcsrc/server/w_crylink.qc:2 +msgid "Crylink" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:296 qcsrc/server/w_nex.qc:2 +msgid "Nex" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:297 qcsrc/server/w_hagar.qc:2 +msgid "Hagar" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:298 qcsrc/server/w_rocketlauncher.qc:2 +msgid "Rocket Launcher" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:299 qcsrc/server/w_porto.qc:2 +msgid "Port-O-Launch" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:300 +msgid "Minstanex" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:301 +msgid "Hook" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:302 qcsrc/server/w_fireball.qc:2 +msgid "Fireball" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:303 +msgid "HLAC" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:304 qcsrc/server/w_rifle.qc:2 +msgid "Rifle" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:305 qcsrc/server/w_minelayer.qc:2 +msgid "Mine Layer" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:311 +msgid "Invisibility" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:312 +msgid "Extra life" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:313 +msgid "Speed" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:314 +msgid "Strength" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:315 +msgid "Shield" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:316 +msgid "Fuel regen" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:317 +msgid "Jet Pack" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:318 +msgid "Frozen!" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:319 +msgid "Tagged" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:320 +msgid "Vehicle" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:590 qcsrc/client/tturrets.qc:285 +msgid "Spam" +msgstr "" + +#: qcsrc/client/waypointsprites.qc:594 +#, c-format +msgid "%s needing help!" +msgstr "" + +#: qcsrc/client/Main.qc:30 +msgid "ERROR - MENU IS VISIBLE BUT NO MENU WAS DEFINED!" +msgstr "" + +#: qcsrc/client/Main.qc:104 +msgid "" +"^3Your engine build is outdated\n" +"^3This Server uses a newer QC VM. Please update!\n" +msgstr "" + +#: qcsrc/client/Main.qc:114 +#, c-format +msgid "^4CSQC Build information: ^1%s\n" +msgstr "" + +#: qcsrc/client/Main.qc:293 qcsrc/client/Main.qc:309 +#, c-format +msgid "trying to switch to unsupported team %d\n" +msgstr "" + +#: qcsrc/client/Main.qc:424 qcsrc/client/scoreboard.qc:241 +msgid "Usage:\n" +msgstr "" + +#: qcsrc/client/Main.qc:425 +msgid "hud_save configname (saves to hud_skinname_configname.cfg)\n" +msgstr "" + +#: qcsrc/client/Main.qc:549 +msgid "Usage: cl_cmd COMMAND..., where possible commands are:\n" +msgstr "" + +#: qcsrc/client/Main.qc:550 +msgid " settemp cvar value\n" +msgstr "" + +#: qcsrc/client/Main.qc:551 +msgid " scoreboard_columns_set ...\n" +msgstr "" + +#: qcsrc/client/Main.qc:552 +msgid " scoreboard_columns_help\n" +msgstr "" + +#: qcsrc/client/Main.qc:788 +#, c-format +msgid "A CSQC entity changed its owner! (edict: %d, classname: %s)\n" +msgstr "" + +#: qcsrc/client/Main.qc:1029 +#, c-format +msgid "" +"A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n" +msgstr "" + +#: qcsrc/client/Main.qc:1038 +#, c-format +msgid "" +"A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n" +msgstr "" + +#: qcsrc/client/Main.qc:1080 +#, c-format +msgid "" +"Unknown entity type in CSQC_Ent_Update (enttype: %d, edict: %d, classname: " +"%s)\n" +msgstr "" + +#: qcsrc/client/Main.qc:1526 +#, c-format +msgid "%s (not bound)" +msgstr "" + +#: qcsrc/client/Main.qc:1531 qcsrc/client/hud.qc:230 +#, c-format +msgid "%s (%s)" +msgstr "" + +#: qcsrc/client/movetypes.qc:163 +#, c-format +msgid "Can't unstick an entity (edict: %d, classname: %s, origin: %s)\n" +msgstr "" + +#: qcsrc/client/movetypes.qc:166 +#, c-format +msgid "Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:19 +msgid "SCO^bckills" +msgstr "" + +#: qcsrc/client/scoreboard.qc:20 +msgid "SCO^bctime" +msgstr "" + +#: qcsrc/client/scoreboard.qc:21 +msgid "SCO^caps" +msgstr "" + +#: qcsrc/client/scoreboard.qc:22 +msgid "SCO^deaths" +msgstr "" + +#: qcsrc/client/scoreboard.qc:23 +msgid "SCO^destroyed" +msgstr "" + +#: qcsrc/client/scoreboard.qc:24 +msgid "SCO^drops" +msgstr "" + +#: qcsrc/client/scoreboard.qc:25 +msgid "SCO^faults" +msgstr "" + +#: qcsrc/client/scoreboard.qc:26 +msgid "SCO^fckills" +msgstr "" + +#: qcsrc/client/scoreboard.qc:27 +msgid "SCO^goals" +msgstr "" + +#: qcsrc/client/scoreboard.qc:28 +msgid "SCO^kckills" +msgstr "" + +#: qcsrc/client/scoreboard.qc:29 +msgid "SCO^kdratio" +msgstr "" + +#: qcsrc/client/scoreboard.qc:30 +msgid "SCO^k/d" +msgstr "" + +#: qcsrc/client/scoreboard.qc:31 +msgid "SCO^kd" +msgstr "" + +#: qcsrc/client/scoreboard.qc:32 +msgid "SCO^kdr" +msgstr "" + +#: qcsrc/client/scoreboard.qc:33 +msgid "SCO^kills" +msgstr "" + +#: qcsrc/client/scoreboard.qc:34 +msgid "SCO^laps" +msgstr "" + +#: qcsrc/client/scoreboard.qc:35 +msgid "SCO^lives" +msgstr "" + +#: qcsrc/client/scoreboard.qc:36 +msgid "SCO^losses" +msgstr "" + +#: qcsrc/client/scoreboard.qc:37 +msgid "SCO^name" +msgstr "" + +#: qcsrc/client/scoreboard.qc:38 +msgid "SCO^nick" +msgstr "" + +#: qcsrc/client/scoreboard.qc:39 +msgid "SCO^objectives" +msgstr "" + +#: qcsrc/client/scoreboard.qc:40 +msgid "SCO^pickups" +msgstr "" + +#: qcsrc/client/scoreboard.qc:41 +msgid "SCO^ping" +msgstr "" + +#: qcsrc/client/scoreboard.qc:42 +msgid "SCO^pl" +msgstr "" + +#: qcsrc/client/scoreboard.qc:43 +msgid "SCO^pushes" +msgstr "" + +#: qcsrc/client/scoreboard.qc:44 +msgid "SCO^rank" +msgstr "" + +#: qcsrc/client/scoreboard.qc:45 +msgid "SCO^returns" +msgstr "" + +#: qcsrc/client/scoreboard.qc:46 +msgid "SCO^revivals" +msgstr "" + +#: qcsrc/client/scoreboard.qc:47 +msgid "SCO^score" +msgstr "" + +#: qcsrc/client/scoreboard.qc:48 +msgid "SCO^suicides" +msgstr "" + +#: qcsrc/client/scoreboard.qc:49 +msgid "SCO^takes" +msgstr "" + +#: qcsrc/client/scoreboard.qc:50 +msgid "SCO^ticks" +msgstr "" + +#: qcsrc/client/scoreboard.qc:239 +msgid "" +"You can modify the scoreboard using the ^2scoreboard_columns_set command.\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:240 +msgid "^3|---------------------------------------------------------------|\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:242 +msgid "^2scoreboard_columns_set default\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:243 +msgid "^2scoreboard_columns_set ^7field1 field2 ...\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:244 +msgid "The following field names are recognized (case insensitive):\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:245 +msgid "" +"You can use a ^3|^7 to start the right-aligned fields.\n" +"\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:247 +msgid "^3name^7 or ^3nick^7 Name of a player\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:248 +msgid "^3ping^7 Ping time\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:249 +msgid "^3pl^7 Packet loss\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:250 +msgid "^3kills^7 Number of kills\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:251 +msgid "^3deaths^7 Number of deaths\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:252 +msgid "^3suicides^7 Number of suicides\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:253 +msgid "^3frags^7 kills - suicides\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:254 +msgid "^3kd^7 The kill-death ratio\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:255 +msgid "" +"^3caps^7 How often a flag (CTF) or a key (KeyHunt) was " +"captured\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:256 +msgid "" +"^3pickups^7 How often a flag (CTF) or a key (KeyHunt) or a " +"ball (Keepaway) was picked up\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:257 +msgid "^3fckills^7 Number of flag carrier kills\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:258 +msgid "^3returns^7 Number of flag returns\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:259 +msgid "^3drops^7 Number of flag drops\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:260 +msgid "^3lives^7 Number of lives (LMS)\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:261 +msgid "^3rank^7 Player rank\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:262 +msgid "^3pushes^7 Number of players pushed into void\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:263 +msgid "" +"^3destroyed^7 Number of keys destroyed by pushing them into " +"void\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:264 +msgid "^3kckills^7 Number of keys carrier kills\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:265 +msgid "^3losses^7 Number of times a key was lost\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:266 +msgid "^3laps^7 Number of laps finished (race/cts)\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:267 +msgid "^3time^7 Total time raced (race/cts)\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:268 +msgid "^3fastest^7 Time of fastest lap (race/cts)\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:269 +msgid "^3ticks^7 Number of ticks (DOM)\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:270 +msgid "^3takes^7 Number of domination points taken (DOM)\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:271 +msgid "^3bckills^7 Number of ball carrier kills\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:272 +msgid "" +"^3bctime^7 Total amount of time holding the ball in " +"Keepaway\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:273 +msgid "" +"^3score^7 Total score\n" +"\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:275 +msgid "" +"Before a field you can put a + or - sign, then a comma separated list\n" +"of game types, then a slash, to make the field show up only in these\n" +"or in all but these game types. You can also specify 'all' as a\n" +"field to show all fields available for the current game mode.\n" +"\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:280 +msgid "" +"The special game type names 'teams' and 'noteams' can be used to\n" +"include/exclude ALL teams/noteams game modes.\n" +"\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:283 +msgid "Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:284 +msgid "" +"will display name, ping and pl aligned to the left, and the fields\n" +"right of the vertical bar aligned to the right.\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:286 +msgid "" +"'field3' will only be shown in CTF, and 'field4' will be shown in all\n" +"other gamemodes except DM.\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:432 qcsrc/client/scoreboard.qc:447 +#: qcsrc/client/scoreboard.qc:457 qcsrc/client/scoreboard.qc:466 +#: qcsrc/client/scoreboard.qc:475 +#, c-format +msgid "fixed missing field '%s'\n" +msgstr "" + +#: qcsrc/client/scoreboard.qc:515 qcsrc/client/scoreboard.qc:522 +msgid "N/A" +msgstr "" + +#: qcsrc/client/scoreboard.qc:950 +#, c-format +msgid "Accuracy stats (average %d%%)" +msgstr "" + +#: qcsrc/client/scoreboard.qc:1015 +#, c-format +msgid "%d%%" +msgstr "" + +#: qcsrc/client/scoreboard.qc:1085 +msgid "Map stats:" +msgstr "" + +#: qcsrc/client/scoreboard.qc:1101 +msgid "Secrets found:" +msgstr "" + +#: qcsrc/client/scoreboard.qc:1128 +msgid "Rankings" +msgstr "" + +#: qcsrc/client/scoreboard.qc:1223 +msgid "Scoreboard" +msgstr "" + +#: qcsrc/client/scoreboard.qc:1268 +#, c-format +msgid "Speed award: %d ^7(%s^7)" +msgstr "" + +#: qcsrc/client/scoreboard.qc:1272 +#, c-format +msgid "All-time fastest: %d ^7(%s^7)" +msgstr "" + +#: qcsrc/client/scoreboard.qc:1305 qcsrc/client/teamplay.qc:63 +msgid "Spectators" +msgstr "" + +#: qcsrc/client/scoreboard.qc:1311 +#, c-format +msgid "playing on ^2%s^7" +msgstr "" + +#: qcsrc/client/scoreboard.qc:1318 qcsrc/client/scoreboard.qc:1323 +#, c-format +msgid " for up to ^1%1.0f minutes^7" +msgstr "" + +#: qcsrc/client/scoreboard.qc:1327 qcsrc/client/scoreboard.qc:1346 +msgid " or" +msgstr "" + +#: qcsrc/client/scoreboard.qc:1330 qcsrc/client/scoreboard.qc:1337 +#, c-format +msgid " until ^3%s %s^7" +msgstr "" + +#: qcsrc/client/scoreboard.qc:1331 qcsrc/client/scoreboard.qc:1338 +#: qcsrc/client/scoreboard.qc:1350 qcsrc/client/scoreboard.qc:1357 +msgid "SCO^points" +msgstr "" + +#: qcsrc/client/scoreboard.qc:1332 qcsrc/client/scoreboard.qc:1339 +#: qcsrc/client/scoreboard.qc:1351 qcsrc/client/scoreboard.qc:1358 +msgid "SCO^is beaten" +msgstr "" + +#: qcsrc/client/scoreboard.qc:1349 qcsrc/client/scoreboard.qc:1356 +#, c-format +msgid " until a lead of ^3%s %s^7" +msgstr "" + +#: qcsrc/client/teamplay.qc:64 +msgid "Red Team" +msgstr "" + +#: qcsrc/client/teamplay.qc:65 +msgid "Blue Team" +msgstr "" + +#: qcsrc/client/teamplay.qc:66 +msgid "Yellow Team" +msgstr "" + +#: qcsrc/client/teamplay.qc:67 +msgid "Pink Team" +msgstr "" + +#: qcsrc/client/tturrets.qc:294 +#, c-format +msgid "%s under attack!" +msgstr "" + +#: qcsrc/client/mapvoting.qc:28 +msgid " (1 vote)" +msgstr "" + +#: qcsrc/client/mapvoting.qc:30 +#, c-format +msgid " (%d votes)" +msgstr "" + +#: qcsrc/client/mapvoting.qc:113 +msgid "Don't care" +msgstr "" + +#: qcsrc/client/mapvoting.qc:194 +msgid "Vote for a map" +msgstr "" + +#: qcsrc/client/mapvoting.qc:200 +#, c-format +msgid "%d seconds left" +msgstr "" + +#: qcsrc/client/mapvoting.qc:263 +msgid "" +"mv_mapdownload: ^3You're not supposed to use this command on your own!\n" +msgstr "" + +#: qcsrc/client/mapvoting.qc:273 +msgid "^1Error:^7 Couldn't find pak index.\n" +msgstr "" + +#: qcsrc/client/mapvoting.qc:282 +msgid "Requesting preview...\n" +msgstr "" + +#: qcsrc/client/announcer.qc:31 +msgid "^1Begin!" +msgstr "" + +#: qcsrc/client/announcer.qc:41 +#, c-format +msgid "^1Game starts in %d seconds" +msgstr "" + +#: qcsrc/client/announcer.qc:153 +msgid "^1RED^7 flag" +msgstr "" + +#: qcsrc/client/announcer.qc:158 +msgid "^4BLUE^7 flag" +msgstr "" + +#: qcsrc/client/announcer.qc:166 +#, c-format +msgid "You picked up the %s!" +msgstr "" + +#: qcsrc/client/announcer.qc:170 +#, c-format +msgid "You got the %s!" +msgstr "" + +#: qcsrc/client/hud.qc:160 +msgid "1st" +msgstr "" + +#: qcsrc/client/hud.qc:162 +msgid "2nd" +msgstr "" + +#: qcsrc/client/hud.qc:164 +msgid "3rd" +msgstr "" + +#: qcsrc/client/hud.qc:166 +#, c-format +msgid "%dth" +msgstr "" + +#: qcsrc/client/hud.qc:198 +#, c-format +msgid " (-%dL)" +msgstr "" + +#: qcsrc/client/hud.qc:203 +#, c-format +msgid " (+%dL)" +msgstr "" + +#: qcsrc/client/hud.qc:219 +msgid "Start line" +msgstr "" + +#: qcsrc/client/hud.qc:221 qcsrc/client/hud.qc:225 +msgid "Finish line" +msgstr "" + +#: qcsrc/client/hud.qc:223 +#, c-format +msgid "Intermediate %d" +msgstr "" + +#: qcsrc/client/hud.qc:232 +#, c-format +msgid "%s (%s %s)" +msgstr "" + +#: qcsrc/client/hud.qc:786 +msgid "Out of ammo" +msgstr "" + +#: qcsrc/client/hud.qc:790 +msgid "Don't have" +msgstr "" + +#: qcsrc/client/hud.qc:794 +msgid "Unavailable" +msgstr "" + +#: qcsrc/client/hud.qc:1534 +#, c-format +msgid "^1%s^1 couldn't take it anymore\n" +msgstr "" + +#: qcsrc/client/hud.qc:1538 qcsrc/client/hud.qc:1887 +#, c-format +msgid "^1%s^1 died\n" +msgstr "" + +#: qcsrc/client/hud.qc:1542 +#, c-format +msgid "^7%s^7 committed suicide. What's the point of living without ammo?\n" +msgstr "" + +#: qcsrc/client/hud.qc:1546 +#, c-format +msgid "^1%s^1 thought they found a nice camping ground\n" +msgstr "" + +#: qcsrc/client/hud.qc:1550 +#, c-format +msgid "^1%s^1 didn't become friends with the Lord of Teamplay\n" +msgstr "" + +#: qcsrc/client/hud.qc:1554 +#, c-format +msgid "^1%s^1 unfairly eliminated themself\n" +msgstr "" + +#: qcsrc/client/hud.qc:1558 +#, c-format +msgid "^1%s^1 burned to death\n" +msgstr "" + +#: qcsrc/client/hud.qc:1562 +#, c-format +msgid "^1%s^1 couldn't resist the urge to self-destruct\n" +msgstr "" + +#: qcsrc/client/hud.qc:1566 +#, c-format +msgid "^1%s^1 ended it all after a %d kill spree\n" +msgstr "" + +#: qcsrc/client/hud.qc:1583 +#, c-format +msgid "^1%s^1 took action against a team mate\n" +msgstr "" + +#: qcsrc/client/hud.qc:1585 +#, c-format +msgid "^1%s^1 mows down a team mate\n" +msgstr "" + +#: qcsrc/client/hud.qc:1590 +#, c-format +msgid "^1%s^1 ended a %d scoring spree by going against a team mate\n" +msgstr "" + +#: qcsrc/client/hud.qc:1592 +#, c-format +msgid "^1%s^1 ended a %d kill spree by killing a team mate\n" +msgstr "" + +#: qcsrc/client/hud.qc:1596 +#, c-format +msgid "^1%s^1's %s scoring spree was ended by a team mate!\n" +msgstr "" + +#: qcsrc/client/hud.qc:1598 +#, c-format +msgid "^1%s^1's %s kill spree was ended by a team mate!\n" +msgstr "" + +#: qcsrc/client/hud.qc:1602 +#, c-format +msgid "^1%s^1 drew first blood\n" +msgstr "" + +#: qcsrc/client/hud.qc:1606 +#, c-format +msgid "^1%s^1 tried to occupy %s^1's teleport destination space\n" +msgstr "" + +#: qcsrc/client/hud.qc:1608 +#, c-format +msgid "^1%s^1 was telefragged by %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1613 +#, c-format +msgid "^1%s^1 was drowned by %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1618 +#, c-format +msgid "^1%s^1 was slimed by %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1623 +#, c-format +msgid "^1%s^1 was cooked by %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1628 +#, c-format +msgid "^1%s^1 was grounded by %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1633 +#, c-format +msgid "^1%s^1 was shot into space by %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1638 +#, c-format +msgid "^1%s^1 was conserved by %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1644 +#, c-format +msgid "^1%s^1 was thrown into a world of hurt by %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1648 +#, c-format +msgid "^1%s^1 was crushed by %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1652 +#, c-format +msgid "^1%s^1 got shredded by %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1656 +#, c-format +msgid "^1%s^1 was blasted to bits by %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1660 +#, c-format +msgid "^1%s^1 got caught in the destruction of %s^1's vehicle\n" +msgstr "" + +#: qcsrc/client/hud.qc:1664 +#, c-format +msgid "^1%s^1 was bolted down by %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1668 +#, c-format +msgid "^1%s^1 could find no shelter from %s^1's rockets\n" +msgstr "" + +#: qcsrc/client/hud.qc:1672 +#, c-format +msgid "^1%s^1 dies when %s^1's wakizashi dies.\n" +msgstr "" + +#: qcsrc/client/hud.qc:1676 +#, c-format +msgid "^1%s^1 nailed to hell by %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1680 +#, c-format +msgid "^1%s^1 cluster crushed by %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1684 +#, c-format +msgid "^1%s^1 dies when %s^1's raptor dies.\n" +msgstr "" + +#: qcsrc/client/hud.qc:1688 +#, c-format +msgid "^1%s^1 was pushed into the line of fire by %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1692 +#, c-format +msgid "^1%s^1 was pushed into an accident by %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1696 +#, c-format +msgid "^1%s^1 was unfairly eliminated by %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1700 +#, c-format +msgid "^1%s^1 was burnt to death by %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1712 +#, c-format +msgid "^1%s^1 was fragged by %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1717 +#, c-format +msgid "^1%s^1's %s scoring spree was ended by %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1719 +#, c-format +msgid "^1%s^1's %s kill spree was ended by %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1722 +#, c-format +msgid "^1%s^1 made %s scores in a row\n" +msgstr "" + +#: qcsrc/client/hud.qc:1724 +#, c-format +msgid "^1%s^1 has %s frags in a row\n" +msgstr "" + +#: qcsrc/client/hud.qc:1727 +#, c-format +msgid "%s^7 made a ^1TRIPLE SCORE\n" +msgstr "" + +#: qcsrc/client/hud.qc:1729 +#, c-format +msgid "%s^7 made a ^1TRIPLE FRAG\n" +msgstr "" + +#: qcsrc/client/hud.qc:1732 +#, c-format +msgid "%s^7 unleashes ^1SCORING RAGE\n" +msgstr "" + +#: qcsrc/client/hud.qc:1734 +#, c-format +msgid "%s^7 unleashes ^1RAGE\n" +msgstr "" + +#: qcsrc/client/hud.qc:1737 +#, c-format +msgid "%s^7 made ^1TEN SCORES IN A ROW!\n" +msgstr "" + +#: qcsrc/client/hud.qc:1739 +#, c-format +msgid "%s^7 starts the ^1MASSACRE!\n" +msgstr "" + +#: qcsrc/client/hud.qc:1742 +#, c-format +msgid "%s^7 made ^1FIFTEEN SCORES IN A ROW!\n" +msgstr "" + +#: qcsrc/client/hud.qc:1744 +#, c-format +msgid "%s^7 executes ^1MAYHEM!\n" +msgstr "" + +#: qcsrc/client/hud.qc:1747 +#, c-format +msgid "%s^7 made ^1TWENTY SCORES IN A ROW!\n" +msgstr "" + +#: qcsrc/client/hud.qc:1749 +#, c-format +msgid "%s^7 is a ^1BERSERKER!\n" +msgstr "" + +#: qcsrc/client/hud.qc:1752 +#, c-format +msgid "%s^7 made ^1TWENTY FIVE SCORES IN A ROW!\n" +msgstr "" + +#: qcsrc/client/hud.qc:1754 +#, c-format +msgid "%s^7 inflicts ^1CARNAGE!\n" +msgstr "" + +#: qcsrc/client/hud.qc:1757 +#, c-format +msgid "%s^7 made ^1THIRTY SCORES IN A ROW!\n" +msgstr "" + +#: qcsrc/client/hud.qc:1759 +#, c-format +msgid "%s^7 unleashes ^1ARMAGEDDON!\n" +msgstr "" + +#: qcsrc/client/hud.qc:1767 +#, c-format +msgid "^1%s^1 was in the water for too long\n" +msgstr "" + +#: qcsrc/client/hud.qc:1769 +#, c-format +msgid "^1%s^1 drowned\n" +msgstr "" + +#: qcsrc/client/hud.qc:1774 +#, c-format +msgid "^1%s^1 was slimed\n" +msgstr "" + +#: qcsrc/client/hud.qc:1780 +#, c-format +msgid "^1%s^1 found a hot place\n" +msgstr "" + +#: qcsrc/client/hud.qc:1782 +#, c-format +msgid "^1%s^1 turned into hot slag\n" +msgstr "" + +#: qcsrc/client/hud.qc:1789 +#, c-format +msgid "^1%s^1 tested gravity (and it worked)\n" +msgstr "" + +#: qcsrc/client/hud.qc:1791 +#, c-format +msgid "^1%s^1 hit the ground with a crunch\n" +msgstr "" + +#: qcsrc/client/hud.qc:1796 +#, c-format +msgid "^1%s^1 became a shooting star\n" +msgstr "" + +#: qcsrc/client/hud.qc:1802 +#, c-format +msgid "^1%s^1 discovered a swamp\n" +msgstr "" + +#: qcsrc/client/hud.qc:1804 +#, c-format +msgid "^1%s^1 is now conserved for centuries to come\n" +msgstr "" + +#: qcsrc/client/hud.qc:1811 +#, c-format +msgid "^1%s^1 ran into a turret\n" +msgstr "" + +#: qcsrc/client/hud.qc:1817 +#, c-format +msgid "^1%s^1 was laserd down by a eWheel turret \n" +msgstr "" + +#: qcsrc/client/hud.qc:1820 +#, c-format +msgid "^1%s^1 got caught in the flac \n" +msgstr "" + +#: qcsrc/client/hud.qc:1823 +#, c-format +msgid "^1%s^1 was riddeld full of riddled by a machinegun turret \n" +msgstr "" + +#: qcsrc/client/hud.qc:1826 +#, c-format +msgid "^1%s^1 got served a led enrichment by a walker turret \n" +msgstr "" + +#: qcsrc/client/hud.qc:1829 +#, c-format +msgid "^1%s^1 was impaled by a walker turret \n" +msgstr "" + +#: qcsrc/client/hud.qc:1832 +#, c-format +msgid "^1%s^1 was rocketed to hell by a walker turret \n" +msgstr "" + +#: qcsrc/client/hud.qc:1835 +#, c-format +msgid "^1%s^1 was blasted away hellion turret \n" +msgstr "" + +#: qcsrc/client/hud.qc:1838 +#, c-format +msgid "^1%s^1 could not hide from the hunter turret \n" +msgstr "" + +#: qcsrc/client/hud.qc:1841 +#, c-format +msgid "^1%s^1 got turned into smoldering gibs by a mlrs turret \n" +msgstr "" + +#: qcsrc/client/hud.qc:1844 +#, c-format +msgid "^1%s^1 got served some superheated plasma from a plasma turret \n" +msgstr "" + +#: qcsrc/client/hud.qc:1847 +#, c-format +msgid "^1%s^1 was phased out \n" +msgstr "" + +#: qcsrc/client/hud.qc:1850 +#, c-format +msgid "^1%s^1 was electrocuted by a tesla turret \n" +msgstr "" + +#: qcsrc/client/hud.qc:1866 +#, c-format +msgid "^1%s^1 died in an accident\n" +msgstr "" + +#: qcsrc/client/hud.qc:1870 +#, c-format +msgid "^1%s^1 was unfairly eliminated\n" +msgstr "" + +#: qcsrc/client/hud.qc:1876 +#, c-format +msgid "^1%s^1 felt a little hot\n" +msgstr "" + +#: qcsrc/client/hud.qc:1878 +#, c-format +msgid "^1%s^1 burnt to death\n" +msgstr "" + +#: qcsrc/client/hud.qc:1885 +#, c-format +msgid "^1%s^1 needs a restart\n" +msgstr "" + +#: qcsrc/client/hud.qc:1892 +#, c-format +msgid "^1%s^1 needs a restart after a %d scoring spree\n" +msgstr "" + +#: qcsrc/client/hud.qc:1894 +#, c-format +msgid "^1%s^1 died with a %d kill spree\n" +msgstr "" + +#: qcsrc/client/hud.qc:1898 +#, c-format +msgid "%s^7 got the %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1901 +#, c-format +msgid "%s^7 lost the %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1904 +#, c-format +msgid "%s^7 picked up the %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1907 +#, c-format +msgid "%s^7 returned the %s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1910 +#, c-format +msgid "%s^7 captured the %s%s\n" +msgstr "" + +#: qcsrc/client/hud.qc:1929 +#, c-format +msgid "%s^7 has picked up the ball!\n" +msgstr "" + +#: qcsrc/client/hud.qc:1934 +#, c-format +msgid "%s^7 has dropped the ball!\n" +msgstr "" + +#: qcsrc/client/hud.qc:1945 +#, c-format +msgid "You are now on: %s" +msgstr "" + +#: qcsrc/client/hud.qc:1947 +#, c-format +msgid "" +"You have been moved into a different team to improve team balance\n" +"You are now on: %s" +msgstr "" + +#: qcsrc/client/hud.qc:1950 +msgid "^1Reconsider your tactics, camper!" +msgstr "" + +#: qcsrc/client/hud.qc:1952 +msgid "^1Die camper!" +msgstr "" + +#: qcsrc/client/hud.qc:1955 +msgid "^1You are reinserted into the game for running out of ammo..." +msgstr "" + +#: qcsrc/client/hud.qc:1957 +msgid "^1You were killed for running out of ammo..." +msgstr "" + +#: qcsrc/client/hud.qc:1960 +msgid "^1You need to preserve your health" +msgstr "" + +#: qcsrc/client/hud.qc:1962 +msgid "^1You grew too old without taking your medicine" +msgstr "" + +#: qcsrc/client/hud.qc:1965 +msgid "^1Don't go against team mates!" +msgstr "" + +#: qcsrc/client/hud.qc:1967 +msgid "^1Don't shoot your team mates!" +msgstr "" + +#: qcsrc/client/hud.qc:1972 +msgid "^1You need to be more careful!" +msgstr "" + +#: qcsrc/client/hud.qc:1974 +msgid "^1You killed your own dumb self!" +msgstr "" + +#: qcsrc/client/hud.qc:1979 +#, c-format +msgid "^1Moron! You went against ^7%s^1, a team mate!" +msgstr "" + +#: qcsrc/client/hud.qc:1981 +#, c-format +msgid "^1Moron! You fragged ^7%s^1, a team mate!" +msgstr "" + +#: qcsrc/client/hud.qc:1985 +msgid "^1First score" +msgstr "" + +#: qcsrc/client/hud.qc:1987 +msgid "^1First blood" +msgstr "" + +#: qcsrc/client/hud.qc:1991 +msgid "^1First casualty" +msgstr "" + +#: qcsrc/client/hud.qc:1993 +msgid "^1First victim" +msgstr "" + +#: qcsrc/client/hud.qc:1997 +#, c-format +msgid "^1You scored against ^7%s^1 who was typing!" +msgstr "" + +#: qcsrc/client/hud.qc:1999 +#, c-format +msgid "^1You typefragged ^7%s" +msgstr "" + +#: qcsrc/client/hud.qc:2003 +#, c-format +msgid "^1You were scored against by ^7%s^1 while you were typing!" +msgstr "" + +#: qcsrc/client/hud.qc:2005 +#, c-format +msgid "^1You were typefragged by ^7%s" +msgstr "" + +#: qcsrc/client/hud.qc:2009 +#, c-format +msgid "^4You scored against ^7%s" +msgstr "" + +#: qcsrc/client/hud.qc:2011 +#, c-format +msgid "^4You fragged ^7%s" +msgstr "" + +#: qcsrc/client/hud.qc:2015 +#, c-format +msgid "^1You were scored against by ^7%s" +msgstr "" + +#: qcsrc/client/hud.qc:2017 +#, c-format +msgid "^1You were fragged by ^7%s" +msgstr "" + +#: qcsrc/client/hud.qc:2022 +msgid "^1Watch your step!" +msgstr "" + +#: qcsrc/client/hud.qc:2091 qcsrc/client/hud.qc:2092 qcsrc/client/hud.qc:2598 +#, c-format +msgid "Player %d" +msgstr "" + +#: qcsrc/client/hud.qc:2907 +msgid "^1Intermediate 1 (+15.42)" +msgstr "" + +#: qcsrc/client/hud.qc:2909 qcsrc/client/hud.qc:2951 qcsrc/client/hud.qc:2992 +#, c-format +msgid "^1PENALTY: %.1f (%s)" +msgstr "" + +#: qcsrc/client/hud.qc:2994 +#, c-format +msgid "^2PENALTY: %.1f (%s)" +msgstr "" + +#: qcsrc/client/hud.qc:3022 +msgid "^1You must answer before entering hud configure mode\n" +msgstr "" + +#: qcsrc/client/hud.qc:3027 +msgid "^2Name ^7instead of \"^1Anonymous player^7\" in stats" +msgstr "" + +#: qcsrc/client/hud.qc:3109 +msgid "A vote has been called for:" +msgstr "" + +#: qcsrc/client/hud.qc:3111 +msgid "Allow servers to store and display your name?" +msgstr "" + +#: qcsrc/client/hud.qc:3115 +msgid "^1Configure the HUD" +msgstr "" + +#: qcsrc/client/hud.qc:3119 +#, c-format +msgid "Yes (%s): %d" +msgstr "" + +#: qcsrc/client/hud.qc:3121 +#, c-format +msgid "No (%s): %d" +msgstr "" + +#: qcsrc/client/hud.qc:3624 qcsrc/client/hud.qc:3627 qcsrc/client/hud.qc:3629 +msgid "Personal best" +msgstr "" + +#: qcsrc/client/hud.qc:3642 qcsrc/client/hud.qc:3645 qcsrc/client/hud.qc:3647 +msgid "Server best" +msgstr "" + +#: qcsrc/client/hud.qc:3993 +msgid "^3Player^7: This is the chat area." +msgstr "" + +#: qcsrc/client/hud.qc:4061 +#, c-format +msgid "FPS: %.*f" +msgstr "" + +#: qcsrc/client/hud.qc:4128 +msgid "^1Observing" +msgstr "" + +#: qcsrc/client/hud.qc:4131 qcsrc/client/hud.qc:4133 +#, c-format +msgid "^1Spectating: ^7%s" +msgstr "" + +#: qcsrc/client/hud.qc:4138 +#, c-format +msgid "^1Press ^3%s^1 to spectate" +msgstr "" + +#: qcsrc/client/hud.qc:4140 +#, c-format +msgid "^1Press ^3%s^1 for another player" +msgstr "" + +#: qcsrc/client/hud.qc:4144 +#, c-format +msgid "^1Use ^3%s^1 or ^3%s^1 to change the speed" +msgstr "" + +#: qcsrc/client/hud.qc:4146 +#, c-format +msgid "^1Press ^3%s^1 to observe" +msgstr "" + +#: qcsrc/client/hud.qc:4149 +#, c-format +msgid "^1Press ^3%s^1 for gamemode info" +msgstr "" + +#: qcsrc/client/hud.qc:4153 +msgid "^1Wait for your turn to join" +msgstr "" + +#: qcsrc/client/hud.qc:4159 +msgid "^1Match has already begun" +msgstr "" + +#: qcsrc/client/hud.qc:4161 +msgid "^1You have no more lives left" +msgstr "" + +#: qcsrc/client/hud.qc:4163 qcsrc/client/hud.qc:4166 +#, c-format +msgid "^1Press ^3%s^1 to join" +msgstr "" + +#: qcsrc/client/hud.qc:4174 +#, c-format +msgid "^1Game starts in ^3%d^1 seconds" +msgstr "" + +#: qcsrc/client/hud.qc:4181 +msgid "^2Currently in ^1warmup^2 stage!" +msgstr "" + +#: qcsrc/client/hud.qc:4196 +#, c-format +msgid "%sPress ^3%s%s to end warmup" +msgstr "" + +#: qcsrc/client/hud.qc:4198 +#, c-format +msgid "%sPress ^3%s%s once you are ready" +msgstr "" + +#: qcsrc/client/hud.qc:4203 +msgid "^2Waiting for others to ready up to end warmup..." +msgstr "" + +#: qcsrc/client/hud.qc:4205 +msgid "^2Waiting for others to ready up..." +msgstr "" + +#: qcsrc/client/hud.qc:4211 +#, c-format +msgid "^2Press ^3%s^2 to end warmup" +msgstr "" + +#: qcsrc/client/hud.qc:4232 +msgid "Teamnumbers are unbalanced!" +msgstr "" + +#: qcsrc/client/hud.qc:4237 +#, c-format +msgid " Press ^3%s%s to adjust" +msgstr "" + +#: qcsrc/client/hud.qc:4245 +msgid "^7Press ^3ESC ^7to show HUD options." +msgstr "" + +#: qcsrc/client/hud.qc:4247 +msgid "^3Doubleclick ^7a panel for panel-specific options." +msgstr "" + +#: qcsrc/client/hud.qc:4249 +msgid "^3CTRL ^7to disable collision testing, ^3SHIFT ^7and" +msgstr "" + +#: qcsrc/client/hud.qc:4251 +msgid "^3ALT ^7+ ^3ARROW KEYS ^7for fine adjustments." +msgstr "" + +#: qcsrc/client/hud.qc:4289 +msgid " qu/s" +msgstr "" + +#: qcsrc/client/hud.qc:4293 +msgid " m/s" +msgstr "" + +#: qcsrc/client/hud.qc:4297 +msgid " km/h" +msgstr "" + +#: qcsrc/client/hud.qc:4301 +msgid " mph" +msgstr "" + +#: qcsrc/client/hud.qc:4305 +msgid " knots" +msgstr "" + +#: qcsrc/client/hud.qc:4968 +msgid "Automatically fixed wrong/missing panel numbers in _hud_panelorder\n" +msgstr "" + +#: qcsrc/common/mapinfo.qc:1097 +#, c-format +msgid "%s: %s" +msgstr "" + +#: qcsrc/server/w_crylink.qc:666 +#, c-format +msgid "%s succeeded at self-destructing themself with the Crylink" +msgstr "" + +#: qcsrc/server/w_crylink.qc:671 +#, c-format +msgid "%s could not hide from %s's Crylink" +msgstr "" + +#: qcsrc/server/w_crylink.qc:673 +#, c-format +msgid "%s was too close to %s's Crylink" +msgstr "" + +#: qcsrc/server/w_crylink.qc:675 +#, c-format +msgid "%s took a close look at %s's Crylink" +msgstr "" + +#: qcsrc/server/w_hlac.qc:2 +msgid "Heavy Laser Assault Cannon" +msgstr "" + +#: qcsrc/server/w_hlac.qc:240 qcsrc/server/w_fireball.qc:423 +#, c-format +msgid "%s should have used a smaller gun" +msgstr "" + +#: qcsrc/server/w_hlac.qc:242 +#, c-format +msgid "%s was cut down with a HLAC by %s" +msgstr "" + +#: qcsrc/server/w_minstanex.qc:2 +msgid "MinstaNex" +msgstr "" + +#: qcsrc/server/w_minstanex.qc:293 qcsrc/server/w_nex.qc:253 +#: qcsrc/server/w_shotgun.qc:271 qcsrc/server/w_rifle.qc:232 +#: qcsrc/server/w_uzi.qc:318 +#, c-format +msgid "%s is now thinking with portals" +msgstr "" + +#: qcsrc/server/w_minstanex.qc:295 +#, c-format +msgid "%s has been vaporized by %s's minstanex" +msgstr "" + +#: qcsrc/server/w_grenadelauncher.qc:388 +#, c-format +msgid "%s didn't see their own grenade" +msgstr "" + +#: qcsrc/server/w_grenadelauncher.qc:390 +#, c-format +msgid "%s blew themself up with their grenadelauncher" +msgstr "" + +#: qcsrc/server/w_grenadelauncher.qc:396 +#, c-format +msgid "%s didn't see %s's grenade" +msgstr "" + +#: qcsrc/server/w_grenadelauncher.qc:398 +#, c-format +msgid "%s almost dodged %s's grenade" +msgstr "" + +#: qcsrc/server/w_grenadelauncher.qc:400 +#, c-format +msgid "%s ate %s's grenade" +msgstr "" + +#: qcsrc/server/w_laser.qc:312 +#, c-format +msgid "%s lasered themself to hell" +msgstr "" + +#: qcsrc/server/w_laser.qc:316 +#, c-format +msgid "%s was cut in half by %s's gauntlet" +msgstr "" + +#: qcsrc/server/w_laser.qc:318 +#, c-format +msgid "%s was lasered to death by %s" +msgstr "" + +#: qcsrc/server/w_nex.qc:255 +#, c-format +msgid "%s has been vaporized by %s's nex" +msgstr "" + +#: qcsrc/server/w_hook.qc:2 +msgid "Grappling Hook" +msgstr "" + +#: qcsrc/server/w_hook.qc:286 qcsrc/server/w_porto.qc:296 +#, c-format +msgid "%s did the impossible" +msgstr "" + +#: qcsrc/server/w_hook.qc:288 +#, c-format +msgid "%s was caught in %s's hook gravity bomb" +msgstr "" + +#: qcsrc/server/w_rocketlauncher.qc:507 +#, c-format +msgid "%s blew themself up with their rocketlauncher" +msgstr "" + +#: qcsrc/server/w_rocketlauncher.qc:511 +#, c-format +msgid "%s got too close to %s's rocket" +msgstr "" + +#: qcsrc/server/w_rocketlauncher.qc:513 +#, c-format +msgid "%s almost dodged %s's rocket" +msgstr "" + +#: qcsrc/server/w_rocketlauncher.qc:515 +#, c-format +msgid "%s ate %s's rocket" +msgstr "" + +#: qcsrc/server/w_porto.qc:298 +#, c-format +msgid "%s felt %s doing the impossible to him" +msgstr "" + +#: qcsrc/server/w_electro.qc:581 +#, c-format +msgid "%s could not remember where they put their electro plasma" +msgstr "" + +#: qcsrc/server/w_electro.qc:583 +#, c-format +msgid "%s played with electro plasma" +msgstr "" + +#: qcsrc/server/w_electro.qc:590 +#, c-format +msgid "%s just noticed %s's electro plasma" +msgstr "" + +#: qcsrc/server/w_electro.qc:592 +#, c-format +msgid "%s got in touch with %s's electro plasma" +msgstr "" + +#: qcsrc/server/w_electro.qc:597 +#, c-format +msgid "%s felt the electrifying air of %s's electro combo" +msgstr "" + +#: qcsrc/server/w_electro.qc:599 +#, c-format +msgid "%s got too close to %s's blue electro bolt" +msgstr "" + +#: qcsrc/server/w_electro.qc:601 +#, c-format +msgid "%s was blasted by %s's blue electro bolt" +msgstr "" + +#: qcsrc/server/w_hagar.qc:462 +#, c-format +msgid "%s played with tiny hagar rockets" +msgstr "" + +#: qcsrc/server/w_hagar.qc:466 +#, c-format +msgid "%s was pummeled with a burst of hagar rockets by %s" +msgstr "" + +#: qcsrc/server/w_hagar.qc:468 +#, c-format +msgid "%s was pummeled with hagar rockets by %s" +msgstr "" + +#: qcsrc/server/w_shotgun.qc:275 +#, c-format +msgid "%2$s slapped %1$s around a bit with a large shotgun" +msgstr "" + +#: qcsrc/server/w_shotgun.qc:277 +#, c-format +msgid "%s was gunned down with a shotgun by %s" +msgstr "" + +#: qcsrc/server/w_tuba.qc:2 +#, c-format +msgid "@!#%'n Tuba" +msgstr "" + +#: qcsrc/server/w_tuba.qc:444 +#, c-format +msgid "%s hurt his own ears with the @!#%%'n Tuba" +msgstr "" + +#: qcsrc/server/w_tuba.qc:447 +#, c-format +msgid "%s hurt his own ears with the @!#%%'n Accordeon" +msgstr "" + +#: qcsrc/server/w_tuba.qc:465 +#, c-format +msgid "%s died of %s's great playing on the @!#%%'n Tuba" +msgstr "" + +#: qcsrc/server/w_tuba.qc:468 +#, c-format +msgid "%s died of %s's great playing on the @!#%%'n Accordeon" +msgstr "" + +#: qcsrc/server/w_minelayer.qc:533 +#, c-format +msgid "%s blew themself up with their minelayer" +msgstr "" + +#: qcsrc/server/w_minelayer.qc:535 +#, c-format +msgid "%s forgot about their mine" +msgstr "" + +#: qcsrc/server/w_minelayer.qc:539 +#, c-format +msgid "%s got too close to %s's mine" +msgstr "" + +#: qcsrc/server/w_minelayer.qc:541 +#, c-format +msgid "%s almost dodged %s's mine" +msgstr "" + +#: qcsrc/server/w_minelayer.qc:543 +#, c-format +msgid "%s stepped on %s's mine" +msgstr "" + +#: qcsrc/server/w_rifle.qc:239 +#, c-format +msgid "%s failed to hide from %s's rifle bullet hail" +msgstr "" + +#: qcsrc/server/w_rifle.qc:241 +#, c-format +msgid "%s died in %s's rifle bullet hail" +msgstr "" + +#: qcsrc/server/w_rifle.qc:248 +#, c-format +msgid "%s failed to hide from %s's rifle" +msgstr "" + +#: qcsrc/server/w_rifle.qc:253 +#, c-format +msgid "%s got shot in the head with a rifle by %s" +msgstr "" + +#: qcsrc/server/w_rifle.qc:255 +#, c-format +msgid "%s was sniped with a rifle by %s" +msgstr "" + +#: qcsrc/server/w_uzi.qc:322 +#, c-format +msgid "%s was sniped by %s's machine gun" +msgstr "" + +#: qcsrc/server/w_uzi.qc:324 +#, c-format +msgid "%s was riddled full of holes by %s's machine gun" +msgstr "" + +#: qcsrc/server/w_fireball.qc:421 +#, c-format +msgid "%s forgot about some firemine" +msgstr "" + +#: qcsrc/server/w_fireball.qc:430 +#, c-format +msgid "%s tried to catch %s's firemine" +msgstr "" + +#: qcsrc/server/w_fireball.qc:432 +#, c-format +msgid "%s fatefully ignored %s's firemine" +msgstr "" + +#: qcsrc/server/w_fireball.qc:439 +#, c-format +msgid "%s could not hide from %s's fireball" +msgstr "" + +#: qcsrc/server/w_fireball.qc:441 +#, c-format +msgid "%s saw the pretty lights of %s's fireball" +msgstr "" + +#: qcsrc/server/w_fireball.qc:444 +#, c-format +msgid "%s got too close to %s's fireball" +msgstr "" + +#: qcsrc/server/w_fireball.qc:446 +#, c-format +msgid "%s tasted %s's fireball" +msgstr "" + +#: qcsrc/server/w_seeker.qc:2 +msgid "T.A.G. Seeker" +msgstr "" + +#: qcsrc/server/w_seeker.qc:661 +#, c-format +msgid "%s played with tiny seeker rockets" +msgstr "" + +#: qcsrc/server/w_seeker.qc:665 +#, c-format +msgid "%s was tagged with a seeker by %s" +msgstr "" + +#: qcsrc/server/w_seeker.qc:667 +#, c-format +msgid "%s was pummeled with seeker rockets by %s" +msgstr "" diff --git a/ctfscoring-ai.cfg b/ctfscoring-ai.cfg index 28ed89dd5f..7113736478 100644 --- a/ctfscoring-ai.cfg +++ b/ctfscoring-ai.cfg @@ -1,22 +1,3 @@ -set g_ctf_flagscore_pickup_base 1 -set g_ctf_flagscore_pickup_dropped_early 0 -set g_ctf_flagscore_pickup_dropped_late 1 -set g_ctf_flagscore_capture 20 -set g_ctf_flagscore_kill 2 -set g_ctf_flagpenalty_drop 0 -set g_ctf_flagpenalty_suicidedrop 1 -set g_ctf_flagpenalty_returned 0 -set g_ctf_flagscore_return 3 -set g_ctf_flagscore_return_rogue 3 -set g_ctf_flagscore_return_by_killer 5 -set g_ctf_flagscore_return_rogue_by_killer 5 - -// succeeded capture (pickup capture) 21 (0 for enemy) -// failed capture (pickup kill drop return) 1 (8 for enemy) -// failed (shot into void) (pickup kill drop) 1 (2 for enemy) -// capture retry (kill drop pickup) 0..1 (2 for enemy) -// suicide, then retake (suicidedrop pickup) -1 (0 for enemy) - set g_ctf_personalscore_pickup_base 1 set g_ctf_personalscore_pickup_dropped_early 0 set g_ctf_personalscore_pickup_dropped_late 1 diff --git a/ctfscoring-alien.cfg b/ctfscoring-alien.cfg index a32ffda130..dd5758d495 100644 --- a/ctfscoring-alien.cfg +++ b/ctfscoring-alien.cfg @@ -1,21 +1,3 @@ -set g_ctf_flagscore_pickup_base 1 -set g_ctf_flagscore_pickup_dropped_early 1 -set g_ctf_flagscore_pickup_dropped_late 1 -set g_ctf_flagscore_capture 30 -set g_ctf_flagscore_kill 1 -set g_ctf_flagpenalty_drop 2 -set g_ctf_flagpenalty_suicidedrop 2 -set g_ctf_flagpenalty_returned 0 -set g_ctf_flagscore_return 5 -set g_ctf_flagscore_return_rogue 10 -set g_ctf_flagscore_return_by_killer 6 -set g_ctf_flagscore_return_rogue_by_killer 11 -// succeeded capture (pickup capture) 31 (0 for enemy) -// failed capture (pickup kill drop return) -1 (6 or 7 for enemy) -// failed (shot into void) (pickup kill drop) 1 (1 for enemy) -// capture retry (kill drop pickup) -1 (1 for enemy) -// suicide, then retake (suicidedrop pickup) -1 (0 for enemy) - set g_ctf_personalscore_pickup_base 1 set g_ctf_personalscore_pickup_dropped_early 1 set g_ctf_personalscore_pickup_dropped_late 1 diff --git a/ctfscoring-alpha.cfg b/ctfscoring-alpha.cfg index a97bd6e64b..c15cee8dab 100644 --- a/ctfscoring-alpha.cfg +++ b/ctfscoring-alpha.cfg @@ -1,21 +1,3 @@ -set g_ctf_flagscore_pickup_base 0 -set g_ctf_flagscore_pickup_dropped_early 0 -set g_ctf_flagscore_pickup_dropped_late 0 -set g_ctf_flagscore_capture 20 -set g_ctf_flagscore_kill 0 -set g_ctf_flagpenalty_drop 0 -set g_ctf_flagpenalty_suicidedrop 0 -set g_ctf_flagpenalty_returned 0 -set g_ctf_flagscore_return 5 -set g_ctf_flagscore_return_rogue 10 -set g_ctf_flagscore_return_by_killer 5 -set g_ctf_flagscore_return_rogue_by_killer 10 -// succeeded capture (pickup capture) 20 (0 for enemy) -// failed capture (pickup kill drop return) 0 (5 for enemy) -// failed (shot into void) (pickup kill drop) 0 (0 for enemy) -// capture retry (kill drop pickup) 0 (0 for enemy) -// suicide, then retake (suicidedrop pickup) 0 (0 for enemy) - set g_ctf_personalscore_pickup_base 0 set g_ctf_personalscore_pickup_dropped_early 0 set g_ctf_personalscore_pickup_dropped_late 0 diff --git a/ctfscoring-div0.cfg b/ctfscoring-div0.cfg index d36d0ad10f..33c8ab1b72 100644 --- a/ctfscoring-div0.cfg +++ b/ctfscoring-div0.cfg @@ -1,22 +1,3 @@ -set g_ctf_flagscore_pickup_base 0 -set g_ctf_flagscore_pickup_dropped_early 1 -set g_ctf_flagscore_pickup_dropped_late 1 -set g_ctf_flagscore_capture 25 -set g_ctf_flagscore_kill 3 -set g_ctf_flagpenalty_drop 2 -set g_ctf_flagpenalty_suicidedrop 2 -set g_ctf_flagpenalty_returned 1 -set g_ctf_flagscore_return 5 // not adjusted as this would suck for team game -set g_ctf_flagscore_return_rogue 10 -set g_ctf_flagscore_return_by_killer 5 -set g_ctf_flagscore_return_rogue_by_killer 10 - -// succeeded capture (pickup capture) 25 (0 for enemy) -// failed capture (pickup kill drop return) -3 (8 for enemy) -// failed (shot into void) (pickup kill drop) -2 (3 for enemy) -// capture retry (kill drop pickup) -1 (3 for enemy) -// suicide, then retake (suicidedrop pickup) -1 (0 for enemy) - set g_ctf_personalscore_pickup_base 0 set g_ctf_personalscore_pickup_dropped_early 1 set g_ctf_personalscore_pickup_dropped_late 1 diff --git a/ctfscoring-nex242.cfg b/ctfscoring-nex242.cfg index 193cc183fb..861ead4613 100644 --- a/ctfscoring-nex242.cfg +++ b/ctfscoring-nex242.cfg @@ -1,21 +1,3 @@ -set g_ctf_flagscore_pickup_base 1 -set g_ctf_flagscore_pickup_dropped_early 1 -set g_ctf_flagscore_pickup_dropped_late 1 -set g_ctf_flagscore_capture 20 -set g_ctf_flagscore_kill 1 -set g_ctf_flagpenalty_drop 0 -set g_ctf_flagpenalty_suicidedrop 1 -set g_ctf_flagpenalty_returned 0 -set g_ctf_flagscore_return 5 -set g_ctf_flagscore_return_rogue 10 -set g_ctf_flagscore_return_by_killer 5 -set g_ctf_flagscore_return_rogue_by_killer 10 -// succeeded capture (pickup capture) 21 (0 for enemy) -// failed capture (pickup kill drop return) 1 (6 for enemy) -// failed (shot into void) (pickup kill drop) 1 (1 for enemy) -// capture retry (kill drop pickup) 1 (1 for enemy) -// suicide, then retake (suicidedrop pickup) 0 (0 for enemy) - set g_ctf_personalscore_pickup_base 1 set g_ctf_personalscore_pickup_dropped_early 1 set g_ctf_personalscore_pickup_dropped_late 1 diff --git a/ctfscoring-z-lowdeposit.cfg b/ctfscoring-z-lowdeposit.cfg index 52acece12f..c75b306806 100644 --- a/ctfscoring-z-lowdeposit.cfg +++ b/ctfscoring-z-lowdeposit.cfg @@ -1,5 +1,3 @@ -exec ctfscoring-ai.cfg // fall back to ai's scoring for flag scores, if g_ctf_win_mode is 2, as this system is highly broken in that mode - set g_ctf_personalscore_pickup_base -1 set g_ctf_personalscore_pickup_dropped_early 5 set g_ctf_personalscore_pickup_dropped_late 9 diff --git a/ctfscoring-z.cfg b/ctfscoring-z.cfg index bffe0d0561..e45bdd93a3 100644 --- a/ctfscoring-z.cfg +++ b/ctfscoring-z.cfg @@ -1,5 +1,3 @@ -exec ctfscoring-ai.cfg // fall back to ai's scoring for flag scores, if g_ctf_win_mode is 2, as this system is highly broken in that mode - set g_ctf_personalscore_pickup_base -5 set g_ctf_personalscore_pickup_dropped_early 1 set g_ctf_personalscore_pickup_dropped_late 5 diff --git a/data/campaign.cfg b/data/campaign.cfg new file mode 100644 index 0000000000..c8a6efb6ce --- /dev/null +++ b/data/campaign.cfg @@ -0,0 +1 @@ +// placeholder file, is replaced by data/campaign.cfg in user home directory diff --git a/defaultSamual.cfg b/defaultSamual.cfg deleted file mode 100644 index c0dce41e13..0000000000 --- a/defaultSamual.cfg +++ /dev/null @@ -1,31 +0,0 @@ -// Samual's mod configuration file -exec defaultXonotic.cfg - -// weapon replace options -set g_weaponreplace_laser "" -set g_weaponreplace_shotgun "" -set g_weaponreplace_uzi "" -set g_weaponreplace_grenadelauncher "" -set g_weaponreplace_electro "" -set g_weaponreplace_crylink "" -set g_weaponreplace_nex "" -set g_weaponreplace_hagar "" -set g_weaponreplace_rocketlauncher "" -set g_weaponreplace_porto "" -set g_weaponreplace_minstanex "" -set g_weaponreplace_hook "" -set g_weaponreplace_hlac 0 // Maybe will be enabled later after I figure out what I want to do with it -set g_weaponreplace_campingrifle "" -set g_weaponreplace_tuba "" -set g_weaponreplace_fireball 0 // Same with this -set g_weaponreplace_seeker 0 // Same with this -set sv_q3acompat_machineshotgunswap 0 - -// other options -set sv_fragmessage_information_ping 1 -set sv_fragmessage_information_handicap 2 -set sv_fragmessage_information_stats 1 -set sv_fragmessage_information_typefrag 1 - -exec physicsSamual.cfg -exec balanceSamual.cfg diff --git a/defaultXPM.cfg b/defaultXPM.cfg index 35d5da9859..38d74c7c99 100644 --- a/defaultXPM.cfg +++ b/defaultXPM.cfg @@ -7,6 +7,7 @@ exec defaultXonotic.cfg // players sv_fbskin_green // visible playermodel forced on everyone +set teamplay_mode 2 // friendly fire and self damage //================ // impure changes @@ -25,8 +26,6 @@ set g_shootfromcenter 1 // hit where you point at with the crosshair (almost so, // match rules set timelimit_overtimes 1 // overtimes on, draw matches are less interesting! :) set g_forced_respawn 1 // no delaying/cheating a match by not spawning -set g_mirrordamage 0 // hurting teammates does not hurt you... -set g_friendlyfire 1 // ...it hurts them. // info -set sv_fragmessage_information_stats 0 // don't reveal how much health/armor the attacker had +set sv_fraginfo_stats 0 // don't reveal how much health/armor the attacker had diff --git a/defaultXonotic.cfg b/defaultXonotic.cfg index 18ce4a9881..52c14b2be9 100644 --- a/defaultXonotic.cfg +++ b/defaultXonotic.cfg @@ -9,7 +9,8 @@ // // e.g. Xonotic 1.5.1 RC1 will be 15101 set g_xonoticversion git "Xonotic version (formatted for humans)" -gameversion 100 // 0.1.0 + +gameversion 500 // 0.5.0 gameversion_min 0 // git builds see all versions gameversion_max 65535 // git builds see all versions @@ -21,22 +22,9 @@ gameversion_max 65535 // git builds see all versions // gameversion_min = (gameversion / 100) * 100 - 100 // gameversion_max = (gameversion / 100) * 100 + 199 -// changes a cvar and reports it to the server (for the menu to notify the -// server about changes) -alias setreport "set \"$1\" \"$2\" ; sendcvar \"$1\"" - seta cl_firststart "" "how many times the client has been run" seta cl_startcount 0 "how many times the client has been run" -// detect dedicated server or client -alias "_detect_dedicated_$qport" "${* asis}" -alias "_detect_dedicated_0" "" -alias _if_dedicated "_detect_dedicated_$qport ${* asis}" -alias if_client "${* asis}" -alias if_dedicated "${* asis}" -_if_dedicated alias if_client "" -if_client alias if_dedicated "" - seta g_configversion 0 "Configuration file version (used to upgrade settings) 0: first run, or previous start was <2.4.1 Later, it's overridden by config.cfg, version ranges are defined in config_update.cfg" // say aliases @@ -51,39 +39,16 @@ alias asay_drop "say_team (%l) dropped %w ; impulse 17" // other aliases alias +hook +button6 alias -hook -button6 -alias ready "cmd ready" -alias lockteams "sv_cmd lockteams" -alias unlockteams "sv_cmd unlockteams" -alias nospectators "sv_cmd nospectators" -alias cointoss "sv_cmd cointoss" -alias timeout "cmd timeout" //use this command to call a timeout -alias timein "cmd timein" //use this command to resume the game before timeout is finished - -alias bsp "ls maps/*.bsp" -alias chmap "changelevel $*" -alias gotomap "sv_cmd gotomap \"$1\"" - -alias rec "record demos/$1" -alias ply "playdemo $1" -alias tdem "timedemo $1" +alias use "impulse 21" + +// for backwards compatibility alias dropweapon "impulse 17" alias +show_info +button7 alias -show_info -button7 -alias team_red "cmd selectteam red; cmd join" -alias team_blue "cmd selectteam blue; cmd join" -alias team_pink "cmd selectteam pink; cmd join" -alias team_yellow "cmd selectteam yellow; cmd join" -alias team_auto "cmd selectteam auto; cmd join" bind f6 team_auto -alias movetoteam_red "sv_cmd movetoteam $1 red" -alias movetoteam_blue "sv_cmd movetoteam $1 blue" -alias movetoteam_pink "sv_cmd movetoteam $1 pink" -alias movetoteam_yellow "sv_cmd movetoteam $1 yellow" -alias movetoteam_auto "sv_cmd movetoteam $1 auto" - // merge lightmaps up to 2048x2048 textures mod_q3bsp_lightmapmergepower 4 @@ -102,6 +67,9 @@ seta crosshair_dot_size 0.600000 seta crosshair_dot_color "1 0 0" "when != 0, use custom color for the crosshair dot" seta crosshair_pickup 0.25 seta crosshair_pickup_speed 4 +seta crosshair_hitindication 0.5 +seta crosshair_hitindication_color "10 -10 -10" +seta crosshair_hitindication_speed 5 seta crosshair_per_weapon 0 "when 1, each gun will display a different crosshair" seta crosshair_color_per_weapon 1 "when 1, each gun will display the crosshair with a different color" seta crosshair_effect_speed -1 "how fast (in seconds) some crosshair effects should take place, 0 = instant, -1 = 2x weapon switch time" @@ -169,10 +137,10 @@ seta crosshair_seeker "" "crosshair to display when wielding the TAG Seeker" seta crosshair_seeker_color "1 0.35 0.35" "crosshair color to display when wielding the TAG seeker" seta crosshair_seeker_alpha 0.9 "crosshair alpha value to display when wielding the TAG seeker" seta crosshair_seeker_size 0.8 "crosshair size when wielding the TAG seeker" -seta crosshair_campingrifle "" "crosshair to display when wielding the campingrifle" -seta crosshair_campingrifle_color "0.85 0.5 0.25" "crosshair color to display when wielding the campingrifle" -seta crosshair_campingrifle_alpha 1 "crosshair alpha value to display when wielding the campingrifle" -seta crosshair_campingrifle_size 0.65 "crosshair size when wielding the campingrifle" +seta crosshair_rifle "" "crosshair to display when wielding the rifle" +seta crosshair_rifle_color "0.85 0.5 0.25" "crosshair color to display when wielding the rifle" +seta crosshair_rifle_alpha 1 "crosshair alpha value to display when wielding the rifle" +seta crosshair_rifle_size 0.5 "crosshair size when wielding the rifle" seta crosshair_tuba "" "crosshair to display when wielding the tuba" seta crosshair_tuba_color "0.85 0.5 0.25" "crosshair color to display when wielding the tuba" seta crosshair_tuba_alpha 1 "crosshair alpha value to display when wielding the tuba" @@ -181,14 +149,16 @@ seta crosshair_fireball "" "crosshair to display when wielding the fireball" seta crosshair_fireball_color "0.2 1.0 0.2" "crosshair color to display when wielding the fireball" seta crosshair_fireball_alpha 1 "crosshair alpha value to display when wielding the fireball" seta crosshair_fireball_size 1 "crosshair size when wielding the fireball" +seta crosshair_color_by_health 0 "if enabled, crosshair color will depend on current health" // ring around crosshair, used for various purposes (such as indicating bullets left in clip, nex charge) -seta crosshair_ring_size 2 "bullet counter ring size for Rifle, velocity ring for Nex" +seta crosshair_ring 1 "main cvar to enable or disable normal crosshair rings" +seta crosshair_ring_inner 0 "allow inner rings to be drawn too" +seta crosshair_ring_size 2 "ring size" seta crosshair_ring_alpha 0.2 "ring alpha" -seta crosshair_ring_campingrifle_alpha 0.15 - -seta crosshair_ring_nex_outer_alpha 0.15 +seta crosshair_ring_nex 1 "draw a ring showing the current charge of the nexgun" +seta crosshair_ring_nex_alpha 0.15 seta crosshair_ring_nex_inner_alpha 0.15 seta crosshair_ring_nex_inner_color_red 0.8 seta crosshair_ring_nex_inner_color_green 0 @@ -196,14 +166,27 @@ seta crosshair_ring_nex_inner_color_blue 0 seta crosshair_ring_nex_currentcharge_scale 30 seta crosshair_ring_nex_currentcharge_movingavg_rate 0.05 +seta crosshair_ring_minelayer 1 +seta crosshair_ring_minelayer_alpha 0.15 + +seta crosshair_ring_hagar 1 +seta crosshair_ring_hagar_alpha 0.15 + +seta crosshair_ring_reload 1 "main cvar to enable or disable ammo crosshair rings" +seta crosshair_ring_reload_size 2.5 "reload ring size" +seta crosshair_ring_reload_alpha 0.2 "reload ring alpha" + +seta cl_reticle 1 "control for toggling whether ANY zoom reticles are shown" seta cl_reticle_stretch 0 "whether to stretch reticles so they fit the screen (brakes image proportions)" -seta cl_reticle_item_nex 1 "draw aiming recticle for the nex weapon's zoom, 0 disables and values between 0 and 1 change alpha" -seta cl_reticle_item_normal 1 "draw recticle when zooming with the zoom button, 0 disables and values between 0 and 1 change alpha" +seta cl_reticle_item_nex 1 "draw aiming reticle for the nex weapon's zoom, 0 disables and values between 0 and 1 change alpha" +seta cl_reticle_item_normal 1 "draw reticle when zooming with the zoom button, 0 disables and values between 0 and 1 change alpha" fov 90 seta cl_velocityzoom 0 "velocity based zooming of fov, negative values zoom out" -seta cl_velocityzoomtime 0.3 "time value for averaging speed values" +seta cl_velocityzoom_type 3 "how to factor in speed, 1 = all velocity in all directions, 2 = velocity only in forward direction (can be negative), 3 = velocity only in forward direction (limited to forward only)" +seta cl_velocityzoom_speed 1000 "target speed for fov factoring" +seta cl_velocityzoom_time 0.2 "time value for averaging speed values" seta cl_zoomfactor 5 "how much +zoom will zoom (1-16)" -seta cl_zoomspeed 3.5 "how fast it will zoom (0.5-16), negative values mean instant zoom" +seta cl_zoomspeed 8 "how fast it will zoom (0.5-16), negative values mean instant zoom" seta cl_zoomsensitivity 0 "how zoom changes sensitivity (0 = weakest, 1 = strongest)" freelook 1 sensitivity 6 @@ -227,8 +210,14 @@ vid_conheight 600 // menu_conwidth, menu_conheight are set inside quake.rc v_deathtilt 0 // needed for spectators (who are dead to avoid prediction) +// we want to use sRGB for our maps! +exec sRGB-disable.cfg +vid_sRGB_fallback 2 +r_hdr_glowintensity 1 + // these settings determine how much the view is affected by movement/damage -cl_deathfade 1 // fade screen to dark red when dead, value represents how fast the fade is (higher is faster) +cl_smoothviewheight 0.05 // time of the averaging to the viewheight value so that it creates a smooth transition for crouching and such. 0 for instant transition +cl_deathfade 0 // fade screen to dark red when dead, value represents how fast the fade is (higher is faster) cl_bobcycle 0 // how long the cycle of up/down view movement takes (only works if cl_bob is not 0), default is 0.6 cl_bob 0.01 // how much view moves up/down when moving (does not move if cl_bobcycle is 0, but still enables cl_bobmodel), default is 0.02 cl_bob2cycle 0 // how long the cycle of left/right view movement takes (only works if cl_bob2 is not 0), default is 0.6 @@ -264,15 +253,7 @@ cl_rollangle 0 // amount of view tilt when strafing, default is 2.0 v_kicktime 0 // how long damage kicks of the view last, default is 0 seconds gl_polyblend 0 // whether to use screen tints, this has now been replaced by a better system in CSQC r_motionblur 0 // motion blur value, default is 0 -r_damageblur 0 // motion blur when damaged, default is 0 - -r_bloom_blur 8 -r_bloom_brighten 3 -r_bloom_colorexponent 1 -r_bloom_colorscale 1 -r_bloom_colorsubtract 0.25 -r_bloom_resolution 320 -r_hdr_range 4 +r_damageblur 0 // motion blur when damaged, default is 0 (removed in Xonotic) seta vid_x11_display "" "xonotic-linux-*.sh will use this to start xonotic on an other/new X display" // This can have three possible settings: @@ -287,7 +268,7 @@ seta cl_autotaunt 0 "automatically taunt enemies when fragging them" seta sv_taunt 1 "allow taunts on the server" seta sv_autotaunt 1 "allow autotaunts on the server" seta cl_voice_directional 1 "0 = all voices are non-directional, 1 = all voices are directional, 2 = only taunts are directional" -seta cl_voice_directional_taunt_attenuation 0.5 "this defines the distance from which taunts can be heared" +seta cl_voice_directional_taunt_attenuation 0.5 "this defines the distance from which taunts can be heard" // server settings hostname "Xonotic $g_xonoticversion Server" @@ -299,7 +280,12 @@ set sv_ready_restart 0 "if set to 1 allow a map to be restarted once all players set sv_ready_restart_after_countdown 0 "if set to 1 the players and map items are reset after the countdown ended, otherwise they're reset already at the beginning of the countdown" set sv_ready_restart_repeatable 0 "allows the players to restart the game as often as needed" -set sv_hitsound_antispam_time 0.05 "don't play the hitsound more often than this for the electro lightning gun or the laser gauntlet" +seta cl_hitsound 1 "play a hit notifier sound when you have hit an enemy" +set cl_hitsound_antispam_time 0.05 "don't play the hitsound more often than this" + +seta cl_eventchase_death 1 "camera goes into 3rd person mode when the player is dead" +seta cl_eventchase_distance 140 "final camera distance" +seta cl_eventchase_speed 1.3 "how fast the camera slides back, 0 is instant" //nifreks lockonrestart feature, used in team-based game modes, if set to 1 and all players readied up no other player can then join the game anymore, useful to block spectators from joining set teamplay_lockonrestart 0 "it set to 1 in a team-based game, the teams are locked once all players readied up and the game restarted (no new players can join after restart unless using the server-command unlockteams)" @@ -307,11 +293,12 @@ set teamplay_lockonrestart 0 "it set to 1 in a team-based game, the teams are lo set g_maxplayers 0 "maximum number of players allowed to play at the same time, set to 0 to allow all players to join the game" set g_maxplayers_spectator_blocktime 5 "if the players voted for the \"nospectators\" command, this setting defines the number of seconds a observer/spectator has time to join the game before he gets kicked" -//tournament mod +// tournament mod set g_warmup 0 "split the game into a warmup- and match-stage when set to 1" -set g_warmup_limit 60 "if set to -1 the warmup-stage is not affected by any timelimit, if set to 0 the usual timelimit also affects warmup-stage, otherwise warmup will be limited to this time in SECONDS (useful for public matches)" +set g_warmup_limit 0 "if set to -1 the warmup-stage is not affected by any timelimit, if set to 0 the usual timelimit also affects warmup-stage, otherwise warmup will be limited to this time in SECONDS (useful for public matches)" set g_warmup_allow_timeout 0 "if set to 1 timeouts can also be called in the warmup-stage, when sv_timeout is set to 1" -set g_warmup_allguns 0 "if set players start with all guns in warmup mode" +set g_warmup_allguns 1 "if set players start with all guns in warmup mode" +set g_warmup_majority_factor 0.8 "minimum percentage of players ready needed for warmup to end" set g_chat_nospectators 0 "if 0 spec/observer chat is always visible to the player, if 1 it is never visible to players, if 2 it is only visible to players during warmup stage" set sv_vote_nospectators 0 "if set only players can call a vote (thus spectators and observers can't call a vote)" @@ -328,7 +315,6 @@ set sv_timeout_resumetime 3 "how long the remaining timeout-time will be after a set g_allow_oldnexbeam 0 "If enabled, clients are allowed to use old v2.3 Nexgun beam" seta cl_particles_oldnexbeam 0 "Uses the old v2.3 Nexgun beam instead of the new beam, only works if server allows it (g_allow_oldnexbeam 1)" -set sv_qcweaponanimation 0 set g_telefrags 1 "telefragging, i.e. killing someone who stands in the way of someone who is teleporting" set g_telefrags_teamplay 1 "never telefrag team mates" @@ -338,12 +324,15 @@ set g_teleport_maxspeed 0 "maximum speed that a player can keep when going throu set g_respawn_ghosts 1 "if 1 dead bodies become ghosts and float away when the player respawns" set g_respawn_ghosts_speed 5 "the speed with which respawn ghosts float and rotate" set g_respawn_ghosts_maxtime 6 "maximum amount of time a respawn ghost can last, minimum time is half this value. 0 disables and ghosts fade when the body would" +set cl_deathglow 0.8 "number of seconds during which dead bodies glow out" + +set sv_gibhealth 100 "Minus health a dead body must have in order to get gibbed" // fragmessage: This allows extra information to be displayed with the frag centerprints. -set sv_fragmessage_information_ping 1 "Enable ping display information, 0 = Never display; 1 = Always display (If the player is a bot, it will say bot instead of the ping.)" -set sv_fragmessage_information_handicap 1 "Enable handicap display information, 0 = Never display; 1 = Only when the player has handicap on; 2 = Always display (Displays Off if off)" -set sv_fragmessage_information_stats 1 "Enable statistics (health/armor) display information, 0 = Never display; 1 = Always display (Only available for the person who was killed)" -set sv_fragmessage_information_typefrag 1 "Enable typefrag display information, 0 = Never display; 1 = Always display" +set sv_fraginfo 1 "Enable extra frag message information, 0 = Never display, 1 = Display only in warmup mode; 2 = Always display" +set sv_fraginfo_ping 1 "Enable ping display information, 0 = Never display, 1 = Always display (If the player is a bot, it will say bot instead of the ping.)" +set sv_fraginfo_handicap 1 "Enable handicap display information, 0 = Never display, 1 = Only when the player has handicap on, 2 = Always display (Displays Off if disabled)" +set sv_fraginfo_stats 1 "Enable statistics (health/armor) display information, 0 = Never display, 1 = Always display (Only available for the person who was killed)" // use default physics set sv_friction_on_land 0 @@ -356,11 +345,11 @@ set sv_player_crouch_viewoffset "0 0 20" "view offset of the player model when c set sv_player_crouch_mins "-16 -16 -24" "mins of a crouched playermodel" set sv_player_crouch_maxs "16 16 25" "maxs of a crouched playermodel" -set sv_pogostick 1 "don't require releasing the space bar for jumping again" set sv_doublejump 0 "allow Quake 2-style double jumps" set sv_jumpspeedcap_min "" "lower bound on the baseline velocity of a jump; final velocity will be >= (jumpheight * min + jumpheight)" set sv_jumpspeedcap_max "" "upper bound on the baseline velocity of a jump; final velocity will be <= (jumpheight * max + jumpheight)" set sv_jumpspeedcap_max_disable_on_ramps 0 "disable upper baseline velocity bound on ramps to preserve the old rampjump style" +set sv_player_jumpanim_minfall 48 "minimum distance player has to have below their feet before the jump animation will be activated (only when falling, +jump will play anim instantly)" seta sv_precacheplayermodels 1 seta sv_precacheweapons 0 @@ -368,8 +357,8 @@ seta sv_precacheitems 0 set sv_spectator_speed_multiplier 1.5 seta sv_spectate 1 "if set to 1, new clients are allowed to spectate or observe the game, if set to 0 joining clients spawn as players immediately (no spectating)" seta sv_defaultcharacter 0 "master switch, if set to 1 the further configuration for replacing all player models, skins and colors is taken from the sv_defaultplayermodel, sv_defaultplayerskin and sv_defaultplayercolors variables" -seta sv_defaultplayermodel "models/player/erebus.iqm" "default model selection, only works if sv_defaultcharacter is set to 1" -seta sv_defaultplayerskin 0 "each model has 1 or more skins (combination of model and skin = character), set which skin of the model you wish the default character to have, only works if sv_defaultcharacter is set to 1" +seta sv_defaultplayermodel "models/player/erebus.iqm" "default model selection, only works if sv_defaultcharacter is set to 1; you may append a : suffix to model names; you can specify multiple, separated by space, and a random one will be chosen" +seta sv_defaultplayerskin 0 "each model has 1 or more skins (combination of model and skin = character), set which skin of the model you wish the default character to have, only works if sv_defaultcharacter is set to 1; can be overriden by : suffix in sv_defaultplayermodel" seta sv_defaultplayermodel_red "" "\"\" means see sv_defaultplayermodel" seta sv_defaultplayerskin_red 0 seta sv_defaultplayermodel_blue "" "\"\" means see sv_defaultplayermodel" @@ -385,13 +374,12 @@ net_connecttimeout 30 sv_jumpstep 1 // step up stairs while jumping, makes it easier to reach ledges set ekg 0 "Throw huge amounts of gibs" +seta sv_shownames_cull_distance 2500 "distance after which to not send origin/health/armor of another player" + cl_movement 1 cl_movement_track_canjump 0 cl_stairsmoothspeed 200 -seta cl_autoswitch 1 "automatically switch to newly picked up weapons if they are better than what you are carrying" -alias autoswitch "set cl_autoswitch $1 ; cmd autoswitch $1" - set bot_config_file bots.txt "Name and path of the bot configuration file" set bot_number 0 "Minimum number of bots" seta bot_usemodelnames 0 "Use player model names for bot names" @@ -399,39 +387,42 @@ set bot_nofire 0 "When set, bots never fire. Mainly for testing in g_waypointedi seta bot_prefix [BOT] "Prefix in front of the bot names" seta bot_suffix "" "Suffix behind the bot names" seta skill_auto 0 "when 1, \"skill\" gets adjusted to match the best player on the map" +set bot_debug_tracewalk 0 "Enable visual indicators for short-term navigation. Green: Goal Reached / Yellow: Obstacle found / Red: Unsolvable obstacle found" +set bot_debug_goalstack 0 "Visualize the current path that each bot is following. Use with as few bots as possible." +set bot_wander_enable 1 "Have bots wander around if they are unable to reach any useful goal. Disable only for debugging purposes." // general bot AI cvars set bot_ai_thinkinterval 0.05 -set bot_ai_strategyinterval 3 "How often a new objective is chosen" -set bot_ai_enemydetectioninterval 0.5 "How often bots pick a new target" +set bot_ai_strategyinterval 5 "How often a new objective is chosen" +set bot_ai_enemydetectioninterval 2 "How often bots pick a new target" set bot_ai_enemydetectionradius 10000 "How far bots can see enemies" -set bot_ai_dodgeupdateinterval 0.1 "How often scan for items to dodge. Currently not in use." -set bot_ai_chooseweaponinterval 0.3 "How often the best weapon according to the situation will be chosen" -set bot_ai_dangerdetectioninterval 0.1 "How often scan for waypoints with dangers near" +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_dangerdetectioninterval 0.25 "How often scan for waypoints with dangers near" set bot_ai_dangerdetectionupdates 64 "How many waypoints will be considered for danger detection" set bot_ai_aimskill_blendrate 2 "How much correction will be applied to the aiming angle" set bot_ai_aimskill_fixedrate 15 -set bot_ai_aimskill_firetolerance_distdegrees 180 +set bot_ai_aimskill_firetolerance_distdegrees 100 set bot_ai_aimskill_firetolerance_mindegrees 2 "Minimum angle tolerance. Used on large distances" set bot_ai_aimskill_firetolerance_maxdegrees 60 "Maximum firing angle. Used on close range" set bot_ai_aimskill_mouse 1 "How much of the aiming filters are applied" set bot_ai_keyboard_distance 250 "Keyboard emulation is disabled after this distance to the goal" -set bot_ai_keyboard_treshold 0.57 +set bot_ai_keyboard_threshold 0.57 set bot_ai_aimskill_offset 0.3 "Amount of error induced to the bots aim" set bot_ai_aimskill_think 1 "Aiming velocity. Use values below 1 for slower aiming" set bot_ai_custom_weapon_priority_distances "300 850" "Define close and far distances in any order. Based on the distance to the enemy bots will choose different weapons" -set bot_ai_custom_weapon_priority_far "minstanex nex campingrifle electro rocketlauncher grenadelauncher hagar hlac crylink laser uzi fireball seeker shotgun tuba minelayer" "Desired weapons for far distances ordered by priority" -set bot_ai_custom_weapon_priority_mid "minstanex rocketlauncher nex fireball seeker grenadelauncher electro uzi campingrifle crylink hlac hagar shotgun laser tuba minelayer" "Desired weapons for middle distances ordered by priority" -set bot_ai_custom_weapon_priority_close "minstanex shotgun nex uzi hlac tuba seeker hagar crylink grenadelauncher electro campingrifle rocketlauncher laser fireball minelayer" "Desired weapons for close distances ordered by priority" +set bot_ai_custom_weapon_priority_far "minstanex nex rifle electro rocketlauncher grenadelauncher hagar hlac crylink laser uzi fireball seeker shotgun tuba minelayer" "Desired weapons for far distances ordered by priority" +set bot_ai_custom_weapon_priority_mid "minstanex rocketlauncher nex fireball seeker grenadelauncher electro uzi crylink hlac hagar shotgun laser rifle tuba minelayer" "Desired weapons for middle distances ordered by priority" +set bot_ai_custom_weapon_priority_close "minstanex shotgun nex uzi hlac tuba seeker hagar crylink grenadelauncher electro rocketlauncher laser fireball rifle minelayer" "Desired weapons for close distances ordered by priority" set bot_ai_weapon_combo 1 "Enable bots to do weapon combos" -set bot_ai_weapon_combo_threshold 0.3 "Try to make a combo N seconds after the last attack" +set bot_ai_weapon_combo_threshold 0.4 "Try to make a combo N seconds after the last attack" 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 250 "Run to goals located further than this distance" -set bot_ai_bunnyhop_stopdistance 220 "Stop jumping after reaching this distance to the goal" -set bot_ai_bunnyhop_firstjumpdelay 0.5 "Start running to the goal only if it was seen for more than N seconds" +set bot_ai_bunnyhop_startdistance 200 "Run to goals located further than this distance" +set bot_ai_bunnyhop_stopdistance 200 "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_god 0 "god mode for bots" -set bot_ai_navigation_jetpack 0 "Enable bots to navigat maps using the jetpack" +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" // Better don't touch these, there are hard to tweak! set bot_ai_aimskill_order_mix_1st 0.01 "Amount of the 1st filter output to apply to the aiming angle" @@ -447,6 +438,7 @@ set bot_ai_aimskill_order_filter_5th 0.5 "Movement prediction filter. Used rarel // waypoint editor enable set g_waypointeditor 0 +set g_waypointeditor_auto 0 "Automatically create waypoints for bots while playing; BEWARE, this currently creates too many of them" set bot_ignore_bots 0 "When set, bots don't shoot at other bots" set bot_join_empty 0 "When set, bots also play if no player has joined the server" set bot_vs_human 0 "Bots and humans play in different teams when set. positive values to make an all-bot blue team, set to negative values to make an all-bot red team, the absolute value is the ratio bots vs humans (1 for equal count). Changes will be correctly applied only from the next game" @@ -459,23 +451,21 @@ alias g_waypointeditor_unreachable "impulse 107" locs_enable 0 pausable 0 -seta g_spawnshieldtime 0.300000 "number of seconds you are invincible after you spawned, this shield is lost after you fire" -seta g_antilag 2 "AntiLag (0 = no AntiLag, 1 = verified client side hit scan, 2 = server side hit scan in the past, 3 = unverified client side hit scan)" +set g_spawnshieldtime 1 "number of seconds you are invincible after you spawned, this shield is lost after you fire" +set g_antilag 2 "AntiLag (0 = no AntiLag, 1 = verified client side hit scan, 2 = server side hit scan in the past, 3 = unverified client side hit scan)" +set g_trueaim_minrange 44 "TrueAim minimum range (TrueAim adjusts shots so they hit the crosshair point even though the gun is not at the screen center)" set g_antilag_nudge 0 "don't touch" set g_antilag_bullets 1 "Bullets AntiLag (0 = no AntiLag, 1 = server side hit scan in the past) - DO NOT TOUCH (severely changes weapon balance)" -set g_shootfromclient 1 "let client decide if it has the gun left or right; if set to 2, center handedness is allowed, and defaulted to, too; see also cl_gunalign" +set g_shootfromclient 2 "let client decide if it has the gun left or right; if set to 2, center handedness is allowed; see also cl_gunalign" 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 "if set to 1 or 2, weapons stay after they were picked up (1: weapons you don't have yet give you ammo of their type and they can not be dropped, 2: weapons don't give ammo, but instead players start with one pickup-load of ammo by default, 3: weapons give ammo, weapons only stay as ammo-less ghosts)" +set g_weapon_stay 0 "1: ghost weapons can be picked up too but give no ammo, 2: ghost weapons refill ammo to one pickup size, thrown guns have no ammo" set g_weapon_throwable 1 "if set to 1, weapons can be dropped" -set g_powerup_superhealth 1 "if set to 0 the mega health powerup will not spawn on the map" -set g_powerup_strength 1 "if set to 0 the strength powerup will not spawn on the map" -set g_powerup_shield 1 "if set to 0 the shield (invincibility) powerup will not spawn on the map" -set g_balance_powerup_timer 1 "if set to 0 the powerups dont wear off" -set g_use_ammunition 1 "if set to 0 all weapons you pick up have unlimited ammunition" -set g_pickup_items 1 "if set to 0 all items (health, armor, ammo, weapons...) are removed from the map" +set g_powerups -1 "if set to 0 the strength and shield (invincibility) will not spawn on the map, if 1 they will spawn in all game modes, -1 is game mode default" +set g_use_ammunition 1 "if set to 0 all weapons have unlimited ammunition" +set g_pickup_items -1 "if set to 0 all items (health, armor, ammo, weapons...) are removed from the map, if 1 they are forced to spawn" set g_minstagib 0 "enable minstagib" set g_minstagib_extralives 2 "how many extra lives you will get per powerup" set g_minstagib_ammo_start 10 "starting ammo" @@ -499,28 +489,60 @@ set g_casings 2 "specifies which casings (0: none, 1: only shotgun casings, 2: s set g_norecoil 0 "if set to 1 shooting weapons won't make you crosshair to move upwards (recoil)" set g_maplist_mostrecent "" "contains the name of the maps that were most recently played" seta g_maplist_mostrecent_count 3 "number of most recent maps that are blocked from being played again" -seta g_maplist "g-23" "the list of maps to be cycled among (is autogenerated if empty)" +seta g_maplist "" "the list of maps to be cycled among (is autogenerated if empty)" seta g_maplist_index 0 "this is used internally for saving position in maplist cycle" seta g_maplist_selectrandom 0 "if 1, a random map will be chosen as next map - DEPRECATED in favor of g_maplist_shuffle" seta g_maplist_shuffle 1 "new randomization method: like selectrandom, but avoid playing the same maps in short succession. This works by taking out the first element and inserting it into g_maplist with a bias to the end of the list" set g_maplist_check_waypoints 0 "when 1, maps are skipped if there currently are bots, but the map has no waypoints" set samelevel 0 "when 1, always play the same level over and over again" -set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap" + +set g_grab_range 200 "distance at which dragable objects can be grabbed" set g_cloaked 0 "display all players mostly invisible" set g_player_alpha 1 set g_player_brightness 0 "set to 2 for brighter players" seta g_balance_cloaked_alpha 0.25 +set g_sandbox 0 "allow players to spawn and edit objects around the map" +set g_sandbox_info 1 "print object information to the server. 1 prints info about spawned / removed objects, 2 also prints info about edited objects" +set g_sandbox_readonly 0 "when this mode is active, players cannot modify objects or use any sandbox commands" +set g_sandbox_storage_name default "name of the selected storage to use" +set g_sandbox_storage_autosave 5 "storage is automatically saved every specified number of seconds" +set g_sandbox_storage_autoload 1 "if a storage file exists for the given map, automatically load it at startup" +set g_sandbox_editor_flood 1 "players must wait this many seconds between spawning objects" +set g_sandbox_editor_maxobjects 1000 "maximum number of objects that may exist at a time" +set g_sandbox_editor_free 1 "0 = players can only copy or edit their own objects, 1 = players can copy but not edit other objects, 2 = players can copy and edit all object" +set g_sandbox_editor_distance_spawn 200 "distance at which objects spawn in front of the player" +set g_sandbox_editor_distance_edit 300 "distance at which players can edit or remove objects they are looking at" +set g_sandbox_object_scale_min 0.1 "minimum scale that objects can be set to" +set g_sandbox_object_scale_max 2 "maximum scale that objects can be set to" +set g_sandbox_object_material_velocity_min 100 "velocity objects must have while colliding for material effects to be applied" +set g_sandbox_object_material_velocity_factor 0.002 "velocity range which decides the intensity of material effects" +set cl_sandbox_clipboard "" + +seta menu_sandbox_spawn_model "" +seta menu_sandbox_attach_bone "" +seta menu_sandbox_edit_skin 0 +seta menu_sandbox_edit_alpha 1 +seta menu_sandbox_edit_color_main "1 1 1" +seta menu_sandbox_edit_color_glow "1 1 1" +seta menu_sandbox_edit_frame 0 +seta menu_sandbox_edit_scale 1 +seta menu_sandbox_edit_solidity 1 +seta menu_sandbox_edit_physics 1 +seta menu_sandbox_edit_force 1 +seta menu_sandbox_edit_material "" + +bind f7 menu_showsandboxtools + set g_playerclip_collisions 1 "0 = disable collision testing against playerclips, might be useful on some defrag maps" set g_botclip_collisions 1 "0 = disable collision testing against botclips, might be useful on some defrag maps" set welcome_message_time 8 -alias clearmap "disconnect" - set g_grappling_hook 0 "let players spawn with the grappling hook which allows them to pull themselves up" +set g_invincible_projectiles 0 "set to 1 to disable any damage to projectiles in all balance configs, regardless of g_projectiles_damage" set g_dodging 0 "set to 1 to enable dodging in games" set g_rocket_flying 0 "set to 1 to enable rocket flying in all balance configs" @@ -544,8 +566,6 @@ seta fraglimit_override -1 "Frag limit overriding the mapinfo specified one (use seta leadlimit_override -1 "Lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)" seta capturelimit_override -1 "Capture limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)" seta captureleadlimit_override -1 "Capture llead imit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)" -seta g_ctf_capture_limit -1 "CTF capture limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)" -seta g_ctf_capture_leadlimit -1 "CTF capture lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)" seta g_arena_point_limit -1 "Arena point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)" seta g_arena_point_leadlimit -1 "Arena point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)" seta g_domination_point_limit -1 "Domination point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)" @@ -558,19 +578,21 @@ seta g_race_laps_limit -1 "Race laps limit overriding the mapinfo specified one seta g_nexball_goallimit -1 "Nexball goal limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)" seta g_nexball_goalleadlimit -1 "Nexball goal lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)" -seta g_ctf_win_mode 0 "0: captures only, 1: captures, then points, 2: points only" seta g_ctf_ignore_frags 0 "1: regular frags give no points" set g_freezetag 0 "Freeze Tag: Freeze the opposing team(s) to win, unfreeze teammates by standing next to them" seta g_freezetag_warmup 5 "Time players get to run around before the round starts" seta g_freezetag_point_limit -1 "Freeze Tag point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)" seta g_freezetag_point_leadlimit -1 "Freeze Tag point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)" -seta g_freezetag_revive_time 2.5 "Time it takes to revive a frozen teammate" +seta g_freezetag_revive_speed 0.4 "Speed for reviving a frozen teammate" +seta g_freezetag_revive_clearspeed 1.6 "Speed at which reviving progress gets lost when out of range" seta g_freezetag_revive_extra_size 100 "Distance in qu that you can stand from a frozen teammate to keep reviving him" seta g_freezetag_frozen_force 0.6 "How much to multiply the force on a frozen player with" -// 50% of the spawns shall be far away from any players -set g_spawn_furthest 0.5 +set g_spawn_furthest 0.5 "this amount of the spawns shall be far away from any players" +set g_spawn_useallspawns 0 "use all spawns, e.g. also team spawns in non-teamplay, and all spawns, even enemy spawns, in teamplay" +set g_spawn_near_teammate 0 "if set, players prefer spawns near a team mate" +set g_spawn_near_teammate_distance 640 "max distance to consider a spawn to be near a team mate" // respawn delay set g_respawn_delay 2 "number of seconds you have to wait before you can respawn again" set g_respawn_waves 0 "respawn in waves (every n seconds), intended to decrease overwhelming base attacks" @@ -621,7 +643,7 @@ set g_cts_respawn_waves 0 set g_cts_respawn_delay 0 set g_cts_selfdamage 1 "0 = disable all selfdamage and falldamage in cts" set g_cts_finish_kill_delay 10 "prevent cheating by running back to the start line, and starting out with more speed than otherwise possible" -set g_cts_weapon_stay 1 +set g_cts_weapon_stay 2 set g_freezetag_respawn_waves 0 set g_freezetag_respawn_delay 0 set g_freezetag_weapon_stay 0 @@ -636,14 +658,17 @@ seta timelimit_suddendeath 5 "number of minutes suddendeath mode lasts after all // common team values set g_tdm 0 "Team Deathmatch: the team who kills their opponents most often wins" +set g_tdm_on_dm_maps 0 "when this is set, all DM maps automatically support TDM" seta teamplay_mode 4 "default teamplay setting in team games. 1 = no friendly fire, self damage. 2 = friendly fire and self damage enabled. 3 = no friendly fire, but self damage enabled. 4 = obey the following four cvars" -seta g_mirrordamage 0.300000 "for teamplay 4: mirror damage factor" -seta g_friendlyfire 0.100000 "for teamplay 4: fiendly fire factor" -seta g_teamdamage_threshold 50 "for teamplay 4: threshold over which to apply mirror damage" -seta g_teamdamage_resetspeed 30 "for teamplay 4: how fast player's teamdamage count decreases" +seta g_mirrordamage 0.700000 "for teamplay 4: mirror damage factor" +seta g_mirrordamage_virtual 1 "for teamplay 4: do not actually apply mirror damage, just show graphics effect for it" +seta g_friendlyfire 0.500000 "for teamplay 4: fiendly fire factor" +seta g_friendlyfire_virtual 1 "for teamplay 4: do not actually apply friendly fire, just show graphics effect for it" +seta g_friendlyfire_virtual_force 1 "for teamplay 4: apply force even though damage was made virtual only" +seta g_teamdamage_threshold 40 "for teamplay 4: threshold over which to apply mirror damage" +seta g_teamdamage_resetspeed 20 "for teamplay 4: how fast player's teamdamage count decreases" -set deathmatch_force_teamplay 0 "Always play TDM instead of DM" seta g_balance_teams 0 "automatically balance out players entering instead of asking them for their preferred team" seta g_balance_teams_force 0 "automatically balance out teams when players move or disconnect" seta g_balance_teams_prevent_imbalance 0 "prevent players from changing to larger teams" @@ -667,12 +692,12 @@ set g_ctf_flagcarrier_selfforce 1 set g_ctf_fullbrightflags 0 set g_ctf_dynamiclights 0 set g_ctf_allow_drop 1 "dropping allows circumventing carrierkill score, so enable this with care!" -set g_ctf_reverse 0 "when 1, bases/flags are switched :P you have to capture your OWN flag by bringing it to the ENEMY's" +set g_ctf_reverse 0 "if enabled, flags positions are switched: you have to capture the enemy's flag from your own base by bringing it to your own flag in the enemy base" set g_balance_ctf_delay_collect 1.0 set g_balance_ctf_damageforcescale 1 -set g_ctf_shield_max_ratio 0 "shield at most 0% of a team from the enemy flag (try: 0.4 for 40%)" -set g_ctf_shield_min_negscore 20 "shield the player from the flag if he's got -20 points or less" +set g_ctf_shield_max_ratio 0 "shield at most this percentage of a team from the enemy flag (try: 0.4 for 40%)" +set g_ctf_shield_min_negscore 20 "shield the player from the flag if he's got this negative amount of points or less" set g_ctf_shield_force 100 "push force of the shield" // fun for server admins @@ -767,12 +792,12 @@ set g_arena 0 "Arena: many one-on-one rounds are played to find the winner" set g_arena_maxspawned 2 "maximum number of players to spawn at once (the rest is spectating, waiting for their turn)" set g_arena_roundbased 1 "if disabled, the next player will spawn as soon as someone dies" set g_arena_warmup 5 "time, newly spawned players have to prepare themselves in round based matches" -set g_arena_powerups 0 "enables powerups (superhealth, strength and shield), which are removed by default" // ca set g_ca 0 "Clan Arena: Played in rounds, once you're dead you're out! The team with survivors wins the round." set g_ca_point_limit 10 "point limit 10 is standard for clan arena" set g_ca_point_leadlimit 0 +set g_ca_spectate_enemies 0 "Allow spectating enemy player by dead player during clan arena games." set g_ca_warmup 10 "how long the players will have time to run around the map before the round starts" // onslaught @@ -864,6 +889,8 @@ set g_multijump_add 0 "0 = make the current z velocity equal to jumpvelocity, 1 set g_multijump_speed -999999 "Minimum vertical speed a player must have in order to jump again" // effects +r_glsl_vertextextureblend_usebothalphas 1 // allows to abuse texture blending as detail texture +r_glsl_postprocess 1 r_picmipsprites 0 // Xonotic uses sprites that should never be picmipped (team mate, typing, waypoints) r_picmipworld 1 gl_picmip_world 0 @@ -872,10 +899,9 @@ gl_picmip_other 1 // so, picmip -1 is best possible quality r_mipsprites 1 r_mipskins 1 r_shadow_realtime_world_lightmaps 1 -seta r_ambient 4 cl_decals_fadetime 5 cl_decals_time 2 -seta cl_gunalign 3 "Gun alignment; 1 = right, 2 = left, 3 = center or right, 4 = center or left" +seta cl_gunalign 3 "Gun alignment; 1 = center (if allowed by g_shootfromclient) or right, 2 = center (if allowed by g_shootfromclient) or left, 3 = right only, 4 = left only" seta cl_nogibs 0 "reduce number of violence effects, or remove them totally" seta cl_particlegibs 0 "simpler gibs" seta cl_gibs_damageforcescale 3.5 "force to push around gibs" @@ -885,6 +911,7 @@ seta cl_gibs_velocity_random 1 "gib throw velocity randomness scale" seta cl_gibs_velocity_up 1 "extra z velocity for gibs" seta cl_gibs_ticrate 0.1 "ticrate for gibs" seta cl_gibs_sloppy 1 "sloppy gibs, may temporarily penetrate walls" +seta cl_gibs_avelocity_scale 1 "how much angular velocity to use on gibs" seta cl_casings 1 "enable or disable bullet casings" seta cl_casings_shell_time 30 "shell casing lifetime" seta cl_casings_bronze_time 10 "bullet casings lifetime" @@ -917,17 +944,16 @@ cl_sound_ric3 weapons/ric3.wav cl_sound_r_exp3 "" sv_sound_land "" sv_sound_watersplash "" -seta cl_sound_maptime_warning "1" "play announcer sound telling you the remaining maptime - 0: do not play at all, 1: play at one minute, 2: play at five minutes, 3: play both" -seta cl_notify_carried_items "3" "notify you of carried items when you obtain them (e.g. flags in CTF) - 0: disabled, 1: notify of taken items, 2: notify of picking up dropped items, 3: notify of both" -seta cl_hitsound 1 "play a hit notifier sound when you have hit an enemy" seta cl_announcer default "name of the announcer you wish to use from data/sound/announcer" +seta cl_announcer_antispam 2 "number of seconds before an announcement of the same sound can be played again" +seta cl_announcer_maptime 3 "play announcer sound telling you the remaining maptime - 0: do not play at all, 1: play at one minute, 2: play at five minutes, 3: play both" +seta cl_notify_carried_items "3" "notify you of carried items when you obtain them (e.g. flags in CTF) - 0: disabled, 1: notify of taken items, 2: notify of picking up dropped items, 3: notify of both" // startmap_dm is used when running with the -listen or -dedicated commandline options set serverconfig server.cfg -alias startmap_dm "set _sv_init 0; map _init/_init; exec $serverconfig; set _sv_init 1; map _init/_init" -alias sv_loadconfig "exec $serverconfig" -alias sv_restart "say \"Server will restart at the end of the match, you will all be reconnected automatically. $* \"; quit_and_redirect self" +set _sv_init 0 +alias startmap_dm "set _sv_init 0; map _init/_init; exec $serverconfig; set _sv_init 1" // aliases: alias +fire +attack @@ -936,8 +962,6 @@ alias +fire2 +button3 alias -fire2 -button3 alias +attack2 +button3 // old alias from Nexuiz alias -attack2 -button3 // old alias name from Nexuiz -alias +zoom +button4 -alias -zoom -button4 alias +crouch +button5 alias -crouch -button5 alias weapnext "_weapnext_${cl_weaponpriority_useforcycling}" @@ -951,6 +975,12 @@ alias _weapprev_1 "impulse 16" alias _weapprev_2 "impulse 12" alias weapbest "impulse 13" +// experimental zoom toggle (can be in wrong state at start of a game, though) +set _togglezoom + +alias +zoom "set _togglezoom -; +button4" +alias -zoom "set _togglezoom +; -button4" +alias togglezoom "${_togglezoom}zoom" + alias reload "impulse 20" // movement @@ -967,20 +997,31 @@ bind ENTER +jump bind SPACE +jump // weapons -bind 1 "impulse 1" -bind 2 "impulse 2" -bind 3 "impulse 3" -bind 4 "impulse 4" -bind 5 "impulse 5" -bind 6 "impulse 6" -bind 7 "impulse 7" -bind 8 "impulse 8" -bind 9 "impulse 9" -bind 0 "impulse 14" // cycles the superweapons +alias weapon_group_1 "impulse 1" +alias weapon_group_2 "impulse 2" +alias weapon_group_3 "impulse 3" +alias weapon_group_4 "impulse 4" +alias weapon_group_5 "impulse 5" +alias weapon_group_6 "impulse 6" +alias weapon_group_7 "impulse 7" +alias weapon_group_8 "impulse 8" +alias weapon_group_9 "impulse 9" +alias weapon_group_0 "impulse 14" // cycles the superweapons +exec weapons.cfg +bind 0 weapon_group_0 +bind 1 weapon_group_1 +bind 2 weapon_group_2 +bind 3 weapon_group_3 +bind 4 weapon_group_4 +bind 5 weapon_group_5 +bind 6 weapon_group_6 +bind 7 weapon_group_7 +bind 8 weapon_group_8 +bind 9 weapon_group_9 bind q weaplast bind MOUSE1 +fire bind MOUSE2 +fire2 -bind MOUSE3 +zoom +bind MOUSE3 togglezoom bind MOUSE4 weaplast bind MOUSE5 +hook bind MWHEELUP weapnext @@ -989,6 +1030,7 @@ bind r reload bind BACKSPACE dropweapon bind g dropweapon bind f +use +bind v +button8 // drag object // misc bind e +hook @@ -1000,9 +1042,10 @@ bind t messagemode bind y messagemode2 bind z messagemode2 bind u "+con_chat_maximize" +bind m +hud_panel_radar_maximized bind i +show_info bind PAUSE pause -bind F10 quit +bind F10 menu_showquitdialog bind F11 disconnect bind F12 screenshot bind F4 ready @@ -1056,51 +1099,10 @@ bind kp_enter "+userbind 16" bind kp_plus "+userbind 17" bind kp_minus "+userbind 18" -set sv_vote_commands "restart fraglimit chmap gotomap nextmap endmatch reducematchtime extendmatchtime allready kick cointoss movetoteam_auto" "these commands can be voted" -set sv_vote_only_commands "" -set sv_vote_master_commands "movetoteam_red movetoteam_blue movetoteam_yellow movetoteam_pink" "maybe add kickban here (but then sv_vote_master 0)" -set rcon_restricted_commands "restart fraglimit chmap gotomap endmatch reducematchtime extendmatchtime allready kick kickban \"sv_cmd bans\" \"sv_cmd unban *\" status \"sv_cmd teamstatus\" movetoteam_auto movetoteam_red movetoteam_blue movetoteam_yellow movetoteam_pink" -set sv_vote_call 1 "users can call a vote for the above commands" -set sv_vote_master 1 "users can call a vote to become master" -set sv_vote_master_password "" "when set, users can use \"vlogin PASSWORD\" to log in as master" -set sv_vote_change 1 "set to 1 to allow to change you vote/mind" -set sv_vote_singlecount 0 "set to 1 to count votes once after timeout or to 0 to count with every vote" -set sv_vote_timeout 30 "a vote will timeout after this many seconds" -set sv_vote_wait 120 "a player can not call a vote again for this many seconds when his vote was not accepted" -set sv_vote_stop 15 "a player can not call a vote again for this many seconds when he stopped this vote (e.g. to correct it)" -set sv_vote_majority_factor 0.5 "which quotient of the PLAYERS constitute a majority? (try: 0.666, 0.75 when using the above)" -set sv_vote_simple_majority_factor 0.666 "which quotient of the VOTERS constitute a majority too? (0 = off, otherwise it must be higher than or equal to sv_vote_majority_factor)" -// when disabled, don't allow game type changes "note: set these two equal to JUST support simple majorities" -set sv_vote_override_mostrecent 0 -alias vhelp "cmd vote help" -alias vstatus "cmd vote status" -alias vcall "cmd vote call $*" -alias vstop "cmd vote stop" -alias vmaster "cmd vote master" -alias vlogin "cmd vote login $*" -alias vdo "cmd vote do $*" -alias vyes "cl_cmd vyes" -alias vno "cl_cmd vno" -alias vdontcare "cmd vote dontcare" -alias vabstain "cmd vote abstain" - -alias vmap "vcall gotomap $1" -alias vnextmap "vcall nextmap $1" -alias vkick "vcall kick $1" -alias vkickban "vcall kickban $1" -alias vend "vcall endmatch" -alias vdomap "vdo gotomap $1" -alias vdokick "vdo kick $*" -alias vdokickban "vdo kickban $*" -alias vdoend "vdo endmatch" - -alias lsmaps "cmd lsmaps" // lists all maps on server (for vmap, suggestmap, vnextmap) -alias lsnewmaps "cmd lsnewmaps" // lists all maps on server that do not yet have a record set (race/cts) bind F1 vyes bind F2 vno //used for spectate/observer mode -alias spec "cmd spectate" bind F3 spec // NIX (No Items Xonotic) - at each time, everyone uses the same weapon, @@ -1135,36 +1137,33 @@ set g_campaign 0 set g_campaign_forceteam 0 "Forces the player to a given team in campaign mode, 1 = red, 2 = blue, 3 = yellow, 4 = pink" seta g_campaign_name "xonoticbeta" set g_campaign_skill 0 -set g_campaignxonotic20_index 0 -set g_campaignxonotic25_index 1 alias singleplayer_start "g_campaign_index 0; set scmenu_campaign_goto 0" alias singleplayer_continue "set scmenu_campaign_goto -1" alias singleplayer_levellist "set scmenu_campaign_dump 1; togglemenu; wait; togglemenu" -// Green's fullbright skins -alias cl_fbskin_green "playermodel models/player/erebus.iqm; playerskin 1; color 3 3" -alias cl_fbskin_red "playermodel models/player/erebus.iqm; playerskin 1; color 4 4" -alias cl_fbskin_orange "playermodel models/player/erebus.iqm; playerskin 1; color 14 14" -alias cl_fbskin_off "playermodel models/player/erebus.iqm; playerskin 0" -alias sv_fbskin_green "sv_defaultcharacter 1; sv_defaultplayermodel models/player/erebus.iqm; sv_defaultplayerskin 1; sv_defaultplayercolors 51" -alias sv_fbskin_red "sv_defaultcharacter 1; sv_defaultplayermodel models/player/erebus.iqm; sv_defaultplayerskin 1; sv_defaultplayercolors 68" -alias sv_fbskin_orange "sv_defaultcharacter 1; sv_defaultplayermodel models/player/erebus.iqm; sv_defaultplayerskin 1; sv_defaultplayercolors 238" +// Green's fullbright skins, updated by Samual +alias sv_fbskin_unique "sv_defaultcharacter 1; sv_defaultplayermodel models/player/megaerebus.iqm; sv_defaultplayerskin 1; sv_defaultplayercolors \"\"" +alias sv_fbskin_green "sv_defaultcharacter 1; sv_defaultplayermodel models/player/megaerebus.iqm; sv_defaultplayerskin 1; sv_defaultplayercolors 51" +alias sv_fbskin_red "sv_defaultcharacter 1; sv_defaultplayermodel models/player/megaerebus.iqm; sv_defaultplayerskin 1; sv_defaultplayercolors 68" +alias sv_fbskin_orange "sv_defaultcharacter 1; sv_defaultplayermodel models/player/megaerebus.iqm; sv_defaultplayerskin 1; sv_defaultplayercolors 238" +alias sv_fbskin_rainbow "sv_defaultcharacter 1; sv_defaultplayermodel models/player/megaerebus.iqm; sv_defaultplayerskin 1; sv_defaultplayercolors 95" + alias sv_fbskin_off "sv_defaultcharacter 0; sv_defaultplayerskin 0; sv_defaultplayercolors \"\"" seta sv_servermodelsonly 1 cl_curl_enabled 1 -cl_curl_maxspeed 300 -sv_curl_defaulturl "http://www.xonotic.com/contentdownload/getmap.php?file=" -set sv_curl_serverpackages_auto 0 "automatically add packs with *.serverpackage files to sv_curl_serverpackages" +cl_curl_maxspeed 500 +cl_curl_useragent 1 +cl_curl_useragent_append "$g_xonoticversion" -set sv_motd "" +sv_curl_defaulturl "http://www.xonotic.org/contentdownload/getmap.php?file=" +set sv_curl_serverpackages_auto 1 "automatically add packs with *.serverpackage files to sv_curl_serverpackages" -seta cl_shownames 1 "show player names pointed to (0: never, 1: teamplay only, 2: always)" -set sv_allow_shownames 1 +set sv_motd "" -set g_waypoints_for_items 1 "make waypoints out of items, values: 0 = never, 1 = unless the mapper prevents it by worldspawn.spawnflags & 1, 2 = always" +set g_waypoints_for_items 0 "make waypoints out of items, values: 0 = never, 1 = unless the mapper prevents it by worldspawn.spawnflags & 1, 2 = always" seta g_maplist_votable 6 "number of maps that are shown in the map voting at the end of a match" seta g_maplist_votable_keeptwotime 15 @@ -1174,7 +1173,6 @@ seta g_maplist_votable_suggestions_override_mostrecent 0 seta g_maplist_votable_nodetail 1 "nodetail only shows total count instead of all vote counts per map, so votes don't influence others that much" seta g_maplist_votable_abstain 0 "when 1, you can abstain from your vote" seta g_maplist_votable_screenshot_dir "maps levelshots" "where to look for map screenshots" -alias suggestmap "cmd suggestmap $1" set g_chat_flood_spl 3 "normal chat: seconds between lines to not count as flooding" set g_chat_flood_lmax 2 "normal chat: maximum number of lines per chat message at once" @@ -1192,26 +1190,34 @@ set g_nick_flood_penalty 0.5 "duration of the nick flood penalty" set g_nick_flood_penalty_yellow 3 "number of changes to allow before warning and movement blocking" set g_nick_flood_penalty_red 30 "number of changes to allow before totally disorienting the player" +set sv_waypointsprite_deployed_lifetime 10 +set sv_waypointsprite_deadlifetime 1 +set sv_waypointsprite_limitedrange 5120 + +seta g_waypointsprite_uppercase 1 set g_waypointsprite_normdistance 512 set g_waypointsprite_minscale 0.5 set g_waypointsprite_minalpha 0.4 set g_waypointsprite_distancealphaexponent 2 set g_waypointsprite_timealphaexponent 1 -set g_waypointsprite_deployed_lifetime 10 -set g_waypointsprite_deadlifetime 1 -set g_waypointsprite_limitedrange 5120 set g_waypointsprite_stuffbinds 0 seta g_waypointsprite_scale 1 +seta g_waypointsprite_fontsize 12 seta g_waypointsprite_alpha 1 "This allows the client to control transparency of the waypoint" seta g_waypointsprite_edgefadealpha 0.5 "alpha multiplier near the edge" seta g_waypointsprite_edgefadescale 1 "scale multiplier near the edge" seta g_waypointsprite_edgefadedistance 50 "distance in virtual pixels from edge where to start fading" +seta g_waypointsprite_edgeoffset_bottom 0 "offset of how close the waypoint can be to the bottom edge of the screen" +seta g_waypointsprite_edgeoffset_left 0 "offset of how close the waypoint can be to the left edge of the screen" +seta g_waypointsprite_edgeoffset_right 0 "offset of how close the waypoint can be to the right edge of the screen" +seta g_waypointsprite_edgeoffset_top 0 "offset of how close the waypoint can be to the top edge of the screen" seta g_waypointsprite_crosshairfadealpha 0.25 "alpha multiplier near crosshair" seta g_waypointsprite_crosshairfadescale 1 "scale multiplier near the crosshair" seta g_waypointsprite_crosshairfadedistance 150 "distance in virtual pixels from crosshair where to start fading" seta g_waypointsprite_distancefadealpha 1 "alpha multiplier near distance" seta g_waypointsprite_distancefadescale 0.7 "scale multiplier near the distance" seta g_waypointsprite_distancefadedistancemultiplier 0.5 "distance in map sizes from distance where to stop fading" +set g_waypointsprite_spam 0 "Debugging feature. Set to 10 and load courtfun in race mode to test." alias "g_waypointsprite_personal" "impulse 30" alias "g_waypointsprite_personal_p" "impulse 31" alias "g_waypointsprite_personal_d" "impulse 32" @@ -1224,24 +1230,12 @@ alias "g_waypointsprite_team_danger_p" "impulse 38" alias "g_waypointsprite_team_danger_d" "impulse 39" alias "g_waypointsprite_clear_personal" "impulse 47" alias "g_waypointsprite_clear" "impulse 48" -alias "g_waypointsprite_toggle" "impulse 49" +alias "g_waypointsprite_toggle" "toggle cl_hidewaypoints" // key for that? seta cl_hidewaypoints 0 "disable static waypoints, only show team waypoints" -// command extension -alias qc_cmd "sv_cmd $*" // menu QC will override this to menu_cmd -alias adminmsg "sv_cmd adminmsg $*" -alias teamstatus "cmd teamstatus; sv_cmd teamstatus" // yes, it is broken on listen servers that way, but well, who cares :P -alias printstats "sv_cmd printstats" // print status on demand -alias g_maplist_add "qc_cmd maplist add $*" -alias g_maplist_remove "qc_cmd maplist remove $*" -alias g_maplist_putfirst "qc_cmd maplist remove $* ; qc_cmd maplist add $*" -alias g_maplist_shufflenow "qc_cmd maplist shuffle" -alias g_maplist_cleanup "qc_cmd maplist cleanup" // removes maps that don't exist from the map list -alias gametype "sv_cmd gametype $*" - -alias addfav "qc_cmd addtolist net_slist_favorites $*" -alias addvote "qc_cmd addtolist sv_vote_commands $*" +seta g_waypointsprites_turrets 1 "disable turret waypoints" +seta g_waypointsprites_turrets_maxdist 4000 "max distace for turret sprites" // key hunt set g_keyhunt 0 "Key Hunt: collect all keys from the enemies and bring them together to score" @@ -1250,7 +1244,6 @@ set g_balance_keyhunt_delay_round 5 set g_balance_keyhunt_delay_tracking 10 set g_balance_keyhunt_delay_fadeout 2 set g_balance_keyhunt_delay_collect 1.5 -set g_balance_keyhunt_delay_drop 0.4 set g_balance_keyhunt_maxdist 150 set g_balance_keyhunt_score_collect 3 set g_balance_keyhunt_score_carrierfrag 2 @@ -1267,23 +1260,25 @@ set g_keyhunt_teams 0 // keepaway set g_keepaway 0 "game mode which focuses around a ball, look at g_keepaway_win_mode for further details" -set g_keepaway_bckillscore 1 "enable scoring points (y/n) for ball carrier kills" -set g_keepaway_pointlimit -1 "total amount of points you can get, -1 for unlimited" -set g_keepaway_pointleadlimit -1 "mercy rule, -1 for unlimited" -set g_keepaway_ballcarrier_alpha 0.6 "alpha when the player is the ballcarrier" -set g_keepaway_ballcarrier_highspeed 1.5 "speed multiplier done to the person holding the ball" -set g_keepaway_ballcarrier_damage 1.5 "damage multiplier while having powerup" -set g_keepaway_ballcarrier_force 1.5 "force multiplier while having powerup" -set g_keepaway_ballcarrier_selfdamage 1 "self damage multiplier while having powerup" -set g_keepaway_ballcarrier_selfforce 1.5 "self force multiplier while having powerup" -set g_keepaway_noncarrier_warn 0 "warn players when they kill without holding the ball" -set g_keepaway_noncarrier_damage 0.5 "damage done to other players if both you and they don't have the ball" -set g_keepaway_noncarrier_force 0.5 "force done to other players if both you and they don't have the ball" +set g_keepaway_score_bckill 1 "enable scoring points (y/n) for ball carrier kills (value is how many points to award)" +set g_keepaway_score_killac 1 "amount of points to give when you kill someone while you have the ball" +set g_keepaway_score_timeinterval 1 "amount of time it takes between intervals for timepoints to be added to the score" +set g_keepaway_score_timepoints 0 "points to add to score per timeinterval, 0 for no points" +set g_keepaway_ballcarrier_effects 8 "Add together the numbers you want: EF_ADDITIVE (32) / EF_NODEPTHTEST (8192) / EF_DIMLIGHT (8)" +set g_keepaway_ballcarrier_highspeed 1 "speed multiplier done to the person holding the ball (recommended when used with some mutators)" +set g_keepaway_ballcarrier_damage 1 "damage multiplier while holding the ball" +set g_keepaway_ballcarrier_force 1 "force multiplier while holding the ball" +set g_keepaway_ballcarrier_selfdamage 1 "self damage multiplier while holding the ball" +set g_keepaway_ballcarrier_selfforce 1 "self force multiplier while holding the ball" +set g_keepaway_noncarrier_warn 1 "warn players when they kill without holding the ball" +set g_keepaway_noncarrier_damage 1 "damage done to other players if both you and they don't have the ball" +set g_keepaway_noncarrier_force 1 "force done to other players if both you and they don't have the ball" set g_keepaway_noncarrier_selfdamage 1 "self damage if you don't have the ball" set g_keepaway_noncarrier_selfforce 1 "self force if you don't have the ball" +set g_keepawayball_effects 0 "Add together the numbers you want: EF_ADDITIVE (32) / EF_NODEPTHTEST (8192) / EF_DIMLIGHT (8)" set g_keepawayball_trail_color 254 "particle trail color from player/ball" -set g_keepawayball_damageforcescale 2 "Scale of force which is applied to the ball by weapons/explosions/etc" -set g_keepawayball_respawntime 15 "if no one picks up the ball, how long to wait until the ball respawns" +set g_keepawayball_damageforcescale 3 "Scale of force which is applied to the ball by weapons/explosions/etc" +set g_keepawayball_respawntime 10 "if no one picks up the ball, how long to wait until the ball respawns" seta g_keepaway_teams_override 0 set g_keepaway_teams 0 @@ -1294,23 +1289,9 @@ set g_ban_default_bantime 5400 "90 minutes" set g_ban_default_masksize 3 "masksize 0 means banning by UID only, 1 means banning by /8 (IPv6: /32) network, 2 means banning by /16 (IPv6: /48) network, 3 means banning by /24 (IPv6: /56) network, 4 means banning by single IP (IPv6: /64 network)" set g_banned_list "" "format: IP remainingtime IP remainingtime ..." set g_banned_list_idmode "1" "when set, the IP banning system always uses the ID over the IP address (so a user in a banned IP range can connect if they have a valid signed ID)" -alias bans "sv_cmd bans" -alias ban "sv_cmd ban $*" // usage: ban address(maybe incomplete, like 1.2.3) bantime(seconds) -alias kickban "sv_cmd kickban $*" // usage: kickban # playerno bantime(seconds) masksize(bytes) -alias unban "sv_cmd unban $*" // usage: unban 3 (number from bans) r_labelsprites_scale 0.40625 // labels sprites get displayed at 0.5x from 640x480 to 1280x1024, and at 1x from 1600x1200 onwards -// settemp subsystem. Do not touch. Usage: settemp variable value, next map resets it. -set settemp_list 0 -set settemp_idx 0 -set _settemp_var UNUSED -alias settemp "_settemp_var \"_settemp_x$settemp_idx\"; qc_cmd rpn /settemp_idx settemp_idx 1 add def; _settemp \"$1\" \"$2\"" -alias _settemp "settemp_list \"1 $1 $_settemp_var $settemp_list\"; set $_settemp_var \"${$1}\"; $1 \"$2\"" -alias settemp_restore "_settemp_restore_${settemp_list asis}" -alias _settemp_restore_0 "set settemp_var 0; set settemp_list 0" -alias _settemp_restore_1 "$1 \"${$2}\"; _settemp_restore_${3- asis}" - // usercommands. These can be edited and bound by the menu. seta "userbind1_press" "say_team quad soon"; seta "userbind1_release" ""; seta "userbind1_description" "team: quad soon" seta "userbind2_press" "say_team free item %x^7 (l:%y^7); g_waypointsprite_team_here_p"; seta "userbind2_release" ""; seta "userbind2_description" "team: free item, icon" @@ -1326,6 +1307,7 @@ seta "userbind11_press" "say_team attacking (l:%l^7) (h:%h^7 a:%a^7 w:%w^7); g_w seta "userbind12_press" "say_team killed flagcarrier (l:%y^7); g_waypointsprite_team_p"; seta "userbind12_release" ""; seta "userbind12_description" "team: killed flag, icon" seta "userbind13_press" "say_team dropped flag (l:%d^7); g_waypointsprite_team_here_d"; seta "userbind13_release" ""; seta "userbind13_description" "team: dropped flag, icon" seta "userbind14_press" "say_team dropped gun %w^7 (l:%l^7); g_waypointsprite_team_here; wait; dropweapon"; seta "userbind14_release" ""; seta "userbind14_description" "team: drop gun, icon" +// TODO change this to "use" once we can seta "userbind15_press" "say_team dropped flag/key %w^7 (l:%l^7); g_waypointsprite_team_here; wait; +use"; seta "userbind15_release" "-use"; seta "userbind15_description" "team: drop flag/key, icon" seta "userbind16_press" "say :-) / nice one"; seta "userbind16_release" ""; seta "userbind16_description" "chat: nice one" seta "userbind17_press" "say good game"; seta "userbind17_release" ""; seta "userbind17_description" "chat: good game" @@ -1349,11 +1331,13 @@ alias +userbind "_userbind_call userbind${1}_press" alias -userbind "_userbind_call userbind${1}_release" // we must change its default from 1.0 to 1 to be consistent with menuqc -seta slowmo 1 +set slowmo 1 seta menu_skin "luminos" set menu_slowmo 1 seta menu_sounds 0 "enables menu sound effects. 1 enables click sounds, 2 also enables hover sounds" +seta menu_tooltips 1 "menu tooltips: 0 disabled, 1 enabled, 2 also shows cvar or console command (when available) changed or executed by the item" +set menu_picmip_bypass 0 "bypass texture quality enforcement based on system resources, not recommended and may cause crashes!" r_textbrightness 0.2 r_textcontrast 0.8 @@ -1369,66 +1353,8 @@ con_chatwidth 0.6 con_notifysize 10 con_notifyalign 0 -// hud variables -set _hud_configure 0 "1 = configure the HUD" -seta hud_configure_teamcolorforced 0 "1 = force display of team colors in configure mode" -seta hud_configure_checkcollisions 1 "check for collisions against other panels when in hud configure mode" -seta hud_configure_bg_minalpha 0.25 "minimum panel background alpha when in hud configure mode" -seta hud_configure_grid_alpha 0.15 "alpha for visible grid when in configure mode" - seta sbar_info_pos 0 "Y-axis distance from lower right corner for engine info prints" -// user preference cvars (i.e. shouldn't be adjusted by a skin config) -seta hud_panel_weapons_label 1 "1 = show number of weapon, 2 = show bound key of weapon" -seta hud_panel_weapons_complainbubble_time 1 "time that a new entry stays until it fades out" -seta hud_panel_weapons_complainbubble_fadetime 0.25 "fade out time" -seta hud_panel_weapons_accuracy 1 "show accuracy color as the weapon icon background; colors can be configured with accuracy_color* cvars" -seta hud_panel_weapons_ammo 1 "show ammo as a status bar" -seta hud_panel_weapons_ammo_full_shells 50 "show 100% of the status bar at this ammo count" -seta hud_panel_weapons_ammo_full_nails 200 "show 100% of the status bar at this ammo count" -seta hud_panel_weapons_ammo_full_cells 80 "show 100% of the status bar at this ammo count" -seta hud_panel_weapons_ammo_full_rockets 80 "show 100% of the status bar at this ammo count" -seta hud_panel_weapons_ammo_full_fuel 100 "show 100% of the status bar at this ammo count" - -seta hud_panel_ammo_maxammo "40" "when you have this much ammo, the ammo status bar is full" - -seta hud_panel_healtharmor_maxhealth "250" "when you have this much health, the health status bar is full" -seta hud_panel_healtharmor_maxarmor "150" "when you have this much armor, the armor status bar is full" - -seta hud_panel_notify_time 10 "time that a new entry stays until it fades out" -seta hud_panel_notify_fadetime 3 "fade out time" - -seta hud_panel_timer_increment 0 "show elapsed time instead of remaining time" - -seta hud_panel_radar_scale 4096 "distance you can see on the team radar" -seta hud_panel_radar_rotation 0 "rotation mode: you set what points up. 0 = player, 1 = west, 2 = south, 3 = east, 4 = north" -seta hud_panel_radar_zoommode 0 "zoom mode: 0 = zoomed by default, 1 = zoomed when +zoom, 2 = always zoomed, 3 = always zoomed out" -alias hud_panel_radar_rotate "toggle hud_panel_radar_rotation 0 1 2 3 4" - -seta hud_panel_engineinfo_framecounter_time 0.1 "time between framerate display updates" -seta hud_panel_engineinfo_framecounter_decimals 0 "amount of decimals to show" -seta hud_panel_engineinfo_framecounter_exponentialmovingaverage 1 "use an averaging method for calculating fps instead of counting frametime like engine does" -seta hud_panel_engineinfo_framecounter_exponentialmovingaverage_new_weight 0.1 "weight of latest data point" -seta hud_panel_engineinfo_framecounter_exponentialmovingaverage_instantupdate_change_threshold 0.5 "threshold for fps change when to update instantly, to make big fps changes update faster" - -seta hud_showbinds 1 "the way to show the keys to press in HUD messages: 0 displays commands, 1 bound keys, 2 both" -seta hud_showbinds_limit 2 "maximum number of bound keys to show for a command. 0 for unlimited" - -seta hud_colorflash_alpha 0.5 "starting alpha of the color flash" - -seta hud_damage 1 "an improved version of gl_polyblend, draw an image instead when hurt" -seta hud_damage_gentle_alpha_multiplier 0.25 "how much to multiply alpha of flash when using the cl_gentle version, it's much more opaque than the non-gentle version" -seta hud_damage_gentle_color "1 0.7 1" "color of flash for cl_gentle version" -seta hud_damage_color "1 0 0" "color of flash" -seta hud_damage_factor 0.025 "(damage * factor) = how much to add to the alpha value" -seta hud_damage_fade_rate 1 "how much to subtract from the alpha value each second" -seta hud_damage_maxalpha 2 "how much to limit the alpha value to" -seta hud_damage_pain_threshold 0.1 "how much alpha to ignore (must be bigger than the hud_damage_factor so that e.g. rot is ignored)" -seta hud_damage_pain_threshold_lower 1.25 "how much we lower pain_threshold with when nearing 0 health (if pain_threshold gets negative then we always draw a flash at alpha = fabs(pain_threshold)" -seta hud_damage_pain_threshold_lower_health 50 "at which health we start lowering pain_threshold" -seta hud_damage_pain_threshold_pulsating_min 0.6 "minimum value when calculating the pulse: max(pulsating_min, fabs(sin(PI * time / period))" -seta hud_damage_pain_threshold_pulsating_period 0.8 "one pulse every X seconds" - // scoreboard seta scoreboard_columns default seta scoreboard_border_thickness 1 "scoreboard border thickness" @@ -1448,8 +1374,9 @@ seta scoreboard_fadeoutspeed 5 "speed at which scoreboard fades out, higher is f seta scoreboard_highlight 1 "enable highlighting for rows and columns in the scoreboard" seta scoreboard_highlight_alpha 0.10 "highlight alpha value (depends on hud_scoreboard_highlight 1)" seta scoreboard_highlight_alpha_self 0.25 "self highlight alpha value" -seta scoreboard_offset_left 0.04 "how many pixels the scoreboard is offset from the left screen edge" -seta scoreboard_offset_right 0.148 "how many pixels the scoreboard is offset from the right screen edge" +seta scoreboard_offset_left 0.15 "how far (by percent) the scoreboard is offset from the left screen edge" +seta scoreboard_offset_right 0.15 "how far (by percent) the scoreboard is offset from the right screen edge" +seta scoreboard_offset_vertical 0.05 "how far (by percent) the scoreboard is offset from the top and bottom of the screen" seta scoreboard_bg_scale 0.25 "scale for the tiled scoreboard background" seta accuracy_color_levels "0 20 100" "accuracy values at which a specified color (accuracy_color) will be used. If your accuracy is between 2 of these values then a mix of the Xth and X+1th colors will be used. You can specify up to 10 values, in increasing order" @@ -1460,26 +1387,18 @@ seta accuracy_color2 "0 1 0" // for menu server list (eventually make them have engine support?) seta menu_slist_showfull 1 "show servers even if they are full and have no slots to join" seta menu_slist_showempty 1 "show servers even if they are no empty and have no opponents to play against" -set menu_slist_modfilter "=" // set to either: !modname or modname. modname of = means "same as we are running now". +seta menu_slist_modfilter "" // set to either: !modname or modname. modname of = means "same as we are running now". // for menu weapon arena set menu_weaponarena_with_laser 0 "also enable the Laser in this weapon arena" seta menu_maxplayers 16 "maxplayers value when the menu starts a game" -// command executed before loading a map by the menu -// makes sure maxplayers is at least minplayers or bot_number + 1 -alias _menu_loadmap_prepare_maxpl "maxplayers $_menu_loadmap_maxplayers" -alias menu_loadmap_prepare "disconnect; wait; g_campaign 0; menu_cmd rpn /_menu_loadmap_maxplayers menu_maxplayers minplayers bot_number 1 add max max def; _menu_loadmap_prepare_maxpl; g_maplist_shufflenow" - // useful vote aliases set timelimit_increment 5 set timelimit_decrement 5 set timelimit_min 5 set timelimit_max 60 -alias extendmatchtime "sv_cmd rpn /timelimit timelimit timelimit_max timelimit timelimit_increment add bound def" -alias reducematchtime "sv_cmd rpn /timelimit timelimit timelimit_decrement sub timelimit_min timelimit bound def" -alias endmatch "timelimit -1" // useful keybind to maximize the chat area temporarily // HUD code takes care of many of these now... @@ -1521,14 +1440,17 @@ set con_completion_playermodel models/player/*.iqm seta cl_port $cl_port seta r_showsurfaces $r_showsurfaces seta r_ambient $r_ambient -seta skill $skill +seta skill 4 seta gl_finish $gl_finish seta v_kicktime $v_kicktime seta r_subdivisions_tolerance $r_subdivisions_tolerance +seta vid_gl20 $vid_gl20 +seta vid_gl13 $vid_gl13 // ticrate -sys_ticrate 0.0166667 -cl_netfps 60 // should match +//sys_ticrate 0.0166667 +sys_ticrate 0.0333333 +cl_netfps 60 // should match or be a multiple sv_gameplayfix_delayprojectiles 0 sv_gameplayfix_q2airaccelerate 1 sv_gameplayfix_stepmultipletimes 1 @@ -1548,7 +1470,7 @@ gl_texturecompression_lightcubemaps 1 gl_texturecompression_q3bsplightmaps 0 gl_texturecompression_sky 1 -set menu_mouse_absolute 0 "TODO make this seta if the engine understands this right" +seta menu_mouse_absolute 1 "use the OS mouse pointer motion for menu" seta menu_mouse_speed 1 "speed multiplier for the mouse in the menu (does not affect in-game aiming)" set menu_use_default_hostname 1 alias sethostname "set menu_use_default_hostname 0; hostname $*" @@ -1581,31 +1503,23 @@ set sv_maxidle_spectatorsareidle 0 // CTF capture limit placeholder cvar set capturelimit 0 -// hud: font size -seta hud_fontsize 11 -seta scr_centersize 12 -seta hud_width 560 -// alias hud_font "loadfont user1 ${1},gfx/fallback ${2-}; loadfont user2 ${1}-big ${2-}; scoreboard_columns_set" -alias sbar_font "set _requested_sbar_font \"${*}\"" -sbar_font gfx/vera-sans 8 12 16 24 32 - // these entities are not referenced by anything directly, they just represent // teams and are found by find() when needed prvm_leaktest_ignore_classnames "ctf_team dom_team tdm_team" +prvm_backtraceforwarnings 1 sv_allowdownloads_inarchive 1 // for csprogs.dat +sv_allowdownloads 0 // download protocol is evil set g_jump_grunt 0 "Do you make a grunting noise every time you jump? Is it the same grunting noise every time?" -alias allready "sv_cmd allready" - -seta cl_weaponpriority "minstanex rocketlauncher nex minelayer grenadelauncher fireball hlac hagar seeker crylink campingrifle uzi electro tuba shotgun laser hook porto" "weapon priority list" +seta cl_weaponpriority "minstanex nex fireball grenadelauncher uzi hagar rifle electro rocketlauncher crylink minelayer shotgun hlac tuba laser porto seeker hook" "weapon priority list" seta cl_weaponpriority_useforcycling 0 "when set, weapon cycling by the mouse wheel makes use of the weapon priority list (the special value 2 uses the weapon ID list for cycling)" seta cl_weaponpriority0 "rocketlauncher grenadelauncher hagar seeker fireball" "use impulse 200 for prev gun from this list, 210 for best gun, 220 for next gun. Default value: explosives" seta cl_weaponpriority1 "minstanex nex crylink hlac electro laser" "use impulse 201 for prev gun from this list, 211 for best gun, 221 for next gun. Default value: energy" -seta cl_weaponpriority2 "minstanex nex campingrifle" "use impulse 202 for prev gun from this list, 212 for best gun, 222 for next gun. Default value: hitscan exact" -seta cl_weaponpriority3 "minstanex nex campingrifle uzi shotgun" "use impulse 203 for prev gun from this list, 213 for best gun, 223 for next gun. Default value: hitscan all" -seta cl_weaponpriority4 "minelayer grenadelauncher hlac hagar crylink seeker shotgun" "use impulse 204 for prev gun from this list, 214 for best gun, 224 for next gun. Default value: spam weapons" +seta cl_weaponpriority2 "minstanex nex rifle" "use impulse 202 for prev gun from this list, 212 for best gun, 222 for next gun. Default value: hitscan exact" +seta cl_weaponpriority3 "minstanex nex rifle uzi shotgun" "use impulse 203 for prev gun from this list, 213 for best gun, 223 for next gun. Default value: hitscan all" +seta cl_weaponpriority4 "grenadelauncher minelayer hlac hagar crylink seeker shotgun" "use impulse 204 for prev gun from this list, 214 for best gun, 224 for next gun. Default value: spam weapons" seta cl_weaponpriority5 "laser hook porto" "use impulse 205 for prev gun from this list, 215 for best gun, 225 for next gun. Default value: weapons for moving" seta cl_weaponpriority6 "" "use impulse 206 for prev gun from this list, 216 for best gun, 226 for next gun" seta cl_weaponpriority7 "" "use impulse 207 for prev gun from this list, 217 for best gun, 227 for next gun" @@ -1613,19 +1527,9 @@ seta cl_weaponpriority8 "" "use impulse 208 for prev gun from this list, 218 for seta cl_weaponpriority9 "" "use impulse 209 for prev gun from this list, 219 for best gun, 229 for next gun" seta cl_weaponimpulsemode 0 "0: only cycle between currently usable weapons in weapon priority order; 1: cycle between all possible weapons on a key in weapon priority order" -seta sv_status_privacy 1 "hide IP addresses from \"status\" replies shown to clients" - set g_maplist_allow_hidden 0 "allow hidden maps to be, e.g., voted for and in the maplist" set g_maplist_allow_frustrating 0 "allow impossible maps to be, e.g., voted for and in the maplist (if set to 2, ONLY impossible maps are allowed)" -if_client set g_start_delay 0 "delay before the game starts, so everyone can join; recommended to set this to like 15 on a public server" -if_dedicated set g_start_delay 15 "delay before the game starts, so everyone can join; recommended to set this to like 15 on a public server" - -alias ons_map "cl_cmd radar" // legacy alias -alias radar "cl_cmd radar" -alias scoreboard_columns_set "" // aliased later -alias scoreboard_columns_help "cl_cmd scoreboard_columns_help $*" - alias _gl_flashblend_update_00 "gl_flashblend 1" alias _gl_flashblend_update_10 "gl_flashblend 0" alias _gl_flashblend_update_01 "gl_flashblend 0" @@ -1634,13 +1538,14 @@ alias gl_flashblend_update "_gl_flashblend_update_$r_shadow_realtime_dlight$r_sh set sv_clones 0 "number of clones a player may make (reset by the \"kill\" command)" -set cl_handicap 1 "the higher, the more damage you will receive (client setting)" +set cl_handicap 1 "the higher, the more damage you will receive (client setting) NOTE: reconnect or use sendcvar command to update the choice." + +seta cl_clippedspectating 1 "movement collision for spectators so that you can't pass through walls and such. (client setting) NOTE: reconnect or use sendcvar command to update the choice." + +seta cl_autoscreenshot 1 "Take a screenshot upon the end of a match... 0 = Disable completely, 1 = Allow sv_autoscreenshot to take a screenshot when requested, 2 = Always take an autoscreenshot anyway." // must be at the bottom of this file: // alias for switching the teamselect menu -alias menu_showteamselect "menu_cmd directmenu TeamSelect" -alias menu_showhudexit "menu_cmd directmenu HUDExit" -alias menu_showhudoptions "menu_cmd directpanelhudmenu $*" bind f5 menu_showteamselect set g_bugrigs 0 @@ -1673,10 +1578,6 @@ set g_ban_sync_trusted_servers_verify 0 "when set to 1, additional bans sent by set g_showweaponspawns 1 "display sprites for weapon spawns found on the map when a weapon key is pressed and the weapon is not available" -alias records "cmd records" -alias rankings "cmd rankings" -alias ladder "cmd ladder" - // ballistics use physical units, but qu based // Quake-Newton: 1 qN = 1 qu * 1 g / 1 s^2 // Quake-Joule: 1 qJ = 1 qN * 1 qu @@ -1722,7 +1623,7 @@ set camera_speed_roll 0.9 "Camera rotation speed" set camera_speed_chase 4 "Camera movement speed on the x/y/z axis while chasing the player" set camera_speed_free 8 "Camera movement speed on the x/y/z axis in free mode" set camera_speed_attenuation 10 "Camera movements attenuation factor. Bigger is smoother. Applies to mouse movements" -set camera_mouse_treshold 0.5 "Use to ignore small mouse movements. This allows for smoother camera control" +set camera_mouse_threshold 0.5 "Use to ignore small mouse movements. This allows for smoother camera control" set camera_chase_smoothly 0 "Attenuate player movements (only in chase mode)" set camera_look_player 0 "Always look to the player. Mouse input is ignored in this mode" set camera_look_attenuation 8 "Attenuation of \"looking\" movements, only if camera_look_player is set. Bigger is smoother" @@ -1735,28 +1636,14 @@ seta cl_gentle_gibs 0 "client side gentle mode (only replaces gibs); when set t seta cl_gentle_messages 0 "client side gentle mode (only replaces frag messages/centerprints)" seta cl_gentle_damage 0 "client side gentle mode (only replaces damage flash); when set to 1, a white flash replaces the blood image, when set to 2, a randomily colored flash is used instead" -seta cl_racetimer_position 0.25 "Y-axis positioning of the race timer (from 0 to 1)" -seta cl_showpressedkeys 0 "Show which movement keys someone is pressing: 1 for spectating, 2 for always" -seta cl_showpressedkeys_position "0.5 0.8" "1 0 would be upper right corner, 0.5 0.5 the center" - -seta cl_showspeed 0 "show the XY speed of the player" -seta cl_showspeed_unit 0 "unit selection (0 = qu/s (no postfix), 1 = qu/s, 2 = m/s, 3 = km/h, 4 = mph, 5 = knots)" -seta cl_showspeed_z 0 "include the speed on the Z-axis" -seta cl_showspeed_size 30 "size of the numbers" -seta cl_showspeed_position 0.7 "Y-axis positioning of the numbers" - -seta cl_showacceleration 0 "show the XY acceleration of the player" -seta cl_showacceleration_z 0 "include the speed on the Z-axis" -seta cl_showacceleration_size 40 "height of the bar" -seta cl_showacceleration_scale 1 "X-axis scale of the bar" -seta cl_showacceleration_alpha 0.5 "alpha of the bar" -seta cl_showacceleration_color_custom 0 "0 = dynamic color depending on acceleration, 1 = use custom color" -seta cl_showacceleration_color "1 0 0" "color of the bar, needs cl_showacceleration_color_custom to be 1" -seta cl_showacceleration_position 0.6 "Y-axis positioning of the bar" - set g_jetpack 0 "Jetpack mutator (uses the hook's button, can't coexist with the offhand hook, but only with the onhand one)" set g_running_guns 0 "... or wonder, till it drives you mad, what would have followed if you had." +set g_bastet 0 "don't try" +set g_loituma 0 "no, really" + +set _urllib_nextslot 0 "temp variable" +set cl_warpzone_usetrace 1 "do not touch" set cl_effects_lightningarc_simple 0 set cl_effects_lightningarc_segmentlength 64 @@ -1767,24 +1654,12 @@ set cl_effects_lightningarc_branchfactor_add 0.1 set g_hitplots 0 "when set to 1, hitplots are stored by the server to provide a means of proving that a triggerbot was used" seta g_hitplots_individuals "" "the individuals, by IP, that should have their hitplots recorded" -alias g_hitplots_add "qc_cmd rpn /g_hitplots_individuals g_hitplots_individuals $1 union def" -alias g_hitplots_remove "qc_cmd rpn /g_hitplots_individuals g_hitplots_individuals $1 difference def" - -alias mute "prvm_edictset server $1 muted 1" // I am lazy and not making an actual command of this -alias unmute "prvm_edictset server $1 muted 0" // dito - -rcon_secure 1 set menu_updatecheck 1 set bot_navigation_ignoreplayers 0 // FIXME remove this once the issue is solved set bot_sound_monopoly 0 "when enabled, only bots can make any noise" -// broken, sorry (cannot handle weapon attachment properly) -//seta cl_forceplayermodels 0 "force all players to look like you; WARNING: animations can look very bad with this" -//seta cl_forceplayermodelsfromxonotic 0 "force models coming from xonotic; WARNING: animations can look very bad with this" -//set sv_clforceplayermodels 1 "allow clients to use cl_forcemodels" - set sv_loddistance1 1024 set sv_loddistance2 4096 seta cl_playerdetailreduction 0 "the higher, the less detailed player models are displayed (LOD)" @@ -1811,6 +1686,7 @@ alias cl_hook_gamestart_rc alias cl_hook_gamestart_nexball alias cl_hook_gamestart_cts alias cl_hook_gamestart_ka +alias cl_hook_gamestart_freezetag alias cl_hook_gameend alias cl_hook_activeweapon @@ -1832,6 +1708,7 @@ alias sv_hook_gamestart_rc alias sv_hook_gamestart_nexball alias sv_hook_gamestart_cts alias sv_hook_gamestart_ka +alias sv_hook_gamestart_freezetag alias sv_hook_gamerestart alias sv_hook_gameend @@ -1841,7 +1718,7 @@ seta cl_vehicle_spiderbot_cross_alpha 0.6 seta cl_vehicle_spiderbot_cross_size 1 //cl_gunalign calculator -seta menu_cl_gunalign 3 "Gun alignment; 1 = right, 2 = left, 3 = center or right, 4 = center or left" +seta menu_cl_gunalign 3 "Gun alignment; 1 = center (if allowed by g_shootfromclient) or right, 2 = center (if allowed by g_shootfromclient) or left, 3 = right only, 4 = left only" alias _gunalign_01 "cl_gunalign 1" alias _gunalign_02 "cl_gunalign 2" alias _gunalign_03 "cl_gunalign 3" @@ -1858,12 +1735,12 @@ set g_triggerimpulse_accel_power 1 "trigger_impulse accelerator power (applied B set g_triggerimpulse_accel_multiplier 1 "trigger_impulse accelerator multiplier (applied AFTER the power)" set g_triggerimpulse_directional_multiplier 1 "trigger_impulse directional field multiplier" set g_triggerimpulse_radial_multiplier 1 "trigger_impulse radial field multiplier" +set the_goggles "they do nothing" "but the googles, they do" -seta g_ghost_items 1 "enable ghosted items (when between 0 and 1, overrides the alpha value)" -seta g_ghost_items_color "-1 -1 -1" "color of ghosted items, 0 0 0 leaves the color unchanged" +set g_ghost_items 1 "enable ghosted items (when between 0 and 1, overrides the alpha value)" +set g_ghost_items_color "-1 -1 -1" "color of ghosted items, 0 0 0 leaves the color unchanged" -set sv_weaponstats_damagefile "" "when set to a file name, per-weapon damage stats get written to that file" -set sv_weaponstats_killfile "" "when set to a file name, per-weapon kill stats get written to that file" +set sv_weaponstats_file "" "when set to a file name, per-weapon stats get written to that file" seta cl_noantilag 0 "turn this on if you believe antilag is bad" @@ -1873,7 +1750,7 @@ set sv_pitch_fixyaw 0 "workaround to fix the aiming direction on stupidly made p set rescan_pending 0 "set to 1 to schedule a fs_rescan at the end of this match" -seta g_mapinfo_allow_unsupported_modes_and_let_stuff_break "0" "set to 1 to be able to force game types using g_ cvars even if the map does not support them" +set g_mapinfo_allow_unsupported_modes_and_let_stuff_break "0" "set to 1 to be able to force game types using g_ cvars even if the map does not support them" // weapon accuracy stats set sv_accuracy_data_share 1 "1 send weapon accuracy data statistics to spectating clients, depends on cl_accuracy_data_share" @@ -1891,6 +1768,14 @@ set speedmeter 0 "print landing speeds" set developer_shtest 0 "experimental speedhack detection" set waypoint_benchmark 0 "quit after waypoint loading to benchmark bot navigation code" set g_debug_bot_commands 0 "print scripted bot commands before executing" +set g_debug_defaultsounds 0 "always use default sounds" +set sv_use_csqc_players 1 "set to 0 to disable CSQC players for better Xonotic 0.5 compat" +set cl_precacheplayermodels 0 "TODO please check if this needs to be 1 or if precaching a model the server already requested is fast enough to do it at runtime" +seta cl_forceplayermodels 0 "make everyone look like your own model (requires server to have sv_use_csqc_players 1 and sv_defaultcharacter 0)" +seta cl_forceplayercolors 0 "make everyone look like your own color (requires server to have sv_use_csqc_players 1 and sv_defaultcharacter 0, and is ignored in teamplay)" +seta cl_forcemyplayermodel "" "set to the model file name you want to show yourself as (requires server to have sv_use_csqc_players 1; does not affect how enemies look with cl_forceplayermodels)" +seta cl_forcemyplayerskin 0 "set to the skin number you want to show yourself as (requires server to have sv_use_csqc_players 1; does not affect how enemies look with cl_forceplayermodels)" +seta cl_forcemyplayercolors 0 "set to the color value (encoding is same as _cl_color) for your own player model (requires server to have sv_use_csqc_players 1, and is ignored in teamplay; does not affect how enemies look with cl_forceplayermodels)" // debug cvars for keyhunt attaching set _angles "0 0 0" @@ -1900,6 +1785,10 @@ set _origin "0 0 0" set _campaign_index "" set _campaign_name "" +// debug +set _independent_players 0 "DO NOT TOUCH" +set _notarget 0 "NO, REALLY, DON'T" + // define some engine cvars that we need even on dedicated server set r_showbboxes 0 @@ -1910,16 +1799,15 @@ collision_endposnudge 1 set cl_lerpanim_maxdelta_framegroups 0.05 // must be faster than fastest weapon refire set cl_lerpanim_maxdelta_server 0.1 // must be slower than slowest server controlled anim (e.g. animinfo stuff) -// FIXME workaround for engine bug -sv_gameplayfix_nudgeoutofsolid 0 -// to div0: remove this once 5b7ac1706712977bbc0297d2d53294e73574c7cd (svn r9537) is in the stable branch of the engine again - // otherwise, antilag breaks sv_gameplayfix_consistentplayerprethink 1 // support Q1BSP maps mod_q1bsp_polygoncollisions 1 +// match q3map2 +mod_obj_orientation 0 + // improve some minor details sv_gameplayfix_gravityunaffectedbyticrate 1 sv_gameplayfix_nogravityonground 1 @@ -1954,7 +1842,7 @@ set g_weaponreplace_porto "" set g_weaponreplace_minstanex "" set g_weaponreplace_hook "" set g_weaponreplace_hlac "" -set g_weaponreplace_campingrifle "" +set g_weaponreplace_rifle "" set g_weaponreplace_tuba "" set g_weaponreplace_fireball "" set g_weaponreplace_seeker "" @@ -1977,14 +1865,14 @@ scr_conscroll3_y 0 scr_conscroll_x -0.1 scr_conscroll_y -0.3 -scr_loadingscreen_background 0 -scr_loadingscreen_barcolor "0 0.5 1" -scr_loadingscreen_barheight 20 -scr_loadingscreen_count 1 scr_conforcewhiledisconnected 0 +scr_infobar_height 12 // DP cannot properly detect this, so rather turn off the detection -r_texture_dds_load_dxt1_noalpha 1 +r_texture_dds_load_alphamode 2 +r_texture_dds_swdecode 1 // SW decode to quarter res if we want to load DDS but don't support the extension for it +r_texture_dds_load_logfailure 0 // this engine feature SUCKS +set vid_netwmfullscreen 0 // doesn't support non-native res // particles optimization r_drawparticles_nearclip_min 8 @@ -1995,10 +1883,11 @@ sv_cullentities_trace 1 r_cullentities_trace 0 // less "lagging" of other players, but also less PL tolerant... let's try this -sv_clmovement_inputtimeout 0.05 +sv_clmovement_inputtimeout 0.07 // more than 2, less than 3 server frames // exact gloss looks better, e.g. on g-23 r_shadow_glossexact 1 +r_shadow_glossintensity 1 // use fake light if map has no lightmaps r_fakelight 1 @@ -2016,7 +1905,7 @@ utf8_enable 1 // safe font defaults r_font_hinting 1 r_font_disable_freetype 0 -r_font_size_snapping 2 +r_font_size_snapping 4 // database management set sv_db_saveasdump 0 "write server.db in dump format (loads slower, easier to read/parse)" @@ -2024,6 +1913,8 @@ set cl_db_saveasdump 0 "write client.db in dump format (loads slower, easier to // uid2name seta cl_allow_uid2name -1 "-1 = ask if the player wants to disable/enable this feature, 0 = disable, 1 = enable uid2name (allows showing your name in race rankings for instance)" +seta cl_allow_uidtracking 1 "-1 = ask if the player wants to disable/enable this feature, 0 = disable, 1 = enable uid tracking (allows associating your data with your player ID)" +// FIXME set to -1 before release, once we have a dialog for this! // polygonoffset for submodel SUCKS SUCKS SUCKS (only a hack for quake1, we don't need that) r_polygonoffset_submodel_offset 0 @@ -2046,6 +1937,11 @@ set g_forced_team_yellow "" "list of player IDs for yellow team" set g_forced_team_pink "" "list of player IDs for pink team" set g_forced_team_otherwise "default" "action if a non listed player joins (can be default for default action, spectate for forcing to spectate, or red, blue, yellow, pink)" +// nice alias to set up a match +// example: g_forced_team_matchsetup stormkeep "mzDo0nO2y3XpFPNbQAyeUucyaejZ9xpiXLYMGU2x3qM=" "BRLOGENSHFEGLE/+Mq3x2UGMYLXipx9ZjeaycuUeyAQ=" +// will set up a match on stormkeep where mzDo0nO2y3XpFPNbQAyeUucyaejZ9xpiXLYMGU2x3qM= and BRLOGENSHFEGLE/+Mq3x2UGMYLXipx9ZjeaycuUeyAQ= play against each other +alias g_forced_team_matchsetup "map $1; settemp g_forced_team_red \"$2\"; settemp g_forced_team_blue \"$3\"; settemp g_forced_team_yellow \"$4\"; settemp g_forced_team_pink \"$5\"; settemp g_forced_team_otherwise spectate" + // random charge stuff :P set g_weapon_charge_colormod_hdrmultiplier 4 "how much to multiply the colors by in the colormod vector" set g_weapon_charge_colormod_red_half 0 @@ -2057,29 +1953,63 @@ set g_weapon_charge_colormod_blue_full -1 // player statistics server URI set g_playerstats_uri "" +set g_playerstats_debug 0 "when 1, player stats are dumped to the console too" + +// session locking +locksession 1 // create this cvar in case the engine did not set snd_soundradius 1200 +set snd_softclip 1 +set snd_maxchannelvolume 0 +set snd_streaming_length 2 +seta menu_snd_attenuation_method 1 "Use exponential instead of linear falloff for sound attenuation" +alias snd_attenuation_method_0 "set menu_snd_attenuation_method 0; set snd_soundradius 1200; set snd_attenuation_exponent 1; set snd_attenuation_decibel 0" // Quake default +alias snd_attenuation_method_1 "set menu_snd_attenuation_method 1; set snd_soundradius 2400; set snd_attenuation_exponent 4; set snd_attenuation_decibel 0" // nice approximation for method 2 +alias snd_attenuation_method_2 "set menu_snd_attenuation_method 2; set snd_soundradius 1200; set snd_attenuation_exponent 0; set snd_attenuation_decibel 10" // warning: plays sounds within up to 6000qu +snd_attenuation_method_1 + +// declare the channels we use +seta snd_channel8volume 1 "QuakeC controlled background music volume" +seta snd_channel9volume 1 "QuakeC controlled ambient sound volume" + +// sound randomization +snd_identicalsoundrandomization_time -0.1 +snd_identicalsoundrandomization_tics 1 // loading screen -scr_loadingscreen_scale 1 +scr_loadingscreen_background 0 +scr_loadingscreen_barcolor "0 0.5 1" +scr_loadingscreen_barheight 12 +scr_loadingscreen_count 13 +scr_loadingscreen_scale 999 scr_loadingscreen_scale_base 1 -scr_loadingscreen_scale_limit 1 +scr_loadingscreen_scale_limit 2 // other config files exec balanceXonotic.cfg exec ctfscoring-ai.cfg exec effects-normal.cfg -exec physicsX0.cfg +exec physicsX.cfg exec turrets.cfg -exec font-nimbussansl.cfg +exec vehicles.cfg + +// load console command aliases and settings +exec commands.cfg -// hud cvar descriptions +// hud cvar descriptions and common settings +exec _hud_common.cfg exec _hud_descriptions.cfg // exec the default skin config -// please add any new cvars into the hud_save script in qcsrc/client/hud.qc for consistency +// please add any new cvars into the hud_save script in qcsrc/client/hud_config.qc for consistency exec hud_luminos.cfg + +// ... and now that everything is configured/aliased, we can do some things: + +// Change g_start_delay based upon if the server is local or not. +if_client set g_start_delay 0 "delay before the game starts, so everyone can join; recommended to set this to like 15 on a public server" +if_dedicated set g_start_delay 15 "delay before the game starts, so everyone can join; recommended to set this to like 15 on a public server" + // enable menu syncing alias menu_sync "menu_cmd sync" -alias scoreboard_columns_set "cl_cmd scoreboard_columns_set $*" diff --git a/demos/little-bot-orchestra.dem b/demos/little-bot-orchestra.dem new file mode 100644 index 0000000000..81acdd1298 Binary files /dev/null and b/demos/little-bot-orchestra.dem differ diff --git a/effectinfo.txt b/effectinfo.txt index 3e69bd8267..0d464f5f77 100644 --- a/effectinfo.txt +++ b/effectinfo.txt @@ -739,25 +739,30 @@ velocityjitter 512 512 512 // used in qcsrc/client/gibs.qc: pointparticles(particleeffectnum("blood"), self.origin + '0 0 1', '0 0 30', 10) // used in qcsrc/client/gibs.qc: pointparticles(particleeffectnum("blood"), org, vel, amount * 16) effect blood -count 0.167 -type blood +count 0.4 +type spark +blend invmod tex 24 32 -size 3 8 -alpha 256 256 64 +size 5 11 +alpha 1560 2560 7000 color 0xA8FFFF 0xA8FFFFF bounce -1 -airfriction 1 -liquidfriction 4 -velocityjitter 64 64 64 -velocitymultiplier 5 +airfriction 0.4 +velocityjitter 99 99 55 +//velocitymultiplier 2 staincolor 0x808080 0x808080 staintex 16 24 +stainsize 1 2 +stretchfactor 20 +sizeincrease 20 //blood mist effect blood countabsolute 1 type alphastatic -tex 0 8 +blend invmod +tex 24 32 size 25 30 +sizeincrease 20 alpha 100 256 400 color 0x000000 0x420000 originjitter 11 11 11 @@ -795,21 +800,33 @@ color 0xff8400 0xff2a00 // normal super gory blood trail (used by gibs) // used in qcsrc/client/gibs.qc: trailparticles(self, particleeffectnum("TR_BLOOD"), oldorg, self.origin) effect TR_BLOOD -trailspacing 32 -type blood +trailspacing 20 +type spark +blend invmod color 0xA8FFFF 0xA8FFFF tex 24 32 -size 8 8 -alpha 384 384 192 +size 4 19 +alpha 384 984 1492 bounce -1 -airfriction 1 -liquidfriction 4 +gravity 0.4 +airfriction -2 +liquidfriction 1 velocityjitter 64 64 64 -velocitymultiplier 0.5 +velocitymultiplier -0.1 staincolor 0x808080 0x808080 staintex 16 24 - - +stainsize 1 2 +stretchfactor 7 +sizeincrease -5 +// splash around gib +effect TR_BLOOD +trailspacing 42 +type blood +color 0xA8FFFF 0xA8FFFF +tex 24 32 +size 4 6 +alpha 684 684 7492 +sizeincrease 500 // thinner blood trail (used by quake zombies) // used in qcsrc/client/gibs.qc: trailparticles(self, particleeffectnum("TR_SLIGHTBLOOD"), oldorg, self.origin) @@ -1079,15 +1096,16 @@ lightradiusfade 2000 lightcolor 2 1.5 0.2 gravity -0.1 effect uzi_muzzleflash -count 10 +count 3 type spark tex 40 40 -color 0xFFFDD9 0xFFFDD9 -size 2 2 -alpha 0 128 1024 +color 0xff9c00 0xffd200 +size 0.3 0.4 +alpha 0 256 6000 originjitter 1 1 1 -velocityjitter 300 300 300 -velocitymultiplier 0.5 +velocityjitter 555 555 555 +velocitymultiplier 3 +stretchfactor 0.15 airfriction 12 @@ -1201,7 +1219,7 @@ stretchfactor 2.5 -// hagar trail +// mortar trail // smoke // used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_GRENADE"), from, to) // used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_GRENADE"), from, to) @@ -1225,7 +1243,7 @@ trailspacing 4 type static color 0xffdf72 0x811200 tex 48 55 -size 1 2 +size 5 2 sizeincrease -15 alpha 100 144 988 airfriction 8 @@ -1247,7 +1265,7 @@ velocityjitter 16 16 16 -// mortar trail +// hookbomb trail // smoke // used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_KNIGHTSPIKE"), from, to) // used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_KNIGHTSPIKE"), from, to) @@ -1691,11 +1709,11 @@ effect crylink_impact countabsolute 1 type decal tex 47 47 -size 8 8 +size 24 24 alpha 256 256 0 originjitter 12 12 12 -//lightradius 60 -//lightradiusfade 300 +//lightradius 200 +//lightradiusfade 800 //lightcolor 3.2 0.4 4 // purple flare effect effect crylink_impact @@ -1703,34 +1721,34 @@ countabsolute 1 type static tex 39 39 color 0x504060 0x504060 -size 8 8 +size 24 24 alpha 256 256 512 // purple sparks effect crylink_impact -count 10 +count 40 type spark tex 41 41 color 0xA040C0 0xA040C0 bounce 2 -size 1 2 +size 6 6 alpha 256 256 1024 -velocityjitter 256 256 256 +velocityjitter 512 512 512 // purple splash effect crylink_impact count 1.5 type static color 0xE070FF 0xE070FF -size 8 8 +size 16 16 alpha 256 256 512 -velocityjitter 8 8 8 +velocityjitter 32 32 32 // purple splash effect crylink_impact -count 1.5 +count 3 type static color 0xE070FF 0xE070FF -size 8 8 +size 16 16 alpha 256 256 1024 -velocityjitter 32 32 32 +velocityjitter 256 256 256 @@ -3384,13 +3402,14 @@ velocityjitter 256 256 256 // used in qcsrc/server/w_common.qc: zcurveparticles_from_tracetoss(particleeffectnum("tr_bullet"), self.origin, trace_endpos, self.velocity) // used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("tr_bullet"), from, to) effect tr_bullet -trailspacing 256 +trailspacing 750 type spark -color 0x800000 0xFF8020 +tex 70 70 +color 0xff8960 0xff8533 alpha 256 256 2560 -size 1.5 1.5 -stretchfactor 1 -velocitymultiplier 0.7 +size 4 4 +stretchfactor 0.2 +velocitymultiplier 3 // smoke emitter for small pipes // used nowhere in code @@ -3455,83 +3474,144 @@ tex 40 40 //lighttime 0 effect alien_blood -count 0.167 -type blood +count 0.4 +type spark +blend invmod tex 24 32 -size 3 8 -alpha 256 256 64 +size 5 11 +alpha 1560 2560 7000 color 0xDC9BCD 0xDC9BCD bounce -1 -airfriction 1 -liquidfriction 4 -velocityjitter 64 64 64 -velocitymultiplier 5 -staincolor 0x808080 0x808080 +airfriction 0.4 +velocityjitter 99 99 55 +//velocitymultiplier 2 +staincolor 0xDC9BCD 0xDC9BCD staintex 16 24 +stainsize 1 2 +stretchfactor 25 +sizeincrease 20 //blood mist effect alien_blood countabsolute 1 -type alphastatic -tex 0 8 +type smoke +blend invmod +tex 24 32 size 25 30 -alpha 100 256 400 -color 0x000000 0x204010 +sizeincrease 20 +alpha 3000 5560 12000 +color 0xDC9BCD 0xDC9BCD originjitter 11 11 11 effect robot_blood count 0.167 -type blood -tex 24 32 -size 3 8 +type spark +tex 70 70 +size 1 2 alpha 256 256 64 -color 0xC0D890 0xC0D890 +color 0xff3000 0xff7373 bounce -1 +gravity 1 airfriction 1 liquidfriction 4 -velocityjitter 64 64 64 -velocitymultiplier 5 -staincolor 0x808080 0x808080 -staintex 16 24 -//blood mist +velocityjitter 264 264 264 +velocityoffset 0 0 100 +//shockwave effect robot_blood countabsolute 1 -type alphastatic -tex 0 8 -size 25 30 -alpha 100 256 400 -color 0x000000 0x301860 +type smoke +tex 74 74 +size 2 2 +alpha 0 90 1000 +color 0xff8400 0xffbb72 originjitter 11 11 11 +sizeincrease 800 +// electo sparcks +effect robot_blood +count 0.1 +type smoke +tex 71 73 +size 20 40 +alpha 256 256 5120 +color 0xff3000 0xff8585 +originjitter 41 41 21 +rotate -180 180 4000 -4000 + effect alien_TR_BLOOD -trailspacing 32 -type blood +trailspacing 20 +type spark +blend invmod color 0xC080B0 0xC080B0 tex 24 32 -size 8 8 -alpha 384 384 192 +size 4 19 +alpha 384 984 1492 bounce -1 -airfriction 1 -liquidfriction 4 +gravity 0.4 +airfriction -2 +liquidfriction 1 velocityjitter 64 64 64 -velocitymultiplier 0.5 -staincolor 0x808080 0x808080 +velocitymultiplier -0.1 +staincolor 0xC080B0 0xC080B0 staintex 16 24 +stainsize 1 2 +stretchfactor 7 +sizeincrease -5 +// splash around gib +effect TR_BLOOD +trailspacing 42 +type blood +color 0xA8FFFF 0xA8FFFF +tex 24 32 +size 4 6 +alpha 684 684 7492 +sizeincrease 500 effect robot_TR_BLOOD -trailspacing 32 -type blood +trailspacing 16 +type spark +blend invmod color 0xC0D890 0xC0D890 tex 24 32 -size 8 8 -alpha 384 384 192 +size 4 13 +alpha 384 984 1892 bounce -1 -airfriction 1 -liquidfriction 4 +gravity 0.4 +airfriction -2 +liquidfriction 1 velocityjitter 64 64 64 -velocitymultiplier 0.5 +velocitymultiplier -0.3 staincolor 0x808080 0x808080 staintex 16 24 +stainsize 1 3 +stretchfactor 6 +sizeincrease -6 +// fire +effect robot_TR_BLOOD +notunderwater +trailspacing 16 +type spark +tex 48 55 +color 0x902010 0xff3600 +size 5 20 +alpha 128 256 900 +gravity -1 +airfriction 4 +liquidfriction 4 +stretchfactor 5 +sizeincrease 10 +velocityjitter 44 44 44 +// arcs +effect robot_TR_BLOOD +trailspacing 128 +type smoke +tex 71 73 +color 0xff3000 0xff8585 +size 25 30 +alpha 1128 1256 44900 +rotate -180 180 4000 -4000 +velocityjitter 44 44 44 + effect alien_TR_SLIGHTBLOOD trailspacing 64 @@ -3583,50 +3663,101 @@ alpha 256 256 1280 velocityjitter 256 256 256 effect bloodshower -countabsolute 1 -type blood +count 125 +type spark +blend invmod tex 24 32 -size 8 8 +size 8 28 color 0xA8FFFF 0xA8FFFFF -alpha 256 256 64 +alpha 156 656 1664 bounce -1 -airfriction 1 +gravity 1 +stretchfactor 3 liquidfriction 4 -velocityjitter 64 64 64 -velocitymultiplier 1 +velocityjitter 764 764 764 +// velocitymultiplier 1 staincolor 0x808080 0x808080 staintex 16 24 +stainsize 1 2 +// center blood +effect bloodshower +countabsolute 0.1 +type smoke +blend invmod +tex 24 32 +size 1 28 +sizeincrease 300 +originjitter 50 50 50 +color 0xA8FFFF 0xA8FFFFF +alpha 156 656 1664 effect alien_bloodshower -countabsolute 1 -type blood +count 125 +type spark +blend invmod tex 24 32 -size 8 8 +size 8 28 color 0xC080B0 0xC080B0 -alpha 256 256 64 +alpha 156 656 1664 bounce -1 -airfriction 1 +gravity 1 +stretchfactor 3 liquidfriction 4 -velocityjitter 64 64 64 -velocitymultiplier 1 -staincolor 0x808080 0x808080 +velocityjitter 764 764 764 +// velocitymultiplier 1 +staincolor 0xC080B0 0xC080B0 staintex 16 24 +stainsize 1 2 +// center blood +effect bloodshower +countabsolute 0.1 +type smoke +blend invmod +tex 24 32 +size 1 28 +sizeincrease 300 +originjitter 50 50 50 +color 0xA8FFFF 0xA8FFFFF +alpha 156 656 1664 + effect robot_bloodshower -countabsolute 1 -type blood +count 100 +type spark +blend invmod tex 24 32 -size 8 8 +size 8 28 color 0xC0D890 0xC0D890 -alpha 256 256 64 +alpha 156 656 1664 bounce -1 -airfriction 1 +gravity 1 +stretchfactor 3 liquidfriction 4 -velocityjitter 64 64 64 -velocitymultiplier 1 -staincolor 0x808080 0x808080 +velocityjitter 764 764 764 +// velocitymultiplier 1 +staincolor 0xC0D890 0xC0D890 staintex 16 24 - +stainsize 1 2 +// arc +effect robot_bloodshower +count 2.5 +type smoke +tex 71 73 +color 0xff3000 0xff8585 +size 25 40 +alpha 1128 1256 4200 +rotate -180 180 99 -99 +velocityjitter 44 44 44 +originjitter 150 150 150 +// shockwave +effect robot_bloodshower +count 2.5 +type smoke +tex 74 74 +color 0xff3000 0xff8585 +size 5 50 +sizeincrease 3000 +alpha 11 125 990 //red_ground_quake //smoke @@ -4694,8 +4825,6 @@ bounce 1.5 liquidfriction 4 velocityjitter 16 16 16 - - // rocket guiding start // underwater bubbles effect rocket_guide @@ -5125,3 +5254,1435 @@ originjitter 1 1 1 velocityjitter 300 300 300 velocitymultiplier 0.5 airfriction 3 + + +// weak rifle bullet trail (somewhat like a tracer) +// used in qcsrc/server/w_common.qc: zcurveparticles_from_tracetoss(particleeffectnum("tr_bullet"), self.origin, trace_endpos, self.velocity) +// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("tr_bullet"), from, to) +effect tr_rifle_weak +trailspacing 128 +type spark +color 0x800000 0xFF8020 +alpha 256 256 2560 +size 1.5 1.5 +stretchfactor 1 +velocitymultiplier 0.7 +effect tr_rifle_weak +notunderwater +tex 0 8 +trailspacing 48 +type static +color 0x202020 0x404040 +size 4 4 +sizeincrease 0.4 +alpha 256 256 256 +airfriction -4 +velocityjitter 4 4 4 +type smoke +effect tr_rifle_weak +underwater +trailspacing 192 +type bubble +tex 62 62 +color 0x404040 0x808080 +size 2 2 +alpha 256 256 128 +gravity -0.125 +bounce 1.5 +liquidfriction 4 +velocityjitter 16 16 16 + +// red smoke emiter +// used nowhere in code +effect red_smoke +count 2 +type smoke +tex 0 8 +color 0xff8866 0x331100 +size 60 120 +sizeincrease 0 +alpha 32 64 32 +gravity -0.007 +originjitter 0 0 0 +velocityjitter 0 0 0 +velocitymultiplier 5 +airfriction -1 +rotate 0 360 -30 30 + +// pipe smoke emiter +// used nowhere in code +effect pipe_smoke +count 2 +type smoke +tex 0 8 +color 0x999999 0x555555 +size 5 10 +sizeincrease 35 +alpha 32 64 48 +gravity -0.015 +originjitter 0 0 0 +velocityjitter 0 0 5 +velocitymultiplier 15 +airfriction -1 +rotate 0 360 -180 180 + +// seeker missile trail +effect TR_SEEKER +trailspacing 10 +type smoke +notunderwater +color 0x000000 0x666666 +tex 0 8 +size 2 2 +bounce 1 +sizeincrease 11 +alpha 200 300 200 +lightradius 100 +lighttime 0 +lightcolor 6 3 1 +originjitter 2 2 2 +velocityjitter 3 3 3 +velocitymultiplier -0.02 +rotate -180 180 -30 30 +//gravity -0.11 +// fire +effect TR_SEEKER +trailspacing 4 +type static +color 0xffdf72 0x811200 +tex 48 55 +size 5 5 +sizeincrease -30 +alpha 100 144 588 +airfriction 8 +velocityjitter 32 32 32 +velocitymultiplier -1.5 +// bubbles +effect TR_SEEKER +type bubble +underwater +trailspacing 16 +tex 62 62 +size 1 2 +alpha 256 256 256 +gravity -0.125 +bounce 1.5 +liquidfriction 4 +velocityjitter 16 16 16 +velocitymultiplier -0.31 +rotate 0 0 0 0 +// sparks +effect TR_SEEKER +notunderwater +trailspacing 20 +type spark +tex 40 40 +color 0xFFFDD9 0xFFFDD9 +size 0.5 0.5 +alpha 444 512 1866 +stretchfactor 0.3 +//gravity 1 +bounce 1 +//velocityoffset 0 0 15 +airfriction 5 +originjitter 1 1 1 +velocityjitter 100 100 100 +velocitymultiplier -0.31 + +// --------------- vehicles + +effect spiderbot_minigun_trail +notunderwater +trailspacing 10 +type smoke +color 0xd0d0a0 0xffffff +tex 0 8 +size 1 2 +alpha 20 50 100 +sizeincrease 2 +velocityjitter 5 5 5 +gravity -0.03 +airfriction 1 + +effect spiderbot_minigun_muzzleflash +count 3 +type spark +color 0xff9c00 0xff8400 +tex 48 55 +size 10 15 +alpha 256 512 6280 +airfriction 10 +originjitter 2 2 2 +velocityjitter 150 150 150 +velocitymultiplier 0.35 +sizeincrease -100 +stretchfactor 1.3 +rotate -180 180 4000 -4000 +// fire +effect spiderbot_minigun_muzzleflash +count 6 +type spark +color 0xff9c00 0xff8400 +tex 8 15 +size 5 7 +alpha 256 512 6280 +airfriction 12 +originjitter 2 2 2 +velocityjitter 200 200 200 +velocitymultiplier 0.2 +sizeincrease -10 +stretchfactor 0.8 +effect spiderbot_minigun_muzzleflash +countabsolute 2 +type static +tex 48 55 +color 0xff9c00 0xff8400 +size 32 32 +alpha 256 512 6680 +sizeincrease -100 +stretchfactor 0.1 +rotate -180 180 4000 -4000 +lightradius 120 +lightradiusfade 8000 +lightcolor 3 3 0 + +effect spiderbot_minigun_impact +countabsolute 1 +type static +tex 65 65 +color 0xff9c00 0xf6ff00 +size 52 52 +alpha 50 100 1680 +sizeincrease -100 +stretchfactor 0.1 +rotate -180 180 4000 -4000 +// fire +effect spiderbot_minigun_impact +count 7 +type spark +color 0xff9c00 0xff8400 +tex 48 55 +size 9 15 +alpha 256 512 6280 +airfriction 10 +originjitter 2 2 2 +velocityjitter 250 250 150 +velocitymultiplier 0.2 +sizeincrease 100 +stretchfactor 3 +airfriction 6 +rotate -180 180 4000 -4000 +// smoke +effect spiderbot_minigun_impact +count 6 +type smoke +color 0xd0d0a0 0xffffff +tex 0 8 +size 10 20 +alpha 50 50 190 +sizeincrease 80 +velocityjitter 100 100 250 +velocitymultiplier 0.49 +gravity 1.3 +airfriction 10 +rotate -180 180 0 0 +// smoke 2 +effect spiderbot_minigun_impact +count 7 +type spark +color 0xd0d0a0 0xffffff +tex 0 8 +size 15 19 +alpha 25 51 128 +airfriction 6 +originjitter 2 2 2 +velocityjitter 250 250 150 +velocitymultiplier 0.2 +sizeincrease 100 +stretchfactor 7.6 +// derbis +effect spiderbot_minigun_impact +notunderwater +count 3 +type alphastatic +tex 66 68 +color 0x99977D 0xFFFFFF +size 6 8 +alpha 644 756 1484 +gravity 1.1 +airfriction 0.4 +sizeincrease -10 +velocitymultiplier 0.15 +originjitter 16 16 16 +velocityjitter 124 124 224 +rotate -180 180 -1000 1000 +// decal +effect spiderbot_minigun_impact +countabsolute 1 +type decal +tex 56 59 +size 20 25 +alpha 256 256 0 +originjitter 16 16 16 +rotate -180 180 0 0 + +effect spiderbot_rocket_explode +countabsolute 1 +type decal +tex 8 16 +size 72 72 +alpha 256 256 0 +originjitter 23 23 23 +lightradius 300 +lightradiusfade 1750 +lightcolor 8 4 0 +// shockwave +effect spiderbot_rocket_explode +countabsolute 1 +type static +tex 33 33 +size 22 22 +alpha 56 56 230 +color 0x8f0d00 0xff5a00 +sizeincrease 2400 +// glow +effect spiderbot_rocket_explode +countabsolute 1 +type static +tex 64 64 +size 120 120 +alpha 156 156 830 +color 0x8f0d00 0xff5a00 +sizeincrease 240 +// fire effect +effect spiderbot_rocket_explode +notunderwater +count 32 +type static +tex 48 55 +color 0x8f0d00 0xff5a00 +size 12 21 +sizeincrease 495 +alpha 200 256 812 +airfriction 8 +liquidfriction 8 +originjitter 100 100 100 +velocityjitter 512 512 512 +rotate -180 180 -50 50 +// fire effect 2 +effect spiderbot_rocket_explode +notunderwater +count 16 +type spark +tex 48 55 +color 0x8f0d00 0xff5a00 +size 3 3 +sizeincrease 120 +alpha 200 256 912 +airfriction -2 +liquidfriction 8 +velocityjitter 412 412 412 +rotate -180 180 -150 150 +stretchfactor 10 +// fire rays +effect spiderbot_rocket_explode +notunderwater +count 10 +type spark +tex 48 55 +color 0x8f0d00 0xff5a00 +size 13 54 +sizeincrease 120 +alpha 200 256 1600 +airfriction -3 +liquidfriction 8 +originjitter 40 40 40 +velocityjitter 712 712 712 +stretchfactor 10 +// smoke +effect spiderbot_rocket_explode +type alphastatic +notunderwater +tex 0 8 +count 10 +size 10 15 +sizeincrease 280 +alpha 300 650 756 +originjitter 100 100 100 +velocityjitter 200 200 200 +airfriction 3 +color 0x4F4B46 0x000000 +rotate -180 180 -20 20 +// smoke2 +effect spiderbot_rocket_explode +type alphastatic +notunderwater +tex 0 8 +count 3 +size 100 150 +sizeincrease 30 +alpha 300 650 556 +originjitter 10 10 10 +velocityjitter 200 200 200 +airfriction 2 +gravity -0.5 +color 0x4F4B46 0x000000 +rotate -180 180 -20 20 +// underwater bubbles +effect spiderbot_rocket_explode +underwater +count 32 +type bubble +tex 62 62 +color 0x404040 0x808080 +size 1 3 +alpha 128 256 64 +gravity -0.125 +bounce 1.5 +liquidfriction 0.25 +originjitter 160 160 160 +velocityjitter 144 144 144 +// underwatershockwave +effect spiderbot_rocket_explode +underwater +type smoke +countabsolute 1 +tex 33 33 +size 30 30 +sizeincrease 1200 +alpha 40 40 300 + + +effect spiderbot_rocket_thrust +notunderwater +count 3 +type spark +tex 48 55 +color 0x8f0d00 0xff5a00 +size 5 10 +sizeincrease -40 +alpha 200 256 1600 +velocityjitter 20 20 20 +velocitymultiplier -1.4 +stretchfactor 0.9 +effect spiderbot_rocket_thrust +notunderwater +count 4 +type static +tex 48 55 +color 0x8f0d00 0xff5a00 +size 25 25 +sizeincrease -3000 +alpha 200 200 9000 +velocityjitter 60 60 60 +velocitymultiplier -1.4 +stretchfactor 1 +rotate -180 180 -500 500 + + + +// long lasting smoke +effect spiderbot_rocket_launch +notunderwater +count 8 +type smoke +tex 0 8 +color 0xFFFFFF 0xD9C4B0 +size 30 30 +sizeincrease 20 +alpha 100 156 60 +velocityjitter 60 60 60 +velocitymultiplier -0.1 +airfriction 0.3 +gravity -0.01 +// fast smoke +effect spiderbot_rocket_launch +notunderwater +count 14 +type smoke +tex 0 8 +color 0xFFFFFF 0xD9C4B0 +size 30 30 +sizeincrease 20 +alpha 100 156 260 +gravity -0.3 +velocityjitter 160 160 60 +airfriction 0.3 +// fire +effect spiderbot_rocket_launch +notunderwater +count 14 +type spark +tex 48 55 +color 0x8f0d00 0xff5a00 +size 30 30 +sizeincrease 40 +velocitymultiplier 0.5 +alpha 200 256 1960 +velocityjitter 60 60 60 +airfriction 0.3 +stretchfactor 3 +airfriction 0.3 +//sparks +effect spiderbot_rocket_launch +notunderwater +count 10 +type spark +tex 40 40 +color 0xFFFFFF 0xD9C4B0 +size 1 4 +alpha 200 256 1000 +velocityjitter 160 160 160 +velocitymultiplier -0.5 + +effect wakizashi_gun_impact +count 15 +type spark +color 0xff0000 0xc03535 +tex 41 41 +size 4 7 +alpha 256 512 1180 +airfriction 4 +gravity 3 +originjitter 40 40 10 +velocityjitter 350 350 550 +velocityoffset 0 0 700 +stretchfactor 0.9 +effect wakizashi_gun_impact +type smoke +count 24 +color 0xd0d0a0 0xc03535 +tex 0 8 +size 10 20 +alpha 50 90 150 +sizeincrease 80 +velocityjitter 250 250 450 +velocityoffset 0 0 600 +originjitter 40 40 10 +airfriction 4 +sizeincrease 80 +rotate -180 180 0 0 +effect wakizashi_gun_impact +countabsolute 1 +type smoke +tex 65 65 +color 0xff0000 0xc03535 +size 82 82 +alpha 250 300 680 +sizeincrease -180 +effect wakizashi_gun_impact +countabsolute 1 +type smoke +tex 33 33 +color 0xff0000 0xc03535 +size 40 40 +alpha 50 100 620 +sizeincrease 900 +rotate -180 180 400 -400 +effect wakizashi_gun_impact +countabsolute 1 +type decal +tex 59 59 +size 14 14 +alpha 256 256 0 +originjitter 16 16 16 +rotate -180 180 0 0 + +effect wakizashi_gun_muzzleflash +count 16 +type spark +color 0xff0000 0xc03535 +tex 8 15 +size 5 7 +alpha 256 512 6280 +airfriction 12 +originjitter 2 2 2 +velocityjitter 200 200 200 +velocitymultiplier 0.2 +sizeincrease -10 +stretchfactor 0.7 + +effect wakizashi_rocket_explode +countabsolute 1 +type decal +tex 8 16 +size 72 72 +alpha 256 256 0 +originjitter 23 23 23 +lightradius 300 +lightradiusfade 1750 +lightcolor 8 4 0 +// shockwave +effect wakizashi_rocket_explode +countabsolute 1 +type static +tex 33 33 +size 22 22 +alpha 56 56 230 +color 0x8f0d00 0xff5a00 +sizeincrease 2400 +// glow +effect wakizashi_rocket_explode +countabsolute 1 +type static +tex 64 64 +size 120 120 +alpha 156 156 830 +color 0x8f0d00 0xff5a00 +sizeincrease 240 +// fire effect +effect wakizashi_rocket_explode +notunderwater +count 64 +type static +tex 48 55 +color 0xFFAE00 0xff5a00 +size 12 21 +sizeincrease 195 +alpha 200 256 512 +airfriction 2 +liquidfriction 8 +originjitter 10 10 10 +velocityjitter 512 512 512 +rotate -180 180 -50 50 +// fire rays +effect wakizashi_rocket_explode +notunderwater +count 10 +type spark +tex 48 55 +color 0xFFEA00 0xff5a00 +size 43 54 +sizeincrease 120 +alpha 200 256 1600 +airfriction -3 +liquidfriction 8 +originjitter 40 40 40 +velocityjitter 512 512 512 +stretchfactor 10 +// smoke +effect wakizashi_rocket_explode +type alphastatic +notunderwater +tex 0 8 +count 32 +size 10 15 +sizeincrease 230 +alpha 300 450 556 +originjitter 100 100 100 +velocityjitter 200 200 200 +airfriction 3 +color 0x4F4B46 0x000000 +rotate -180 180 -20 20 +// bouncing sparks +effect wakizashi_rocket_explode +notunderwater +count 14 +type spark +tex 40 40 +color 0xffa35b 0xfff2be +size 1 2 +alpha 644 956 884 +gravity 1 +airfriction 1 +liquidfriction 0.8 +velocityoffset 0 0 170 +originjitter 60 60 60 +velocityjitter 524 524 524 +// underwater bubbles +effect wakizashi_rocket_explode +underwater +count 32 +type bubble +tex 62 62 +color 0x404040 0x808080 +size 1 3 +alpha 128 256 64 +gravity -0.125 +bounce 1.5 +liquidfriction 0.25 +originjitter 160 160 160 +velocityjitter 144 144 144 +// underwatershockwave +effect wakizashi_rocket_explode +underwater +type smoke +countabsolute 1 +tex 33 33 +size 30 30 +sizeincrease 1200 +alpha 40 40 300 + +effect wakizashi_rocket_thrust +notunderwater +countabsolute 3 +type spark +tex 48 55 +color 0x00FFDD 0x6200FF +size 14 19 +sizeincrease -2 +alpha 200 256 1600 +velocityjitter 60 60 60 +velocitymultiplier -1.1 +stretchfactor 1 +effect wakizashi_rocket_thrust +notunderwater +countabsolute 2 +type spark +tex 48 55 +color 0xFFFF33 0xFFEE00 +size 5 10 +sizeincrease -2 +alpha 200 256 1900 +velocityjitter 60 60 60 +velocitymultiplier -0.3 +stretchfactor 3 + +// long lasting smoke +effect wakizashi_rocket_launch +notunderwater +count 8 +type smoke +tex 0 8 +color 0xFFFFFF 0xD9C4B0 +size 3 30 +sizeincrease 20 +alpha 100 156 60 +velocityjitter 160 160 60 +velocitymultiplier -0.1 +airfriction 0.3 +// fast smoke +effect wakizashi_rocket_launch +notunderwater +count 14 +type smoke +tex 0 8 +color 0xFFFFFF 0xD9C4B0 +size 30 30 +sizeincrease 20 +alpha 100 156 260 +velocityjitter 160 160 60 +velocitymultiplier 0.4 +airfriction 0.3 +//sparks +effect wakizashi_rocket_launch +notunderwater +count 10 +type spark +tex 40 40 +color 0xFFFFFF 0xD9C4B0 +size 1 4 +alpha 200 256 1000 +velocityjitter 60 60 60 +velocitymultiplier -1.5 + +effect wakizashi_booster_smoke +type alphastatic +notunderwater +tex 0 8 +count 3 +size 60 100 +sizeincrease 10 +gravity -0.1 +alpha 200 750 200 +velocityjitter 40 40 40 +originjitter 60 60 60 +airfriction 2 +color 0xA69A80 0xB3B39F +rotate -180 180 -20 20 + +// decal +effect raptor_cannon_impact +countabsolute 1 +type decal +tex 47 47 +size 24 24 +alpha 256 256 0 +originjitter 16 16 16 +rotate -180 180 0 0 +//spark +effect raptor_cannon_impact +notunderwater +count 6 +type spark +tex 40 40 +color 0xD400FF 0x571863 +size 1 1 +alpha 644 956 784 +gravity 1 +airfriction 0.2 +velocityoffset 0 0 150 +originjitter 16 16 16 +velocityjitter 124 124 524 +// smoke +effect raptor_cannon_impact +count 4 +type alphastatic +tex 0 7 +size 50 50 +color 0x646364 0x151515 +alpha 428 428 600 +rotate -180 180 0 0 +velocityjitter 200 200 300 +velocityoffset 0 0 340 +gravity 0.7 +airfriction 2 +// fire +effect raptor_cannon_impact +notunderwater +count 10 +type static +tex 48 55 +color 0xD400FF 0x571863 +size 33 44 +sizeincrease 25 +alpha 200 256 812 +bounce 1.5 +airfriction 8 +liquidfriction 8 +originjitter 8 8 8 +velocityjitter 312 312 312 + + +effect raptor_cannon_muzzleflash +count 16 +type spark +color 0xD400FF 0x571863 +tex 8 15 +size 10 17 +alpha 1256 1512 56280 +airfriction 12 +originjitter 2 2 2 +velocityjitter 200 200 200 +velocitymultiplier 0.2 +sizeincrease -10 +stretchfactor 0.6 +effect raptor_cannon_muzzleflash +countabsolute 1 +type static +tex 48 55 +color 0xD400FF 0x571863 +size 32 32 +alpha 6056 20112 406280 +sizeincrease -100 +stretchfactor 0.1 +rotate -180 180 4000 -4000 +lightradius 150 +lightradiusfade 6000 +lightcolor 3 0 6 + +// decal +effect raptor_bomb_impact +countabsolute 1 +type decal +tex 8 16 +size 84 84 +alpha 256 256 0 +originjitter 16 16 16 +rotate -180 180 0 0 + +//spark vertical +effect raptor_bomb_impact +count 3 +type spark +color 0xff9c00 0xff3c00 +tex 48 55 +size 20 40 +alpha 300 300 600 +originjitter 10 10 10 +velocityjitter 40 40 120 +stretchfactor 210 +sizeincrease 50 + +//fire +effect raptor_bomb_impact +count 4 +type static +color 0xff9c00 0xff3c00 +tex 48 55 +size 30 120 +alpha 300 300 500 +originjitter 10 10 10 +velocityjitter 950 950 0 +sizeincrease 230 +airfriction 2 + +//smoke +effect raptor_bomb_impact +count 4 +type spark +blend alpha +tex 0 7 +size 120 180 +color 0x646364 0x151515 +alpha 428 428 600 +rotate -180 180 0 0 +velocityjitter 200 200 280 +velocityoffset 0 0 280 +originjitter 30 30 10 +stretchfactor 10 + +//smoke 2 +effect raptor_bomb_impact +count 4 +//type alphastatic +type spark +blend alpha +tex 0 7 +size 40 100 +color 0x646364 0x151515 +alpha 328 328 350 +rotate -180 180 0 0 +velocityjitter 200 200 300 +velocityoffset 0 0 580 +originjitter 30 30 10 +sizeincrease 60 +airfriction 0.6 +gravity 2 + +// sparks +effect raptor_bomb_impact +notunderwater +count 5 +type spark +tex 40 40 +color 0xffa35b 0xfff2be +size 3 5 +alpha 644 956 984 +gravity 1 +airfriction 0.3 +velocityoffset 0 0 350 +originjitter 16 16 16 +velocityjitter 174 174 924 +stretchfactor 2 + +effect raptor_bomb_spread +notunderwater +count 34 +type spark +tex 40 40 +color 0xffa35b 0xfff2be +size 1 2 +alpha 644 956 1284 +gravity 1 +airfriction 1 +liquidfriction 0.8 +originjitter 110 110 110 +velocityjitter 324 324 324 + + +// generic explosion size:big (biggest explosion ever) +effect explosion_big +countabsolute 1 +type decal +tex 8 16 +size 172 172 +alpha 256 256 0 +originjitter 23 23 23 +lightradius 600 +lightradiusfade 1750 +lightcolor 8 4 0 +// shockwave +effect explosion_big +countabsolute 1 +type static +tex 33 33 +size 72 72 +alpha 56 56 330 +color 0x8f0d00 0xff5a00 +sizeincrease 4400 +// fire effect +effect explosion_big +notunderwater +count 64 +type static +tex 48 55 +color 0x8f0d00 0xff5a00 +size 133 144 +sizeincrease 45 +alpha 200 256 712 +airfriction 8 +liquidfriction 8 +originjitter 80 80 80 +velocityjitter 2512 2512 2512 +// fire rays +effect explosion_big +notunderwater +count 64 +type spark +tex 48 55 +color 0x8f0d00 0xff5a00 +size 133 144 +sizeincrease 45 +alpha 200 256 800 +airfriction -5 +liquidfriction 8 +originjitter 40 40 40 +velocityjitter 512 512 512 +stretchfactor 10 +// smoke +effect explosion_big +type alphastatic +notunderwater +tex 0 8 +count 32 +size 50 100 +sizeincrease 244 +alpha 300 650 456 +velocityjitter 3444 3444 3444 +airfriction 8 +color 0x4F4B46 0x000000 +// bouncing sparks +effect explosion_big +notunderwater +count 34 +type spark +tex 40 40 +color 0xffa35b 0xfff2be +size 3 4 +alpha 644 956 1284 +gravity 1 +airfriction 1 +liquidfriction 0.8 +velocityoffset 0 0 370 +originjitter 160 160 160 +velocityjitter 924 924 924 +stretchfactor 0.7 +// derbis +effect explosion_big +notunderwater +count 16 +type alphastatic +tex 66 68 +color 0xFFFFFF 0xcac5b4 +size 10 16 +alpha 444 1356 1184 +gravity 2.3 +airfriction 0.5 +velocityjitter 1800 1800 1800 +velocityoffset 0 0 970 +sizeincrease -5 +rotate -180 180 -1000 1000 +// underwater bubbles +effect explosion_big +underwater +count 32 +type bubble +tex 62 62 +color 0x404040 0x808080 +size 3 3 +alpha 128 256 64 +gravity -0.125 +bounce 1.5 +liquidfriction 0.25 +originjitter 160 160 160 +velocityjitter 444 444 444 +// underwatershockwave +effect explosion_big +underwater +type smoke +countabsolute 1 +tex 33 33 +size 30 30 +sizeincrease 2900 +alpha 40 40 300 +velocitymultiplier 0.3 + + +// generic explosion size:medium (it leaves rising smoke for a longer time) +// shockwave +effect explosion_medium +countabsolute 1 +type static +tex 33 33 +size 72 72 +alpha 56 56 330 +color 0x8f0d00 0xff5a00 +sizeincrease 2400 +// fire effect +effect explosion_medium +notunderwater +count 32 +type static +tex 48 55 +color 0x8f0d00 0xff5a00 +size 133 144 +sizeincrease 45 +alpha 200 256 712 +airfriction 8 +liquidfriction 8 +originjitter 30 30 30 +velocityjitter 1512 1512 1512 +rotate -180 180 -500 500 +// fire effect 2 +effect explosion_medium +notunderwater +count 32 +type static +tex 48 55 +color 0x8f0d00 0xff5a00 +size 73 94 +sizeincrease 40 +gravity -2 +alpha 200 256 612 +airfriction 8 +liquidfriction 8 +originjitter 30 30 30 +velocityjitter 1512 1512 1512 +rotate -180 180 -150 150 +// fire rays +effect explosion_medium +notunderwater +count 14 +type spark +tex 48 55 +color 0x8f0d00 0xff5a00 +size 43 74 +sizeincrease 40 +alpha 200 256 800 +airfriction -3 +liquidfriction 8 +originjitter 40 40 40 +velocityjitter 512 512 512 +stretchfactor 8 +// smoke +effect explosion_medium +type alphastatic +notunderwater +tex 0 8 +count 5 +size 250 300 +sizeincrease -30 +alpha 300 650 756 +originjitter 100 100 100 +velocityjitter 200 200 200 +airfriction 3 +color 0x4F4B46 0x000000 +rotate -180 180 -20 20 +// smoke 2 +effect explosion_medium +type alphastatic +notunderwater +tex 0 8 +count 10 +size 50 100 +sizeincrease 50 +gravity -0.3 +alpha 300 650 256 +originjitter 100 100 100 +velocityjitter 500 500 500 +velocityoffset 0 0 200 +airfriction 3 +color 0x4F4B46 0x000000 +rotate -180 180 -20 20 +// smoke rays +effect explosion_medium +type spark +notunderwater +tex 0 8 +count 13 +size 150 200 +sizeincrease 100 +alpha 140 255 350 +velocityjitter 250 250 250 +originjitter 40 40 40 +color 0x4F4B46 0x000000 +stretchfactor 50 +// bouncing sparks +effect explosion_medium +notunderwater +count 14 +type spark +tex 40 40 +color 0xffa35b 0xfff2be +size 2 3 +alpha 644 956 984 +gravity 1 +airfriction 1 +liquidfriction 0.8 +velocityoffset 0 0 370 +originjitter 100 100 100 +velocityjitter 624 624 624 +stretchfactor 0.7 +// underwater bubbles +effect explosion_medium +underwater +count 32 +type bubble +tex 62 62 +color 0x404040 0x808080 +size 3 3 +alpha 128 256 64 +gravity -0.125 +bounce 1.5 +liquidfriction 0.25 +originjitter 160 160 160 +velocityjitter 444 444 444 +// underwatershockwave +effect explosion_medium +underwater +type smoke +countabsolute 1 +tex 33 33 +size 30 30 +sizeincrease 2900 +alpha 40 40 300 +velocitymultiplier 0.3 + +// generic explosion size:small (its fire only, made to support other explosions) +// shockwave +effect explosion_small +countabsolute 1 +type static +tex 33 33 +size 22 22 +alpha 56 56 330 +color 0x8f0d00 0xff5a00 +sizeincrease 2400 +// fire effect +effect explosion_small +notunderwater +count 16 +type static +tex 48 55 +color 0x8f0d00 0xff5a00 +size 1 44 +sizeincrease 45 +alpha 200 256 1212 +airfriction 5 +liquidfriction 8 +velocityjitter 512 512 512 +rotate -180 180 -500 500 +// fire effect 2 +effect explosion_small +notunderwater +count 16 +type static +tex 48 55 +color 0x8f0d00 0xff5a00 +size 73 94 +sizeincrease 40 +alpha 200 256 812 +airfriction 8 +liquidfriction 8 +velocityjitter 912 912 912 +rotate -180 180 -150 150 +// fire rays +effect explosion_small +notunderwater +count 14 +type spark +tex 48 55 +color 0x8f0d00 0xff5a00 +size 13 54 +sizeincrease 30 +alpha 200 256 1300 +airfriction -3 +liquidfriction 8 +originjitter 40 40 40 +velocityjitter 512 512 512 +stretchfactor 8 +// underwater bubbles +effect explosion_small +underwater +count 32 +type bubble +tex 62 62 +color 0x404040 0x808080 +size 1 3 +alpha 128 256 64 +gravity -0.125 +bounce 1.5 +liquidfriction 0.25 +originjitter 160 160 160 +velocityjitter 144 144 144 +// underwatershockwave +effect explosion_small +underwater +type smoke +countabsolute 1 +tex 33 33 +size 30 30 +sizeincrease 1200 +alpha 40 40 300 + +// big smoke ( for spamming on damaged stuff ) +effect smoke_big +type alphastatic +notunderwater +tex 0 8 +count 3 +size 30 60 +sizeincrease 15 +gravity -0.5 +alpha 200 750 200 +originjitter 55 55 55 +velocityjitter 140 140 200 +velocityoffset 0 0 200 +airfriction 4 +color 0x4F4B46 0x000000 +rotate -180 180 -20 20 + +// small smoke ( more precise than big one, for spamming on damaged parts like raptors spinner ) +effect smoke_small +type alphastatic +notunderwater +tex 0 8 +count 3 +size 60 100 +sizeincrease -10 +gravity -0.5 +alpha 200 750 200 +velocityjitter 40 40 400 +velocityoffset 0 0 200 +airfriction 4 +color 0x4F4B46 0x000000 +rotate -180 180 -20 20 + +// metal impact effect +// used in qcsrc/server/mutators/sandbox.qc: pointparticles(particleeffectnum("impact_metal"), self.origin, '0 0 0', 1); +effect impact_metal +count 1 +type alphastatic +tex 0 8 +size 3 6 +sizeincrease 10 +alpha 25 64 50 +gravity -0.01 +color 0x000000 0x886666 +originjitter 20 20 5 +// sparks +effect impact_metal +count 2 +type spark +tex 41 41 +color 0xFFCC22 0xFF4422 +size 2 2 +alpha 255 255 112 +bounce 1.8 +stretchfactor 0.5 +velocityjitter 200 200 300 +velocitymultiplier 2 +airfriction 2 +gravity 1 + +// stone impact effect +// used in qcsrc/server/mutators/sandbox.qc: pointparticles(particleeffectnum("impact_stone"), self.origin, '0 0 0', 1); +effect impact_stone +count 1 +type alphastatic +tex 0 8 +size 3 6 +sizeincrease 15 +alpha 50 128 75 +gravity -0.01 +color 0x000000 0xcc9966 +originjitter 20 20 5 +// debris +effect impact_stone +notunderwater +count 1 +type alphastatic +tex 66 68 +color 0x000000 0x886644 +size 1 2 +alpha 450 750 300 +gravity 1.3 +airfriction 0.5 +bounce 1.2 +velocityjitter 124 124 324 +rotate -180 180 -1000 1000 + +// wood impact effect +// used in qcsrc/server/mutators/sandbox.qc: pointparticles(particleeffectnum("impact_wood"), self.origin, '0 0 0', 1); +effect impact_wood +count 1 +type alphastatic +tex 0 8 +size 3 6 +sizeincrease 10 +alpha 50 128 75 +gravity -0.01 +color 0x000000 0xcc9966 +originjitter 20 20 5 +// sparks +effect impact_wood +count 2 +type spark +tex 41 41 +color 0x221100 0x221100 +size 1 8 +alpha 255 255 75 +bounce 1.5 +velocityjitter 180 180 260 +velocitymultiplier 2 +airfriction 2 +gravity 1 + +// flesh impact effect +// used in qcsrc/server/mutators/sandbox.qc: pointparticles(particleeffectnum("impact_flesh"), self.origin, '0 0 0', 1); +effect impact_flesh +count 0.5 +type alphastatic +tex 0 8 +size 8 12 +alpha 100 256 400 +color 0x000000 0x420000 +originjitter 11 11 11 +// blood splash +effect impact_flesh +count 0.3 +type blood +tex 24 32 +size 2 6 +alpha 256 256 64 +color 0xA8FFFF 0xA8FFFFF +bounce -1 +airfriction 1 +liquidfriction 4 +velocityjitter 96 96 96 +velocitymultiplier 5 +staincolor 0x808080 0x808080 +staintex 16 24 + +// hagar trail +// smoke +effect tr_hagar +trailspacing 4 +type smoke +color 0x101010 0x000000 +tex 0 8 +size 3 2 +bounce 1 +sizeincrease 10 +alpha 300 400 780 +originjitter 1 1 1 +velocityjitter 1 1 1 +velocitymultiplier -0.02 +//gravity -0.11 +// fire +effect tr_hagar +notunderwater +trailspacing 4 +type static +color 0xffdf72 0x811200 +tex 48 55 +size 5 2 +sizeincrease -15 +alpha 100 144 988 +airfriction 8 +velocityjitter 32 32 32 +velocitymultiplier -1.0 +// bubbles +effect tr_hagar +underwater +trailspacing 16 +type bubble +tex 62 62 +color 0x404040 0x808080 +size 1 1 +alpha 256 256 256 +gravity -0.125 +bounce 1.5 +liquidfriction 4 +velocityjitter 16 16 16 diff --git a/effects-high.cfg b/effects-high.cfg index 7b7358cd94..0e011fe56b 100644 --- a/effects-high.cfg +++ b/effects-high.cfg @@ -1,4 +1,5 @@ cl_decals 1 +cl_decals_models 0 cl_decals_time 4 cl_particles_quality 1 gl_flashblend 0 @@ -7,14 +8,15 @@ gl_texture_anisotropy 16 mod_q3bsp_nolightmaps 0 r_bloom 1 r_coronas 1 -r_damageblur 0.4 +r_coronas_occlusionquery 1 +hud_postprocessing_maxbluralpha 0.5 +hud_powerup 0 r_depthfirst 2 r_drawdecals_drawdistance 500 r_drawparticles_drawdistance 2000 r_glsl_deluxemapping 1 r_glsl_offsetmapping 1 r_glsl_offsetmapping_reliefmapping 0 -r_hdr 0 r_motionblur 0.5 r_shadow_gloss 1 r_shadow_realtime_dlight 1 @@ -28,6 +30,7 @@ r_subdivisions_tolerance 3 r_texture_dds_load 1 r_water 1 r_water_resolutionmultiplier 0.5 -vid_samples 2 +vid_samples 1 +r_viewfbo 2 menu_sync diff --git a/effects-low.cfg b/effects-low.cfg index 79d56951f4..a9cff5abe5 100644 --- a/effects-low.cfg +++ b/effects-low.cfg @@ -1,4 +1,5 @@ cl_decals 1 +cl_decals_models 0 cl_decals_time 2 cl_particles_quality 0.4 gl_flashblend 1 @@ -7,14 +8,15 @@ gl_texture_anisotropy 1 mod_q3bsp_nolightmaps 1 r_bloom 0 r_coronas 1 -r_damageblur 0 +r_coronas_occlusionquery 0 +hud_postprocessing_maxbluralpha 0 +hud_powerup 0 r_depthfirst 0 r_drawdecals_drawdistance 200 r_drawparticles_drawdistance 500 r_glsl_deluxemapping 0 r_glsl_offsetmapping 0 r_glsl_offsetmapping_reliefmapping 0 -r_hdr 0 r_motionblur 0 r_shadow_gloss 0 r_shadow_realtime_dlight 0 @@ -29,5 +31,6 @@ r_texture_dds_load 1 r_water 0 r_water_resolutionmultiplier 0.5 vid_samples 1 +r_viewfbo 0 menu_sync diff --git a/effects-med.cfg b/effects-med.cfg index 0914dac600..5be8356e2e 100644 --- a/effects-med.cfg +++ b/effects-med.cfg @@ -1,4 +1,5 @@ cl_decals 1 +cl_decals_models 0 cl_decals_time 2 cl_particles_quality 1 gl_flashblend 0 @@ -7,14 +8,15 @@ gl_texture_anisotropy 1 mod_q3bsp_nolightmaps 0 r_bloom 0 r_coronas 1 -r_damageblur 0 +r_coronas_occlusionquery 0 +hud_postprocessing_maxbluralpha 0 +hud_powerup 0 r_depthfirst 0 r_drawdecals_drawdistance 300 r_drawparticles_drawdistance 1000 r_glsl_deluxemapping 0 r_glsl_offsetmapping 0 r_glsl_offsetmapping_reliefmapping 0 -r_hdr 0 r_motionblur 0 r_shadow_gloss 0 r_shadow_realtime_dlight 1 @@ -29,5 +31,6 @@ r_texture_dds_load 1 r_water 0 r_water_resolutionmultiplier 0.5 vid_samples 1 +r_viewfbo 0 menu_sync diff --git a/effects-normal.cfg b/effects-normal.cfg index 02796ca30a..0aebfb79df 100644 --- a/effects-normal.cfg +++ b/effects-normal.cfg @@ -1,4 +1,5 @@ cl_decals 1 +cl_decals_models 0 cl_decals_time 2 cl_particles_quality 1 gl_flashblend 0 @@ -7,14 +8,15 @@ gl_texture_anisotropy 1 mod_q3bsp_nolightmaps 0 r_bloom 0 r_coronas 1 -r_damageblur 0 +r_coronas_occlusionquery 0 +hud_postprocessing_maxbluralpha 0 +hud_powerup 0 r_depthfirst 1 r_drawdecals_drawdistance 300 r_drawparticles_drawdistance 1000 r_glsl_deluxemapping 1 r_glsl_offsetmapping 0 r_glsl_offsetmapping_reliefmapping 0 -r_hdr 0 r_motionblur 0 r_shadow_gloss 1 r_shadow_realtime_dlight 1 @@ -29,5 +31,6 @@ r_texture_dds_load 1 r_water 0 r_water_resolutionmultiplier 0.5 vid_samples 1 +r_viewfbo 0 menu_sync diff --git a/effects-omg.cfg b/effects-omg.cfg index cf105ba2b4..350e9b8497 100644 --- a/effects-omg.cfg +++ b/effects-omg.cfg @@ -1,4 +1,5 @@ cl_decals 0 +cl_decals_models 0 cl_decals_time 2 cl_particles_quality 0.4 gl_flashblend 1 @@ -7,14 +8,15 @@ gl_texture_anisotropy 1 mod_q3bsp_nolightmaps 1 r_bloom 0 r_coronas 1 -r_damageblur 0 +r_coronas_occlusionquery 0 +hud_postprocessing_maxbluralpha 0 +hud_powerup 0 r_depthfirst 0 r_drawdecals_drawdistance 100 r_drawparticles_drawdistance 250 r_glsl_deluxemapping 0 r_glsl_offsetmapping 0 r_glsl_offsetmapping_reliefmapping 0 -r_hdr 0 r_motionblur 0 r_shadow_gloss 0 r_shadow_realtime_dlight 0 @@ -29,5 +31,6 @@ r_texture_dds_load 1 r_water 0 r_water_resolutionmultiplier 0.5 vid_samples 1 +r_viewfbo 0 menu_sync diff --git a/effects-ultimate.cfg b/effects-ultimate.cfg index 5a6deb9b94..7e4125bf45 100644 --- a/effects-ultimate.cfg +++ b/effects-ultimate.cfg @@ -1,4 +1,5 @@ cl_decals 1 +cl_decals_models 1 cl_decals_time 10 cl_particles_quality 1 gl_flashblend 0 @@ -7,14 +8,15 @@ gl_texture_anisotropy 16 mod_q3bsp_nolightmaps 0 r_bloom 1 r_coronas 1 -r_damageblur 0.4 +r_coronas_occlusionquery 1 +hud_postprocessing_maxbluralpha 0.5 +hud_powerup 0.5 r_depthfirst 2 r_drawdecals_drawdistance 500 r_drawparticles_drawdistance 2000 r_glsl_deluxemapping 1 r_glsl_offsetmapping 1 r_glsl_offsetmapping_reliefmapping 1 -r_hdr 2 r_motionblur 0.5 r_shadow_gloss 1 r_shadow_realtime_dlight 1 @@ -28,6 +30,7 @@ r_subdivisions_tolerance 1 r_texture_dds_load 0 r_water 1 r_water_resolutionmultiplier 1 -vid_samples 4 +vid_samples 1 +r_viewfbo 2 menu_sync diff --git a/effects-ultra.cfg b/effects-ultra.cfg index b6d7f04aa4..1c9b9db301 100644 --- a/effects-ultra.cfg +++ b/effects-ultra.cfg @@ -1,4 +1,5 @@ cl_decals 1 +cl_decals_models 1 cl_decals_time 10 cl_particles_quality 1 gl_flashblend 0 @@ -7,14 +8,15 @@ gl_texture_anisotropy 16 mod_q3bsp_nolightmaps 0 r_bloom 1 r_coronas 1 -r_damageblur 0.4 +r_coronas_occlusionquery 1 +hud_postprocessing_maxbluralpha 0.5 +hud_powerup 0.5 r_depthfirst 2 r_drawdecals_drawdistance 500 r_drawparticles_drawdistance 2000 r_glsl_deluxemapping 1 r_glsl_offsetmapping 1 r_glsl_offsetmapping_reliefmapping 0 -r_hdr 0 r_motionblur 0.5 r_shadow_gloss 1 r_shadow_realtime_dlight 1 @@ -28,6 +30,7 @@ r_subdivisions_tolerance 2 r_texture_dds_load 0 r_water 1 r_water_resolutionmultiplier 0.5 -vid_samples 4 +vid_samples 1 +r_viewfbo 2 menu_sync diff --git a/fixbalance.sh b/fixbalance.sh new file mode 100755 index 0000000000..cfc6cc0ffe --- /dev/null +++ b/fixbalance.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +main=balanceXonotic.cfg +for X in balance*.cfg; do + case "$X" in + "$main") + ;; + *) + perl ../../misc/tools/cfgapply.pl "$main" "$X" > "$X.new" && mv "$X.new" "$X" + ;; + esac +done +git diff diff --git a/fixtooltips.pl b/fixtooltips.pl new file mode 100644 index 0000000000..e7af7b2306 --- /dev/null +++ b/fixtooltips.pl @@ -0,0 +1,28 @@ +use strict; +use warnings; +use Locale::PO; + +sub quote($) +{ + my $s = shift; + $s = '"' . quotemeta($s) . '"'; + return $s; +} +sub unquote($) +{ + my $s = shift; + $s =~ s/^"//; + $s =~ s/"$//; + $s =~ s/\\(.)/$1/g; + return $s; +} +my $po = Locale::PO->load_file_ashash("menu.dat." . $ENV{L} . ".po"); +while(<>) +{ + /\\(.*?)\\(.*)/s or do { print; next; }; + my @s = split /\//, $1; + @s = map { $po->{quote($_)} ? unquote($po->{quote($_)}->msgstr()) : $_ } @s; + my $s = join "/", @s; + $_ = "\\$s\\$2"; + print "$_"; +} diff --git a/gfx/colormap_palette.lmp b/gfx/colormap_palette.lmp index 5450eedccb..f798c8cc84 100644 Binary files a/gfx/colormap_palette.lmp and b/gfx/colormap_palette.lmp differ diff --git a/gfx/colormap_palette.pl b/gfx/colormap_palette.pl index 47986f9f30..07ad2de114 100644 --- a/gfx/colormap_palette.pl +++ b/gfx/colormap_palette.pl @@ -1,29 +1,43 @@ use strict; use warnings; +# Colors: +# red +# ORANGE1 +# ORANGE2 +# yellow +# yellowgreen +# green +# cyangreen +# cyan +# CYANBLUE1 +# CYANBLUE2 +# blue +# bluemagenta +# magenta +# redmagenta + my @colors = ( - 'cccccc', - '996600', - '00ff80', - '00ff00', - 'ff0000', - '00a8ff', # was: 0080ff, green increased - '00ffff', - '80ff00', - '8000ff', - 'ff00ff', - 'ff0080', - '999999', - 'ffff00', - '0050ff', # was: 0000ff, green increased so the color is perceptively just as bright as red (for teamplay) - 'ff8000', - '000000' + 'ffffff', # white + 'ff5500', # orange1 + '00ff80', # cyangreen + '00ff00', # green + 'ff0000', # red + '00aaff', # cyanblue1 + '00ffff', # cyan + '80ff00', # yellowgreen + '8000ff', # bluemagenta + 'ff00ff', # magenta + 'ff0080', # redmagenta + '0000ff', # blue + 'ffff00', # yellow + '0055ff', # cyanblue2 + 'ffaa00', # orange2 + '000000' # unused ); my $value_min = 0x0F; my $value_max = 0xFF; -my $value_smin = 0x00; -my $value_smax = 0xB3; my $i = 0; my $pal_colormap = ""; @@ -35,9 +49,8 @@ for(@colors) my $g = hex $2; my $b = hex $3; $pal_colormap .= sprintf "%c%c%c", map { int(0.5 + $value_min + ($_ * 1.0 / 0xFF) * ($value_max - $value_min)) } $r, $g, $b; - $pal_scoreboard .= sprintf "%c%c%c", map { int(0.5 + $value_smin + ($_ * 1.0 / 0xFF) * ($value_smax - $value_smin)) } $r, $g, $b; printf STDERR "\t\tcase %2d: return '%f %f %f';\n", $i, $r / 0xFF, $g / 0xFF, $b / 0xFF; ++$i; } -print "$pal_colormap$pal_scoreboard$pal_colormap$pal_scoreboard"; +print "$pal_colormap$pal_colormap$pal_colormap$pal_colormap"; diff --git a/gfx/crosshair21.tga b/gfx/crosshair21.tga new file mode 100644 index 0000000000..17e186b4a4 Binary files /dev/null and b/gfx/crosshair21.tga differ diff --git a/gfx/crosshair22.tga b/gfx/crosshair22.tga new file mode 100644 index 0000000000..4dbecc77ba Binary files /dev/null and b/gfx/crosshair22.tga differ diff --git a/gfx/crosshair23.tga b/gfx/crosshair23.tga new file mode 100644 index 0000000000..26328f4c74 Binary files /dev/null and b/gfx/crosshair23.tga differ diff --git a/gfx/crosshair24.tga b/gfx/crosshair24.tga new file mode 100644 index 0000000000..94c928fe30 Binary files /dev/null and b/gfx/crosshair24.tga differ diff --git a/gfx/crosshair25.tga b/gfx/crosshair25.tga new file mode 100644 index 0000000000..495ba6bab6 Binary files /dev/null and b/gfx/crosshair25.tga differ diff --git a/gfx/crosshair26.tga b/gfx/crosshair26.tga new file mode 100644 index 0000000000..6d49c7ed93 Binary files /dev/null and b/gfx/crosshair26.tga differ diff --git a/gfx/crosshair27.tga b/gfx/crosshair27.tga new file mode 100644 index 0000000000..7d4f980ada Binary files /dev/null and b/gfx/crosshair27.tga differ diff --git a/gfx/crosshair28.tga b/gfx/crosshair28.tga new file mode 100644 index 0000000000..16dcc8be26 Binary files /dev/null and b/gfx/crosshair28.tga differ diff --git a/gfx/crosshair_ring_nexgun.tga b/gfx/crosshair_ring_nexgun.tga new file mode 100644 index 0000000000..6100096bf4 Binary files /dev/null and b/gfx/crosshair_ring_nexgun.tga differ diff --git a/gfx/crosshair_ring_rifle.tga b/gfx/crosshair_ring_rifle.tga new file mode 100644 index 0000000000..b25e3509b2 Binary files /dev/null and b/gfx/crosshair_ring_rifle.tga differ diff --git a/gfx/crosshaircampingrifle.tga b/gfx/crosshaircampingrifle.tga deleted file mode 100644 index c304046e80..0000000000 Binary files a/gfx/crosshaircampingrifle.tga and /dev/null differ diff --git a/gfx/crosshairrifle.tga b/gfx/crosshairrifle.tga new file mode 100644 index 0000000000..67a2c85431 Binary files /dev/null and b/gfx/crosshairrifle.tga differ diff --git a/gfx/crosshairt.tga b/gfx/crosshairt.tga new file mode 100644 index 0000000000..2a8b14f9e7 Binary files /dev/null and b/gfx/crosshairt.tga differ diff --git a/gfx/hud/default/accelbar.tga b/gfx/hud/default/accelbar.tga new file mode 100644 index 0000000000..fd938581f2 Binary files /dev/null and b/gfx/hud/default/accelbar.tga differ diff --git a/gfx/hud/default/nametag_statusbar.tga b/gfx/hud/default/nametag_statusbar.tga new file mode 100644 index 0000000000..1f55921b56 Binary files /dev/null and b/gfx/hud/default/nametag_statusbar.tga differ diff --git a/gfx/hud/default/progressbar.tga b/gfx/hud/default/progressbar.tga new file mode 100644 index 0000000000..987c8f544e Binary files /dev/null and b/gfx/hud/default/progressbar.tga differ diff --git a/gfx/hud/default/progressbar_vertical.tga b/gfx/hud/default/progressbar_vertical.tga new file mode 100644 index 0000000000..3c2d1a8e09 Binary files /dev/null and b/gfx/hud/default/progressbar_vertical.tga differ diff --git a/gfx/hud/default/statusbar.tga b/gfx/hud/default/statusbar.tga deleted file mode 100644 index 987c8f544e..0000000000 Binary files a/gfx/hud/default/statusbar.tga and /dev/null differ diff --git a/gfx/hud/default/statusbar_vertical.tga b/gfx/hud/default/statusbar_vertical.tga deleted file mode 100644 index 3c2d1a8e09..0000000000 Binary files a/gfx/hud/default/statusbar_vertical.tga and /dev/null differ diff --git a/gfx/hud/default/weaponcampingrifle.tga b/gfx/hud/default/weaponcampingrifle.tga deleted file mode 100644 index f5c2e55927..0000000000 Binary files a/gfx/hud/default/weaponcampingrifle.tga and /dev/null differ diff --git a/gfx/hud/default/weaponrifle.tga b/gfx/hud/default/weaponrifle.tga new file mode 100644 index 0000000000..f5c2e55927 Binary files /dev/null and b/gfx/hud/default/weaponrifle.tga differ diff --git a/gfx/hud/luminos/accelbar.tga b/gfx/hud/luminos/accelbar.tga new file mode 100644 index 0000000000..fd938581f2 Binary files /dev/null and b/gfx/hud/luminos/accelbar.tga differ diff --git a/gfx/hud/luminos/border_small_healtharmor.tga b/gfx/hud/luminos/border_small_healtharmor.tga new file mode 100644 index 0000000000..e27f2a3963 Binary files /dev/null and b/gfx/hud/luminos/border_small_healtharmor.tga differ diff --git a/gfx/hud/luminos/border_small_modicons.tga b/gfx/hud/luminos/border_small_modicons.tga new file mode 100644 index 0000000000..64d84f06ec Binary files /dev/null and b/gfx/hud/luminos/border_small_modicons.tga differ diff --git a/gfx/hud/luminos/border_small_powerups.tga b/gfx/hud/luminos/border_small_powerups.tga new file mode 100644 index 0000000000..0737860ec2 Binary files /dev/null and b/gfx/hud/luminos/border_small_powerups.tga differ diff --git a/gfx/hud/luminos/border_small_radar.tga b/gfx/hud/luminos/border_small_radar.tga new file mode 100644 index 0000000000..30729f5d00 Binary files /dev/null and b/gfx/hud/luminos/border_small_radar.tga differ diff --git a/gfx/hud/luminos/border_small_score.tga b/gfx/hud/luminos/border_small_score.tga new file mode 100644 index 0000000000..c8c506ca05 Binary files /dev/null and b/gfx/hud/luminos/border_small_score.tga differ diff --git a/gfx/hud/luminos/border_small_timer.tga b/gfx/hud/luminos/border_small_timer.tga new file mode 100644 index 0000000000..c8c506ca05 Binary files /dev/null and b/gfx/hud/luminos/border_small_timer.tga differ diff --git a/gfx/hud/luminos/border_small_weapons.tga b/gfx/hud/luminos/border_small_weapons.tga new file mode 100644 index 0000000000..d0b58a855c Binary files /dev/null and b/gfx/hud/luminos/border_small_weapons.tga differ diff --git a/gfx/hud/luminos/dom_icon_blue-highlighted.tga b/gfx/hud/luminos/dom_icon_blue-highlighted.tga new file mode 100644 index 0000000000..db2e356322 Binary files /dev/null and b/gfx/hud/luminos/dom_icon_blue-highlighted.tga differ diff --git a/gfx/hud/luminos/dom_icon_blue.tga b/gfx/hud/luminos/dom_icon_blue.tga new file mode 100644 index 0000000000..c78f373d34 Binary files /dev/null and b/gfx/hud/luminos/dom_icon_blue.tga differ diff --git a/gfx/hud/luminos/dom_icon_pink-highlighted.tga b/gfx/hud/luminos/dom_icon_pink-highlighted.tga new file mode 100644 index 0000000000..35640195f8 Binary files /dev/null and b/gfx/hud/luminos/dom_icon_pink-highlighted.tga differ diff --git a/gfx/hud/luminos/dom_icon_pink.tga b/gfx/hud/luminos/dom_icon_pink.tga new file mode 100644 index 0000000000..be51849280 Binary files /dev/null and b/gfx/hud/luminos/dom_icon_pink.tga differ diff --git a/gfx/hud/luminos/dom_icon_red-highlighted.tga b/gfx/hud/luminos/dom_icon_red-highlighted.tga new file mode 100644 index 0000000000..ea4415e975 Binary files /dev/null and b/gfx/hud/luminos/dom_icon_red-highlighted.tga differ diff --git a/gfx/hud/luminos/dom_icon_red.tga b/gfx/hud/luminos/dom_icon_red.tga new file mode 100644 index 0000000000..58a1fe22a6 Binary files /dev/null and b/gfx/hud/luminos/dom_icon_red.tga differ diff --git a/gfx/hud/luminos/dom_icon_yellow-highlighted.tga b/gfx/hud/luminos/dom_icon_yellow-highlighted.tga new file mode 100644 index 0000000000..90be4ac577 Binary files /dev/null and b/gfx/hud/luminos/dom_icon_yellow-highlighted.tga differ diff --git a/gfx/hud/luminos/dom_icon_yellow.tga b/gfx/hud/luminos/dom_icon_yellow.tga new file mode 100644 index 0000000000..4d115054d5 Binary files /dev/null and b/gfx/hud/luminos/dom_icon_yellow.tga differ diff --git a/gfx/hud/luminos/nametag_statusbar.tga b/gfx/hud/luminos/nametag_statusbar.tga new file mode 100644 index 0000000000..1f55921b56 Binary files /dev/null and b/gfx/hud/luminos/nametag_statusbar.tga differ diff --git a/gfx/hud/luminos/progressbar.tga b/gfx/hud/luminos/progressbar.tga new file mode 100644 index 0000000000..987c8f544e Binary files /dev/null and b/gfx/hud/luminos/progressbar.tga differ diff --git a/gfx/hud/luminos/progressbar_vertical.tga b/gfx/hud/luminos/progressbar_vertical.tga new file mode 100644 index 0000000000..3c2d1a8e09 Binary files /dev/null and b/gfx/hud/luminos/progressbar_vertical.tga differ diff --git a/gfx/hud/luminos/shield.tga b/gfx/hud/luminos/shield.tga new file mode 100644 index 0000000000..f13f0b4d84 Binary files /dev/null and b/gfx/hud/luminos/shield.tga differ diff --git a/gfx/hud/luminos/statusbar.tga b/gfx/hud/luminos/statusbar.tga deleted file mode 100644 index 987c8f544e..0000000000 Binary files a/gfx/hud/luminos/statusbar.tga and /dev/null differ diff --git a/gfx/hud/luminos/statusbar_vertical.tga b/gfx/hud/luminos/statusbar_vertical.tga deleted file mode 100644 index 3c2d1a8e09..0000000000 Binary files a/gfx/hud/luminos/statusbar_vertical.tga and /dev/null differ diff --git a/gfx/hud/luminos/strength.tga b/gfx/hud/luminos/strength.tga new file mode 100644 index 0000000000..b19019d5d7 Binary files /dev/null and b/gfx/hud/luminos/strength.tga differ diff --git a/gfx/hud/luminos/weaponcampingrifle.tga b/gfx/hud/luminos/weaponcampingrifle.tga deleted file mode 100644 index f5c2e55927..0000000000 Binary files a/gfx/hud/luminos/weaponcampingrifle.tga and /dev/null differ diff --git a/gfx/hud/luminos/weaponrifle.tga b/gfx/hud/luminos/weaponrifle.tga new file mode 100644 index 0000000000..f5c2e55927 Binary files /dev/null and b/gfx/hud/luminos/weaponrifle.tga differ diff --git a/gfx/hud/old/accelbar.tga b/gfx/hud/old/accelbar.tga new file mode 100644 index 0000000000..0bbad1787c Binary files /dev/null and b/gfx/hud/old/accelbar.tga differ diff --git a/gfx/hud/old/dom_icon_blue-highlighted.tga b/gfx/hud/old/dom_icon_blue-highlighted.tga new file mode 100644 index 0000000000..a1ee2f0194 Binary files /dev/null and b/gfx/hud/old/dom_icon_blue-highlighted.tga differ diff --git a/gfx/hud/old/dom_icon_blue.tga b/gfx/hud/old/dom_icon_blue.tga new file mode 100644 index 0000000000..9524e70c6d Binary files /dev/null and b/gfx/hud/old/dom_icon_blue.tga differ diff --git a/gfx/hud/old/dom_icon_pink-highlighted.tga b/gfx/hud/old/dom_icon_pink-highlighted.tga new file mode 100644 index 0000000000..748e2adaba Binary files /dev/null and b/gfx/hud/old/dom_icon_pink-highlighted.tga differ diff --git a/gfx/hud/old/dom_icon_pink.tga b/gfx/hud/old/dom_icon_pink.tga new file mode 100644 index 0000000000..504c849e47 Binary files /dev/null and b/gfx/hud/old/dom_icon_pink.tga differ diff --git a/gfx/hud/old/dom_icon_red-highlighted.tga b/gfx/hud/old/dom_icon_red-highlighted.tga new file mode 100644 index 0000000000..cba4b3bc39 Binary files /dev/null and b/gfx/hud/old/dom_icon_red-highlighted.tga differ diff --git a/gfx/hud/old/dom_icon_red.tga b/gfx/hud/old/dom_icon_red.tga new file mode 100644 index 0000000000..566614d6cb Binary files /dev/null and b/gfx/hud/old/dom_icon_red.tga differ diff --git a/gfx/hud/old/dom_icon_yellow-highlighted.tga b/gfx/hud/old/dom_icon_yellow-highlighted.tga new file mode 100644 index 0000000000..02e7fb8ce0 Binary files /dev/null and b/gfx/hud/old/dom_icon_yellow-highlighted.tga differ diff --git a/gfx/hud/old/dom_icon_yellow.tga b/gfx/hud/old/dom_icon_yellow.tga new file mode 100644 index 0000000000..ef8fa8defd Binary files /dev/null and b/gfx/hud/old/dom_icon_yellow.tga differ diff --git a/gfx/hud/old/progressbar.tga b/gfx/hud/old/progressbar.tga new file mode 100644 index 0000000000..0bbad1787c Binary files /dev/null and b/gfx/hud/old/progressbar.tga differ diff --git a/gfx/hud/old/progressbar_vertical.tga b/gfx/hud/old/progressbar_vertical.tga new file mode 100644 index 0000000000..d63a37fc06 Binary files /dev/null and b/gfx/hud/old/progressbar_vertical.tga differ diff --git a/gfx/hud/old/statusbar.tga b/gfx/hud/old/statusbar.tga deleted file mode 100644 index 0bbad1787c..0000000000 Binary files a/gfx/hud/old/statusbar.tga and /dev/null differ diff --git a/gfx/hud/old/statusbar_vertical.tga b/gfx/hud/old/statusbar_vertical.tga deleted file mode 100644 index d63a37fc06..0000000000 Binary files a/gfx/hud/old/statusbar_vertical.tga and /dev/null differ diff --git a/gfx/hud/old/weaponcampingrifle.tga b/gfx/hud/old/weaponcampingrifle.tga deleted file mode 100644 index 09da559dcf..0000000000 Binary files a/gfx/hud/old/weaponcampingrifle.tga and /dev/null differ diff --git a/gfx/hud/old/weaponrifle.tga b/gfx/hud/old/weaponrifle.tga new file mode 100644 index 0000000000..09da559dcf Binary files /dev/null and b/gfx/hud/old/weaponrifle.tga differ diff --git a/gfx/loading.tga b/gfx/loading.tga index 44ebb5294a..3b0020261a 100644 Binary files a/gfx/loading.tga and b/gfx/loading.tga differ diff --git a/gfx/loading10.tga b/gfx/loading10.tga new file mode 100644 index 0000000000..9f8b8ae794 Binary files /dev/null and b/gfx/loading10.tga differ diff --git a/gfx/loading11.tga b/gfx/loading11.tga new file mode 100644 index 0000000000..5ca3f38490 Binary files /dev/null and b/gfx/loading11.tga differ diff --git a/gfx/loading12.tga b/gfx/loading12.tga new file mode 100644 index 0000000000..6ef7330ace Binary files /dev/null and b/gfx/loading12.tga differ diff --git a/gfx/loading13.tga b/gfx/loading13.tga new file mode 100644 index 0000000000..800ddb7684 Binary files /dev/null and b/gfx/loading13.tga differ diff --git a/gfx/loading2.tga b/gfx/loading2.tga new file mode 100644 index 0000000000..6b2387f1c8 Binary files /dev/null and b/gfx/loading2.tga differ diff --git a/gfx/loading3.tga b/gfx/loading3.tga new file mode 100644 index 0000000000..256f8cc699 Binary files /dev/null and b/gfx/loading3.tga differ diff --git a/gfx/loading4.tga b/gfx/loading4.tga new file mode 100644 index 0000000000..f6b16330f8 Binary files /dev/null and b/gfx/loading4.tga differ diff --git a/gfx/loading5.tga b/gfx/loading5.tga new file mode 100644 index 0000000000..11e7ada0f5 Binary files /dev/null and b/gfx/loading5.tga differ diff --git a/gfx/loading6.tga b/gfx/loading6.tga new file mode 100644 index 0000000000..7997387c3c Binary files /dev/null and b/gfx/loading6.tga differ diff --git a/gfx/loading7.tga b/gfx/loading7.tga new file mode 100644 index 0000000000..92c54d51ff Binary files /dev/null and b/gfx/loading7.tga differ diff --git a/gfx/loading8.tga b/gfx/loading8.tga new file mode 100644 index 0000000000..94886a7928 Binary files /dev/null and b/gfx/loading8.tga differ diff --git a/gfx/loading9.tga b/gfx/loading9.tga new file mode 100644 index 0000000000..9e358361ce Binary files /dev/null and b/gfx/loading9.tga differ diff --git a/gfx/m_nomap.jpg b/gfx/m_nomap.jpg deleted file mode 100644 index 79675d690b..0000000000 Binary files a/gfx/m_nomap.jpg and /dev/null differ diff --git a/gfx/menu/default/background.tga b/gfx/menu/default/background.tga deleted file mode 100644 index d785d644b8..0000000000 Binary files a/gfx/menu/default/background.tga and /dev/null differ diff --git a/gfx/menu/default/background_ingame.tga b/gfx/menu/default/background_ingame.tga deleted file mode 100644 index 2532d1799d..0000000000 Binary files a/gfx/menu/default/background_ingame.tga and /dev/null differ diff --git a/gfx/menu/default/background_l2.tga b/gfx/menu/default/background_l2.tga deleted file mode 100644 index 2532d1799d..0000000000 Binary files a/gfx/menu/default/background_l2.tga and /dev/null differ diff --git a/gfx/menu/default/bigbutton_c.tga b/gfx/menu/default/bigbutton_c.tga deleted file mode 100644 index a8bf8ad91a..0000000000 Binary files a/gfx/menu/default/bigbutton_c.tga and /dev/null differ diff --git a/gfx/menu/default/bigbutton_d.tga b/gfx/menu/default/bigbutton_d.tga deleted file mode 100644 index f6a832bb75..0000000000 Binary files a/gfx/menu/default/bigbutton_d.tga and /dev/null differ diff --git a/gfx/menu/default/bigbutton_f.tga b/gfx/menu/default/bigbutton_f.tga deleted file mode 100644 index c4cda968c9..0000000000 Binary files a/gfx/menu/default/bigbutton_f.tga and /dev/null differ diff --git a/gfx/menu/default/bigbutton_n.tga b/gfx/menu/default/bigbutton_n.tga deleted file mode 100644 index d54d5d5c0e..0000000000 Binary files a/gfx/menu/default/bigbutton_n.tga and /dev/null differ diff --git a/gfx/menu/default/bigbuttongray_c.tga b/gfx/menu/default/bigbuttongray_c.tga deleted file mode 100644 index 38e9653b02..0000000000 Binary files a/gfx/menu/default/bigbuttongray_c.tga and /dev/null differ diff --git a/gfx/menu/default/bigbuttongray_d.tga b/gfx/menu/default/bigbuttongray_d.tga deleted file mode 100644 index 959ef93c32..0000000000 Binary files a/gfx/menu/default/bigbuttongray_d.tga and /dev/null differ diff --git a/gfx/menu/default/bigbuttongray_f.tga b/gfx/menu/default/bigbuttongray_f.tga deleted file mode 100644 index 55ff591b7a..0000000000 Binary files a/gfx/menu/default/bigbuttongray_f.tga and /dev/null differ diff --git a/gfx/menu/default/bigbuttongray_n.tga b/gfx/menu/default/bigbuttongray_n.tga deleted file mode 100644 index edff6d6a8c..0000000000 Binary files a/gfx/menu/default/bigbuttongray_n.tga and /dev/null differ diff --git a/gfx/menu/default/border.tga b/gfx/menu/default/border.tga deleted file mode 100644 index d435e60196..0000000000 Binary files a/gfx/menu/default/border.tga and /dev/null differ diff --git a/gfx/menu/default/button_c.tga b/gfx/menu/default/button_c.tga deleted file mode 100644 index 745ee7c1d2..0000000000 Binary files a/gfx/menu/default/button_c.tga and /dev/null differ diff --git a/gfx/menu/default/button_d.tga b/gfx/menu/default/button_d.tga deleted file mode 100644 index 6639525e52..0000000000 Binary files a/gfx/menu/default/button_d.tga and /dev/null differ diff --git a/gfx/menu/default/button_f.tga b/gfx/menu/default/button_f.tga deleted file mode 100644 index 817d849216..0000000000 Binary files a/gfx/menu/default/button_f.tga and /dev/null differ diff --git a/gfx/menu/default/button_n.tga b/gfx/menu/default/button_n.tga deleted file mode 100644 index 643360e270..0000000000 Binary files a/gfx/menu/default/button_n.tga and /dev/null differ diff --git a/gfx/menu/default/buttongray_c.tga b/gfx/menu/default/buttongray_c.tga deleted file mode 100644 index 032ea91d27..0000000000 Binary files a/gfx/menu/default/buttongray_c.tga and /dev/null differ diff --git a/gfx/menu/default/buttongray_d.tga b/gfx/menu/default/buttongray_d.tga deleted file mode 100644 index 55f1e622a7..0000000000 Binary files a/gfx/menu/default/buttongray_d.tga and /dev/null differ diff --git a/gfx/menu/default/buttongray_f.tga b/gfx/menu/default/buttongray_f.tga deleted file mode 100644 index 5ed3a7dfc9..0000000000 Binary files a/gfx/menu/default/buttongray_f.tga and /dev/null differ diff --git a/gfx/menu/default/buttongray_n.tga b/gfx/menu/default/buttongray_n.tga deleted file mode 100644 index 6ba22b53c0..0000000000 Binary files a/gfx/menu/default/buttongray_n.tga and /dev/null differ diff --git a/gfx/menu/default/charmap.tga b/gfx/menu/default/charmap.tga deleted file mode 100755 index d8ed1d5de9..0000000000 Binary files a/gfx/menu/default/charmap.tga and /dev/null differ diff --git a/gfx/menu/default/charmapbutton.tga b/gfx/menu/default/charmapbutton.tga deleted file mode 100644 index 54fe07eb75..0000000000 Binary files a/gfx/menu/default/charmapbutton.tga and /dev/null differ diff --git a/gfx/menu/default/checkbox_c0.tga b/gfx/menu/default/checkbox_c0.tga deleted file mode 100644 index aafd08943f..0000000000 Binary files a/gfx/menu/default/checkbox_c0.tga and /dev/null differ diff --git a/gfx/menu/default/checkbox_c1.tga b/gfx/menu/default/checkbox_c1.tga deleted file mode 100644 index 4e517e2464..0000000000 Binary files a/gfx/menu/default/checkbox_c1.tga and /dev/null differ diff --git a/gfx/menu/default/checkbox_d0.tga b/gfx/menu/default/checkbox_d0.tga deleted file mode 100644 index 40efe7a6bb..0000000000 Binary files a/gfx/menu/default/checkbox_d0.tga and /dev/null differ diff --git a/gfx/menu/default/checkbox_d1.tga b/gfx/menu/default/checkbox_d1.tga deleted file mode 100644 index bba682482d..0000000000 Binary files a/gfx/menu/default/checkbox_d1.tga and /dev/null differ diff --git a/gfx/menu/default/checkbox_f0.tga b/gfx/menu/default/checkbox_f0.tga deleted file mode 100644 index aafd08943f..0000000000 Binary files a/gfx/menu/default/checkbox_f0.tga and /dev/null differ diff --git a/gfx/menu/default/checkbox_f1.tga b/gfx/menu/default/checkbox_f1.tga deleted file mode 100644 index 4e517e2464..0000000000 Binary files a/gfx/menu/default/checkbox_f1.tga and /dev/null differ diff --git a/gfx/menu/default/checkbox_n0.tga b/gfx/menu/default/checkbox_n0.tga deleted file mode 100644 index aafd08943f..0000000000 Binary files a/gfx/menu/default/checkbox_n0.tga and /dev/null differ diff --git a/gfx/menu/default/checkbox_n1.tga b/gfx/menu/default/checkbox_n1.tga deleted file mode 100644 index 4e517e2464..0000000000 Binary files a/gfx/menu/default/checkbox_n1.tga and /dev/null differ diff --git a/gfx/menu/default/checkmark.tga b/gfx/menu/default/checkmark.tga deleted file mode 100644 index cf34dde26a..0000000000 Binary files a/gfx/menu/default/checkmark.tga and /dev/null differ diff --git a/gfx/menu/default/closebutton_c.tga b/gfx/menu/default/closebutton_c.tga deleted file mode 100644 index 56488eca61..0000000000 Binary files a/gfx/menu/default/closebutton_c.tga and /dev/null differ diff --git a/gfx/menu/default/closebutton_f.tga b/gfx/menu/default/closebutton_f.tga deleted file mode 100644 index 73385736ab..0000000000 Binary files a/gfx/menu/default/closebutton_f.tga and /dev/null differ diff --git a/gfx/menu/default/closebutton_n.tga b/gfx/menu/default/closebutton_n.tga deleted file mode 100644 index e4b6058094..0000000000 Binary files a/gfx/menu/default/closebutton_n.tga and /dev/null differ diff --git a/gfx/menu/default/color.tga b/gfx/menu/default/color.tga deleted file mode 100755 index 5189ab4963..0000000000 Binary files a/gfx/menu/default/color.tga and /dev/null differ diff --git a/gfx/menu/default/colorbutton_c.tga b/gfx/menu/default/colorbutton_c.tga deleted file mode 100644 index 1c294f77f5..0000000000 Binary files a/gfx/menu/default/colorbutton_c.tga and /dev/null differ diff --git a/gfx/menu/default/colorbutton_f.tga b/gfx/menu/default/colorbutton_f.tga deleted file mode 100644 index 0031c35e35..0000000000 Binary files a/gfx/menu/default/colorbutton_f.tga and /dev/null differ diff --git a/gfx/menu/default/colorbutton_n.tga b/gfx/menu/default/colorbutton_n.tga deleted file mode 100755 index 7fec859bcc..0000000000 Binary files a/gfx/menu/default/colorbutton_n.tga and /dev/null differ diff --git a/gfx/menu/default/colorpicker.tga b/gfx/menu/default/colorpicker.tga deleted file mode 100755 index 6f9845bf3e..0000000000 Binary files a/gfx/menu/default/colorpicker.tga and /dev/null differ diff --git a/gfx/menu/default/colorpicker_m.tga b/gfx/menu/default/colorpicker_m.tga deleted file mode 100755 index 79b0e83b7d..0000000000 Binary files a/gfx/menu/default/colorpicker_m.tga and /dev/null differ diff --git a/gfx/menu/default/colorpicker_selected.tga b/gfx/menu/default/colorpicker_selected.tga deleted file mode 100644 index 605e932017..0000000000 Binary files a/gfx/menu/default/colorpicker_selected.tga and /dev/null differ diff --git a/gfx/menu/default/crosshairbutton_c.tga b/gfx/menu/default/crosshairbutton_c.tga deleted file mode 100644 index 1c294f77f5..0000000000 Binary files a/gfx/menu/default/crosshairbutton_c.tga and /dev/null differ diff --git a/gfx/menu/default/crosshairbutton_d.tga b/gfx/menu/default/crosshairbutton_d.tga deleted file mode 100755 index 110faa18b5..0000000000 Binary files a/gfx/menu/default/crosshairbutton_d.tga and /dev/null differ diff --git a/gfx/menu/default/crosshairbutton_f.tga b/gfx/menu/default/crosshairbutton_f.tga deleted file mode 100644 index 0031c35e35..0000000000 Binary files a/gfx/menu/default/crosshairbutton_f.tga and /dev/null differ diff --git a/gfx/menu/default/crosshairbutton_n.tga b/gfx/menu/default/crosshairbutton_n.tga deleted file mode 100755 index ac945355ef..0000000000 Binary files a/gfx/menu/default/crosshairbutton_n.tga and /dev/null differ diff --git a/gfx/menu/default/cursor.tga b/gfx/menu/default/cursor.tga deleted file mode 100644 index 0a2e29514d..0000000000 Binary files a/gfx/menu/default/cursor.tga and /dev/null differ diff --git a/gfx/menu/default/cursor_move.tga b/gfx/menu/default/cursor_move.tga deleted file mode 100644 index 02643169b2..0000000000 Binary files a/gfx/menu/default/cursor_move.tga and /dev/null differ diff --git a/gfx/menu/default/cursor_resize.tga b/gfx/menu/default/cursor_resize.tga deleted file mode 100644 index 475e2244ff..0000000000 Binary files a/gfx/menu/default/cursor_resize.tga and /dev/null differ diff --git a/gfx/menu/default/cursor_resize2.tga b/gfx/menu/default/cursor_resize2.tga deleted file mode 100644 index 6c97fb8d14..0000000000 Binary files a/gfx/menu/default/cursor_resize2.tga and /dev/null differ diff --git a/gfx/menu/default/icon_aeslevel0.tga b/gfx/menu/default/icon_aeslevel0.tga deleted file mode 100644 index 5c9e66ac67..0000000000 Binary files a/gfx/menu/default/icon_aeslevel0.tga and /dev/null differ diff --git a/gfx/menu/default/icon_aeslevel1.tga b/gfx/menu/default/icon_aeslevel1.tga deleted file mode 100644 index 7103e55b74..0000000000 Binary files a/gfx/menu/default/icon_aeslevel1.tga and /dev/null differ diff --git a/gfx/menu/default/icon_aeslevel2.tga b/gfx/menu/default/icon_aeslevel2.tga deleted file mode 100644 index 793b457692..0000000000 Binary files a/gfx/menu/default/icon_aeslevel2.tga and /dev/null differ diff --git a/gfx/menu/default/icon_aeslevel3.tga b/gfx/menu/default/icon_aeslevel3.tga deleted file mode 100644 index ec2f15bf2f..0000000000 Binary files a/gfx/menu/default/icon_aeslevel3.tga and /dev/null differ diff --git a/gfx/menu/default/icon_aeslevel4.tga b/gfx/menu/default/icon_aeslevel4.tga deleted file mode 100644 index 8f7f4669b8..0000000000 Binary files a/gfx/menu/default/icon_aeslevel4.tga and /dev/null differ diff --git a/gfx/menu/default/icon_aeslevel5.tga b/gfx/menu/default/icon_aeslevel5.tga deleted file mode 100644 index 8662b137b6..0000000000 Binary files a/gfx/menu/default/icon_aeslevel5.tga and /dev/null differ diff --git a/gfx/menu/default/icon_ipv4.tga b/gfx/menu/default/icon_ipv4.tga deleted file mode 100644 index a0484f4e37..0000000000 Binary files a/gfx/menu/default/icon_ipv4.tga and /dev/null differ diff --git a/gfx/menu/default/icon_ipv6.tga b/gfx/menu/default/icon_ipv6.tga deleted file mode 100644 index d3fdc03ee3..0000000000 Binary files a/gfx/menu/default/icon_ipv6.tga and /dev/null differ diff --git a/gfx/menu/default/icon_pure0.tga b/gfx/menu/default/icon_pure0.tga deleted file mode 100644 index 5c9e66ac67..0000000000 Binary files a/gfx/menu/default/icon_pure0.tga and /dev/null differ diff --git a/gfx/menu/default/icon_pure1.tga b/gfx/menu/default/icon_pure1.tga deleted file mode 100644 index 62980d257a..0000000000 Binary files a/gfx/menu/default/icon_pure1.tga and /dev/null differ diff --git a/gfx/menu/default/inputbox_f.tga b/gfx/menu/default/inputbox_f.tga deleted file mode 100644 index 6b5bd201fe..0000000000 Binary files a/gfx/menu/default/inputbox_f.tga and /dev/null differ diff --git a/gfx/menu/default/inputbox_n.tga b/gfx/menu/default/inputbox_n.tga deleted file mode 100644 index ad169c2083..0000000000 Binary files a/gfx/menu/default/inputbox_n.tga and /dev/null differ diff --git a/gfx/menu/default/radiobutton_c0.tga b/gfx/menu/default/radiobutton_c0.tga deleted file mode 100644 index 68ed15e696..0000000000 Binary files a/gfx/menu/default/radiobutton_c0.tga and /dev/null differ diff --git a/gfx/menu/default/radiobutton_c1.tga b/gfx/menu/default/radiobutton_c1.tga deleted file mode 100644 index 68ed15e696..0000000000 Binary files a/gfx/menu/default/radiobutton_c1.tga and /dev/null differ diff --git a/gfx/menu/default/radiobutton_d0.tga b/gfx/menu/default/radiobutton_d0.tga deleted file mode 100644 index f935318b30..0000000000 Binary files a/gfx/menu/default/radiobutton_d0.tga and /dev/null differ diff --git a/gfx/menu/default/radiobutton_d1.tga b/gfx/menu/default/radiobutton_d1.tga deleted file mode 100644 index 1bcc41d0fc..0000000000 Binary files a/gfx/menu/default/radiobutton_d1.tga and /dev/null differ diff --git a/gfx/menu/default/radiobutton_f0.tga b/gfx/menu/default/radiobutton_f0.tga deleted file mode 100644 index 237e09b0e2..0000000000 Binary files a/gfx/menu/default/radiobutton_f0.tga and /dev/null differ diff --git a/gfx/menu/default/radiobutton_f1.tga b/gfx/menu/default/radiobutton_f1.tga deleted file mode 100644 index 68ed15e696..0000000000 Binary files a/gfx/menu/default/radiobutton_f1.tga and /dev/null differ diff --git a/gfx/menu/default/radiobutton_n0.tga b/gfx/menu/default/radiobutton_n0.tga deleted file mode 100644 index 55dae24026..0000000000 Binary files a/gfx/menu/default/radiobutton_n0.tga and /dev/null differ diff --git a/gfx/menu/default/radiobutton_n1.tga b/gfx/menu/default/radiobutton_n1.tga deleted file mode 100644 index 68ed15e696..0000000000 Binary files a/gfx/menu/default/radiobutton_n1.tga and /dev/null differ diff --git a/gfx/menu/default/scrollbar_c.tga b/gfx/menu/default/scrollbar_c.tga deleted file mode 100644 index eb4326dfb6..0000000000 Binary files a/gfx/menu/default/scrollbar_c.tga and /dev/null differ diff --git a/gfx/menu/default/scrollbar_f.tga b/gfx/menu/default/scrollbar_f.tga deleted file mode 100644 index eb4326dfb6..0000000000 Binary files a/gfx/menu/default/scrollbar_f.tga and /dev/null differ diff --git a/gfx/menu/default/scrollbar_n.tga b/gfx/menu/default/scrollbar_n.tga deleted file mode 100644 index eb4326dfb6..0000000000 Binary files a/gfx/menu/default/scrollbar_n.tga and /dev/null differ diff --git a/gfx/menu/default/scrollbar_s.tga b/gfx/menu/default/scrollbar_s.tga deleted file mode 100644 index c7d47005e6..0000000000 Binary files a/gfx/menu/default/scrollbar_s.tga and /dev/null differ diff --git a/gfx/menu/default/skinpreview.jpg b/gfx/menu/default/skinpreview.jpg deleted file mode 100755 index 9b8e393898..0000000000 Binary files a/gfx/menu/default/skinpreview.jpg and /dev/null differ diff --git a/gfx/menu/default/skinvalues.txt b/gfx/menu/default/skinvalues.txt deleted file mode 100755 index 8e0f548a70..0000000000 --- a/gfx/menu/default/skinvalues.txt +++ /dev/null @@ -1,224 +0,0 @@ -title Default // "WickedX" -author sev - -// Colors: 'Red Green Blue' -// Suffixes: Clicked (_c), Disabled (_d), Focused (_f), Normal (_n) - -// Background layer scaling: -// Crop (c), Letterbox (l), Height (h), Width (w), Stretch (s) -// Background layer positioning: -// Top Left (7), Top Center (8) Top Right (9) -// Middle Left (4), Middle Center (5) Middle Right (6) -// Bottom Left (1), Bottom Center (2) Bottom Right (3) -// ALIGN_BACKGROUND(_INGAME) spspsp, s=Scale p=Position - -//------------------------------------------------------------------------------ -// Structure (e.g. positions, sizes, margins) -//------------------------------------------------------------------------------ -// item: color picker -// uses "colorpicker" images -MARGIN_COLORPICKER '0 0 0' - -// item: dialog -// uses "border" images -// uses "closebutton" images -MARGIN_TOP 8 -MARGIN_BOTTOM 8 -MARGIN_LEFT 8 -MARGIN_RIGHT 8 -MARGIN_COLUMNS 4 -MARGIN_ROWS 4 -HEIGHT_DIALOGBORDER 1 - -// font sizes (used for everything) -FONTSIZE_NORMAL 12 -HEIGHT_NORMAL 1.5 -FONTSIZE_TITLE 16 -HEIGHT_TITLE 1.5 -HEIGHT_ZOOMEDTITLE -1 - -// general -// uses "background" images -// uses "background_ingame" images -ALIGN_BACKGROUND h5h5 -ALIGN_BACKGROUND_INGAME h5 -ALPHA_BACKGROUND_INGAME 1 -ALPHA_DISABLED 0.2 -ALPHA_BEHIND 0.5 -ALPHA_TEXT 0.7 - -// mouse -// uses "cursor" images -SIZE_CURSOR '32 32 0' -OFFSET_CURSOR '0 0 0' -ALPHA_CURSOR_INTRO 0 - -// nexposee positions of windows (they are the scale transformation -// centers, NOT the actual positions of the windows!) -POSITION_DIALOG_MULTIPLAYER '0.8 0.4 0' -POSITION_DIALOG_SINGLEPLAYER '0.2 0.4 0' -POSITION_DIALOG_SETTINGS '0.5 0.95 0' -POSITION_DIALOG_CREDITS '-0.05 1.2 0' -POSITION_DIALOG_QUIT '1.05 1.2 0' - -// tooltips -// uses "tooltip" images -MARGIN_TOOLTIP '8 8 0' -BORDER_TOOLTIP '16 16 0' -FONTSIZE_TOOLTIP 12 -ALPHA_TOOLTIP 0.7 -WIDTH_TOOLTIP 0.3 -AVOID_TOOLTIP '8 8 0' - -//------------------------------------------------------------------------------ -// Colors (e.g. font colors, field colors) -//------------------------------------------------------------------------------ -// item: campaign -ALPHA_CAMPAIGN_SELECTABLE 0.8 -COLOR_CAMPAIGN_SELECTABLE '1 1 1' -ALPHA_CAMPAIGN_CURRENT 1 -COLOR_CAMPAIGN_CURRENT '1 1 1' -ALPHA_CAMPAIGN_FUTURE 0.2 -COLOR_CAMPAIGN_FUTURE '1 1 1' -ALPHA_CAMPAIGN_DESCRIPTION 0.7 - -// item: credits list -COLOR_CREDITS_TITLE '0.875 0.375 0' -ALPHA_CREDITS_TITLE 1 -COLOR_CREDITS_FUNCTION '0 0.1875 0.4375' -ALPHA_CREDITS_FUNCTION 0.5 -COLOR_CREDITS_PERSON '0 0.375 0.75' -ALPHA_CREDITS_PERSON 0.875 -ROWS_CREDITS 20 -WIDTH_CREDITS 0.5 - -// item: cvar list -ALPHA_CVARLIST_SAVED 1 -ALPHA_CVARLIST_TEMPORARY 0.7 -COLOR_CVARLIST_CHANGED '0 0.375 0.75' -COLOR_CVARLIST_REVERTBUTTON '1 0 0' -COLOR_CVARLIST_UNCHANGED '1 1 1' - -// item: list box -COLOR_LISTBOX_SELECTED '0.875 0.375 0' -ALPHA_LISTBOX_SELECTED 1 -COLOR_LISTBOX_WAITING '1 1 1' -ALPHA_LISTBOX_WAITING 0.5 - -// item: map list -COLOR_MAPLIST_TITLE '1 1 1' -COLOR_MAPLIST_AUTHOR '0 0.375 0.75' -COLOR_MAPLIST_INCLUDEDBG '0 0.1875 0.4375' -ALPHA_MAPLIST_INCLUDEDFG 1 -ALPHA_MAPLIST_INCLUDEDBG 0.375 -ALPHA_MAPLIST_NOTINCLUDEDFG 0.25 - -// item: nexposee -ALPHAS_MAINMENU '0.8 0.9 1' - -// item: player model -COLOR_MODELTITLE '1 1 1' -ALPHA_MODELTITLE 1 - -// item: server info -COLOR_SERVERINFO_NAME '1 1 1' -COLOR_SERVERINFO_IP '0.875 0.375 0' - -// item: server list -ALPHA_SERVERLIST_FULL 0.4 -ALPHA_SERVERLIST_EMPTY 0.7 -COLOR_SERVERLIST_LOWPING '0 1 0' -COLOR_SERVERLIST_MEDPING '1 0.75 0' -COLOR_SERVERLIST_HIGHPING '1 0 0' -ALPHA_SERVERLIST_HIGHPING 0.4 -ALPHA_SERVERLIST_FAVORITE 0.8 -COLOR_SERVERLIST_FAVORITE '1 1 1' - -// item: skin list -COLOR_SKINLIST_TITLE '1 1 1' -COLOR_SKINLIST_AUTHOR '0 0.375 0.75' - -//------------------------------------------------------------------------------ -// Images (colors multiplied to images) -//------------------------------------------------------------------------------ -// item: button -// uses "button" images -// uses "buttongray" images -// uses "bigbutton" images -// uses "bigbuttongray" images -COLOR_BUTTON_N '1 1 1' -COLOR_BUTTON_C '1 1 1' -COLOR_BUTTON_F '1 1 1' -COLOR_BUTTON_D '1 1 1' - -// item: checkbox -// uses "checkbox" images -COLOR_CHECKBOX_N '1 1 1' -COLOR_CHECKBOX_C '0.5 0.75 1' -COLOR_CHECKBOX_F '0.5 0.75 1' -COLOR_CHECKBOX_D '1 1 1' - -// item: crosshair button -// uses "crosshairbutton" images - -// dialog background colors -// uses "border" images -COLOR_DIALOG_MULTIPLAYER '1 1 1' -COLOR_DIALOG_SETTINGS '1 1 1' -COLOR_DIALOG_TEAMSELECT '1 1 1' -COLOR_DIALOG_QUIT '1 1 1' -COLOR_DIALOG_ADVANCED '1 1 1' -COLOR_DIALOG_MUTATORS '1 1 1' -COLOR_DIALOG_MAPINFO '1 1 1' -COLOR_DIALOG_USERBIND '1 1 1' -COLOR_DIALOG_SINGLEPLAYER '1 1 1' -COLOR_DIALOG_CREDITS '1 1 1' -COLOR_DIALOG_WEAPONS '1 1 1' -COLOR_DIALOG_RADAR '1 1 1' -COLOR_DIALOG_SERVERINFO '1 1 1' -COLOR_DIALOG_CVARS '1 0 0' - -// item: input box -// uses "inputbox" images -COLOR_INPUTBOX_N '1 1 1' -COLOR_INPUTBOX_F '1 1 1' -MARGIN_INPUTBOX_CHARS 1 - -// item: key grabber -COLOR_KEYGRABBER_TITLES '1 1 1' -ALPHA_KEYGRABBER_TITLES 1 -COLOR_KEYGRABBER_KEYS '1 1 1' -ALPHA_KEYGRABBER_KEYS 0.7 - -// item: player color button -// uses "colorbutton" images -// uses "color" images - -// item: player name editor -// uses "charmap" images -// uses "charmapbutton" images - -// item: radio button -// uses "radiobutton" images -COLOR_RADIOBUTTON_N '1 1 1' -COLOR_RADIOBUTTON_C '1 1 1' -COLOR_RADIOBUTTON_F '1 1 1' -COLOR_RADIOBUTTON_D '1 1 1' - -// item: scrollbar -// uses "scrollbar" images -COLOR_SCROLLBAR_N '1 1 1' -COLOR_SCROLLBAR_C '0.5 0.75 1' -COLOR_SCROLLBAR_F '0.5 0.75 1' -COLOR_SCROLLBAR_S '0.25 0.25 0.25' -WIDTH_SCROLLBAR 16 - -// item: slider -// uses "slider" images -COLOR_SLIDER_N '1 1 1' -COLOR_SLIDER_C '0.5 0.75 1' -COLOR_SLIDER_F '0.5 0.75 1' -COLOR_SLIDER_D '1 1 1' -COLOR_SLIDER_S '0.25 0.25 0.25' -WIDTH_SLIDERTEXT 0.333333333333 -TOLERANCE_SLIDER '0.2 2 0' diff --git a/gfx/menu/default/slider_c.tga b/gfx/menu/default/slider_c.tga deleted file mode 100644 index 42e3e98a5c..0000000000 Binary files a/gfx/menu/default/slider_c.tga and /dev/null differ diff --git a/gfx/menu/default/slider_d.tga b/gfx/menu/default/slider_d.tga deleted file mode 100644 index 87ccbe5a67..0000000000 Binary files a/gfx/menu/default/slider_d.tga and /dev/null differ diff --git a/gfx/menu/default/slider_f.tga b/gfx/menu/default/slider_f.tga deleted file mode 100644 index 42e3e98a5c..0000000000 Binary files a/gfx/menu/default/slider_f.tga and /dev/null differ diff --git a/gfx/menu/default/slider_n.tga b/gfx/menu/default/slider_n.tga deleted file mode 100644 index 42e3e98a5c..0000000000 Binary files a/gfx/menu/default/slider_n.tga and /dev/null differ diff --git a/gfx/menu/default/slider_s.tga b/gfx/menu/default/slider_s.tga deleted file mode 100644 index 954c90cffa..0000000000 Binary files a/gfx/menu/default/slider_s.tga and /dev/null differ diff --git a/gfx/menu/default/tooltip.tga b/gfx/menu/default/tooltip.tga deleted file mode 100644 index 1dc567929d..0000000000 Binary files a/gfx/menu/default/tooltip.tga and /dev/null differ diff --git a/gfx/menu/luminos/background.tga b/gfx/menu/luminos/background.tga index 67e31a5402..7497ddc52b 100644 Binary files a/gfx/menu/luminos/background.tga and b/gfx/menu/luminos/background.tga differ diff --git a/gfx/menu/luminos/background_ingame_l2.tga b/gfx/menu/luminos/background_ingame_l2.tga index f134814f71..d77948c2d4 100644 Binary files a/gfx/menu/luminos/background_ingame_l2.tga and b/gfx/menu/luminos/background_ingame_l2.tga differ diff --git a/gfx/menu/luminos/background_l2.tga b/gfx/menu/luminos/background_l2.tga index f134814f71..d77948c2d4 100644 Binary files a/gfx/menu/luminos/background_l2.tga and b/gfx/menu/luminos/background_l2.tga differ diff --git a/gfx/menu/luminos/checkbox_c0.tga b/gfx/menu/luminos/checkbox_c0.tga index 37dbf737ff..af82c92b84 100644 Binary files a/gfx/menu/luminos/checkbox_c0.tga and b/gfx/menu/luminos/checkbox_c0.tga differ diff --git a/gfx/menu/luminos/checkbox_c1.tga b/gfx/menu/luminos/checkbox_c1.tga index 37dbf737ff..af82c92b84 100644 Binary files a/gfx/menu/luminos/checkbox_c1.tga and b/gfx/menu/luminos/checkbox_c1.tga differ diff --git a/gfx/menu/luminos/checkbox_d0.tga b/gfx/menu/luminos/checkbox_d0.tga index f948844839..d7a8be78f8 100644 Binary files a/gfx/menu/luminos/checkbox_d0.tga and b/gfx/menu/luminos/checkbox_d0.tga differ diff --git a/gfx/menu/luminos/checkbox_d1.tga b/gfx/menu/luminos/checkbox_d1.tga index a1dad7eae3..b0f7cccaa3 100644 Binary files a/gfx/menu/luminos/checkbox_d1.tga and b/gfx/menu/luminos/checkbox_d1.tga differ diff --git a/gfx/menu/luminos/checkbox_f0.tga b/gfx/menu/luminos/checkbox_f0.tga index c04496827e..257f544e43 100644 Binary files a/gfx/menu/luminos/checkbox_f0.tga and b/gfx/menu/luminos/checkbox_f0.tga differ diff --git a/gfx/menu/luminos/checkbox_f1.tga b/gfx/menu/luminos/checkbox_f1.tga index 71aad7afb2..5286cfa4e0 100644 Binary files a/gfx/menu/luminos/checkbox_f1.tga and b/gfx/menu/luminos/checkbox_f1.tga differ diff --git a/gfx/menu/luminos/checkbox_n0.tga b/gfx/menu/luminos/checkbox_n0.tga index b0efdda838..b26d7ba912 100644 Binary files a/gfx/menu/luminos/checkbox_n0.tga and b/gfx/menu/luminos/checkbox_n0.tga differ diff --git a/gfx/menu/luminos/checkbox_n1.tga b/gfx/menu/luminos/checkbox_n1.tga index 37dbf737ff..af82c92b84 100644 Binary files a/gfx/menu/luminos/checkbox_n1.tga and b/gfx/menu/luminos/checkbox_n1.tga differ diff --git a/gfx/menu/luminos/icon_aeslevel0.tga b/gfx/menu/luminos/icon_aeslevel0.tga deleted file mode 100644 index 5c9e66ac67..0000000000 Binary files a/gfx/menu/luminos/icon_aeslevel0.tga and /dev/null differ diff --git a/gfx/menu/luminos/icon_pure0.tga b/gfx/menu/luminos/icon_pure0.tga deleted file mode 100644 index 5c9e66ac67..0000000000 Binary files a/gfx/menu/luminos/icon_pure0.tga and /dev/null differ diff --git a/gfx/menu/luminos/icon_stats1.tga b/gfx/menu/luminos/icon_stats1.tga new file mode 100644 index 0000000000..4d8688def8 Binary files /dev/null and b/gfx/menu/luminos/icon_stats1.tga differ diff --git a/gfx/menu/luminos/nopreview_map.tga b/gfx/menu/luminos/nopreview_map.tga new file mode 100644 index 0000000000..c4fed58f5d Binary files /dev/null and b/gfx/menu/luminos/nopreview_map.tga differ diff --git a/gfx/menu/luminos/nopreview_menuskin.tga b/gfx/menu/luminos/nopreview_menuskin.tga new file mode 100644 index 0000000000..c4fed58f5d Binary files /dev/null and b/gfx/menu/luminos/nopreview_menuskin.tga differ diff --git a/gfx/menu/luminos/nopreview_player.tga b/gfx/menu/luminos/nopreview_player.tga new file mode 100644 index 0000000000..c4fed58f5d Binary files /dev/null and b/gfx/menu/luminos/nopreview_player.tga differ diff --git a/gfx/menu/luminos/skinvalues.txt b/gfx/menu/luminos/skinvalues.txt index 9cb2b59266..b4102234ac 100755 --- a/gfx/menu/luminos/skinvalues.txt +++ b/gfx/menu/luminos/skinvalues.txt @@ -24,8 +24,8 @@ MARGIN_COLORPICKER '0 0 0' // uses "closebutton" images MARGIN_TOP 8 MARGIN_BOTTOM 8 -MARGIN_LEFT 8 -MARGIN_RIGHT 8 +MARGIN_LEFT 16 +MARGIN_RIGHT 16 MARGIN_COLUMNS 4 MARGIN_ROWS 4 HEIGHT_DIALOGBORDER 1 @@ -166,6 +166,7 @@ COLOR_CHECKBOX_D '1 1 1' COLOR_DIALOG_MULTIPLAYER '1 1 1' COLOR_DIALOG_SETTINGS '1 1 1' COLOR_DIALOG_TEAMSELECT '1 1 1' +COLOR_DIALOG_SANDBOXTOOLS '1 1 1' COLOR_DIALOG_QUIT '1 1 1' COLOR_DIALOG_ADVANCED '1 1 1' COLOR_DIALOG_MUTATORS '1 1 1' @@ -174,7 +175,7 @@ COLOR_DIALOG_USERBIND '1 1 1' COLOR_DIALOG_SINGLEPLAYER '1 1 1' COLOR_DIALOG_CREDITS '1 1 1' COLOR_DIALOG_WEAPONS '1 1 1' -COLOR_DIALOG_RADAR '1 1 1' +COLOR_DIALOG_WAYPOINTS '1 1 1' COLOR_DIALOG_SERVERINFO '1 1 1' COLOR_DIALOG_CVARS '1 0 0' diff --git a/gfx/menu/luminos/slider_c.tga b/gfx/menu/luminos/slider_c.tga index fe43eb9c7e..a198d7a485 100644 Binary files a/gfx/menu/luminos/slider_c.tga and b/gfx/menu/luminos/slider_c.tga differ diff --git a/gfx/menu/luminos/slider_d.tga b/gfx/menu/luminos/slider_d.tga index aaa80f0513..da81872a1c 100644 Binary files a/gfx/menu/luminos/slider_d.tga and b/gfx/menu/luminos/slider_d.tga differ diff --git a/gfx/menu/luminos/slider_f.tga b/gfx/menu/luminos/slider_f.tga index 3dea5852d6..38b7140adf 100644 Binary files a/gfx/menu/luminos/slider_f.tga and b/gfx/menu/luminos/slider_f.tga differ diff --git a/gfx/menu/luminos/slider_n.tga b/gfx/menu/luminos/slider_n.tga index e270201fc1..2584eecb53 100644 Binary files a/gfx/menu/luminos/slider_n.tga and b/gfx/menu/luminos/slider_n.tga differ diff --git a/gfx/menu/wickedx/background.tga b/gfx/menu/wickedx/background.tga new file mode 100644 index 0000000000..d785d644b8 Binary files /dev/null and b/gfx/menu/wickedx/background.tga differ diff --git a/gfx/menu/wickedx/background_ingame.tga b/gfx/menu/wickedx/background_ingame.tga new file mode 100644 index 0000000000..20e276d193 Binary files /dev/null and b/gfx/menu/wickedx/background_ingame.tga differ diff --git a/gfx/menu/wickedx/background_l2.tga b/gfx/menu/wickedx/background_l2.tga new file mode 100644 index 0000000000..20e276d193 Binary files /dev/null and b/gfx/menu/wickedx/background_l2.tga differ diff --git a/gfx/menu/wickedx/bigbutton_c.tga b/gfx/menu/wickedx/bigbutton_c.tga new file mode 100644 index 0000000000..a8bf8ad91a Binary files /dev/null and b/gfx/menu/wickedx/bigbutton_c.tga differ diff --git a/gfx/menu/wickedx/bigbutton_d.tga b/gfx/menu/wickedx/bigbutton_d.tga new file mode 100644 index 0000000000..f6a832bb75 Binary files /dev/null and b/gfx/menu/wickedx/bigbutton_d.tga differ diff --git a/gfx/menu/wickedx/bigbutton_f.tga b/gfx/menu/wickedx/bigbutton_f.tga new file mode 100644 index 0000000000..c4cda968c9 Binary files /dev/null and b/gfx/menu/wickedx/bigbutton_f.tga differ diff --git a/gfx/menu/wickedx/bigbutton_n.tga b/gfx/menu/wickedx/bigbutton_n.tga new file mode 100644 index 0000000000..d54d5d5c0e Binary files /dev/null and b/gfx/menu/wickedx/bigbutton_n.tga differ diff --git a/gfx/menu/wickedx/bigbuttongray_c.tga b/gfx/menu/wickedx/bigbuttongray_c.tga new file mode 100644 index 0000000000..38e9653b02 Binary files /dev/null and b/gfx/menu/wickedx/bigbuttongray_c.tga differ diff --git a/gfx/menu/wickedx/bigbuttongray_d.tga b/gfx/menu/wickedx/bigbuttongray_d.tga new file mode 100644 index 0000000000..959ef93c32 Binary files /dev/null and b/gfx/menu/wickedx/bigbuttongray_d.tga differ diff --git a/gfx/menu/wickedx/bigbuttongray_f.tga b/gfx/menu/wickedx/bigbuttongray_f.tga new file mode 100644 index 0000000000..55ff591b7a Binary files /dev/null and b/gfx/menu/wickedx/bigbuttongray_f.tga differ diff --git a/gfx/menu/wickedx/bigbuttongray_n.tga b/gfx/menu/wickedx/bigbuttongray_n.tga new file mode 100644 index 0000000000..edff6d6a8c Binary files /dev/null and b/gfx/menu/wickedx/bigbuttongray_n.tga differ diff --git a/gfx/menu/wickedx/border.tga b/gfx/menu/wickedx/border.tga new file mode 100644 index 0000000000..d435e60196 Binary files /dev/null and b/gfx/menu/wickedx/border.tga differ diff --git a/gfx/menu/wickedx/button_c.tga b/gfx/menu/wickedx/button_c.tga new file mode 100644 index 0000000000..745ee7c1d2 Binary files /dev/null and b/gfx/menu/wickedx/button_c.tga differ diff --git a/gfx/menu/wickedx/button_d.tga b/gfx/menu/wickedx/button_d.tga new file mode 100644 index 0000000000..6639525e52 Binary files /dev/null and b/gfx/menu/wickedx/button_d.tga differ diff --git a/gfx/menu/wickedx/button_f.tga b/gfx/menu/wickedx/button_f.tga new file mode 100644 index 0000000000..817d849216 Binary files /dev/null and b/gfx/menu/wickedx/button_f.tga differ diff --git a/gfx/menu/wickedx/button_n.tga b/gfx/menu/wickedx/button_n.tga new file mode 100644 index 0000000000..643360e270 Binary files /dev/null and b/gfx/menu/wickedx/button_n.tga differ diff --git a/gfx/menu/wickedx/buttongray_c.tga b/gfx/menu/wickedx/buttongray_c.tga new file mode 100644 index 0000000000..032ea91d27 Binary files /dev/null and b/gfx/menu/wickedx/buttongray_c.tga differ diff --git a/gfx/menu/wickedx/buttongray_d.tga b/gfx/menu/wickedx/buttongray_d.tga new file mode 100644 index 0000000000..55f1e622a7 Binary files /dev/null and b/gfx/menu/wickedx/buttongray_d.tga differ diff --git a/gfx/menu/wickedx/buttongray_f.tga b/gfx/menu/wickedx/buttongray_f.tga new file mode 100644 index 0000000000..5ed3a7dfc9 Binary files /dev/null and b/gfx/menu/wickedx/buttongray_f.tga differ diff --git a/gfx/menu/wickedx/buttongray_n.tga b/gfx/menu/wickedx/buttongray_n.tga new file mode 100644 index 0000000000..6ba22b53c0 Binary files /dev/null and b/gfx/menu/wickedx/buttongray_n.tga differ diff --git a/gfx/menu/wickedx/charmap.tga b/gfx/menu/wickedx/charmap.tga new file mode 100755 index 0000000000..d8ed1d5de9 Binary files /dev/null and b/gfx/menu/wickedx/charmap.tga differ diff --git a/gfx/menu/wickedx/charmapbutton.tga b/gfx/menu/wickedx/charmapbutton.tga new file mode 100644 index 0000000000..54fe07eb75 Binary files /dev/null and b/gfx/menu/wickedx/charmapbutton.tga differ diff --git a/gfx/menu/wickedx/checkbox_c0.tga b/gfx/menu/wickedx/checkbox_c0.tga new file mode 100644 index 0000000000..aafd08943f Binary files /dev/null and b/gfx/menu/wickedx/checkbox_c0.tga differ diff --git a/gfx/menu/wickedx/checkbox_c1.tga b/gfx/menu/wickedx/checkbox_c1.tga new file mode 100644 index 0000000000..4e517e2464 Binary files /dev/null and b/gfx/menu/wickedx/checkbox_c1.tga differ diff --git a/gfx/menu/wickedx/checkbox_d0.tga b/gfx/menu/wickedx/checkbox_d0.tga new file mode 100644 index 0000000000..40efe7a6bb Binary files /dev/null and b/gfx/menu/wickedx/checkbox_d0.tga differ diff --git a/gfx/menu/wickedx/checkbox_d1.tga b/gfx/menu/wickedx/checkbox_d1.tga new file mode 100644 index 0000000000..bba682482d Binary files /dev/null and b/gfx/menu/wickedx/checkbox_d1.tga differ diff --git a/gfx/menu/wickedx/checkbox_f0.tga b/gfx/menu/wickedx/checkbox_f0.tga new file mode 100644 index 0000000000..aafd08943f Binary files /dev/null and b/gfx/menu/wickedx/checkbox_f0.tga differ diff --git a/gfx/menu/wickedx/checkbox_f1.tga b/gfx/menu/wickedx/checkbox_f1.tga new file mode 100644 index 0000000000..4e517e2464 Binary files /dev/null and b/gfx/menu/wickedx/checkbox_f1.tga differ diff --git a/gfx/menu/wickedx/checkbox_n0.tga b/gfx/menu/wickedx/checkbox_n0.tga new file mode 100644 index 0000000000..aafd08943f Binary files /dev/null and b/gfx/menu/wickedx/checkbox_n0.tga differ diff --git a/gfx/menu/wickedx/checkbox_n1.tga b/gfx/menu/wickedx/checkbox_n1.tga new file mode 100644 index 0000000000..4e517e2464 Binary files /dev/null and b/gfx/menu/wickedx/checkbox_n1.tga differ diff --git a/gfx/menu/wickedx/checkmark.tga b/gfx/menu/wickedx/checkmark.tga new file mode 100644 index 0000000000..cf34dde26a Binary files /dev/null and b/gfx/menu/wickedx/checkmark.tga differ diff --git a/gfx/menu/wickedx/closebutton_c.tga b/gfx/menu/wickedx/closebutton_c.tga new file mode 100644 index 0000000000..56488eca61 Binary files /dev/null and b/gfx/menu/wickedx/closebutton_c.tga differ diff --git a/gfx/menu/wickedx/closebutton_f.tga b/gfx/menu/wickedx/closebutton_f.tga new file mode 100644 index 0000000000..73385736ab Binary files /dev/null and b/gfx/menu/wickedx/closebutton_f.tga differ diff --git a/gfx/menu/wickedx/closebutton_n.tga b/gfx/menu/wickedx/closebutton_n.tga new file mode 100644 index 0000000000..e4b6058094 Binary files /dev/null and b/gfx/menu/wickedx/closebutton_n.tga differ diff --git a/gfx/menu/wickedx/color.tga b/gfx/menu/wickedx/color.tga new file mode 100755 index 0000000000..5189ab4963 Binary files /dev/null and b/gfx/menu/wickedx/color.tga differ diff --git a/gfx/menu/wickedx/colorbutton_c.tga b/gfx/menu/wickedx/colorbutton_c.tga new file mode 100644 index 0000000000..1c294f77f5 Binary files /dev/null and b/gfx/menu/wickedx/colorbutton_c.tga differ diff --git a/gfx/menu/wickedx/colorbutton_f.tga b/gfx/menu/wickedx/colorbutton_f.tga new file mode 100644 index 0000000000..0031c35e35 Binary files /dev/null and b/gfx/menu/wickedx/colorbutton_f.tga differ diff --git a/gfx/menu/wickedx/colorbutton_n.tga b/gfx/menu/wickedx/colorbutton_n.tga new file mode 100755 index 0000000000..7fec859bcc Binary files /dev/null and b/gfx/menu/wickedx/colorbutton_n.tga differ diff --git a/gfx/menu/wickedx/colorpicker.tga b/gfx/menu/wickedx/colorpicker.tga new file mode 100755 index 0000000000..6f9845bf3e Binary files /dev/null and b/gfx/menu/wickedx/colorpicker.tga differ diff --git a/gfx/menu/wickedx/colorpicker_m.tga b/gfx/menu/wickedx/colorpicker_m.tga new file mode 100755 index 0000000000..79b0e83b7d Binary files /dev/null and b/gfx/menu/wickedx/colorpicker_m.tga differ diff --git a/gfx/menu/wickedx/colorpicker_selected.tga b/gfx/menu/wickedx/colorpicker_selected.tga new file mode 100644 index 0000000000..605e932017 Binary files /dev/null and b/gfx/menu/wickedx/colorpicker_selected.tga differ diff --git a/gfx/menu/wickedx/crosshairbutton_c.tga b/gfx/menu/wickedx/crosshairbutton_c.tga new file mode 100644 index 0000000000..1c294f77f5 Binary files /dev/null and b/gfx/menu/wickedx/crosshairbutton_c.tga differ diff --git a/gfx/menu/wickedx/crosshairbutton_d.tga b/gfx/menu/wickedx/crosshairbutton_d.tga new file mode 100755 index 0000000000..110faa18b5 Binary files /dev/null and b/gfx/menu/wickedx/crosshairbutton_d.tga differ diff --git a/gfx/menu/wickedx/crosshairbutton_f.tga b/gfx/menu/wickedx/crosshairbutton_f.tga new file mode 100644 index 0000000000..0031c35e35 Binary files /dev/null and b/gfx/menu/wickedx/crosshairbutton_f.tga differ diff --git a/gfx/menu/wickedx/crosshairbutton_n.tga b/gfx/menu/wickedx/crosshairbutton_n.tga new file mode 100755 index 0000000000..ac945355ef Binary files /dev/null and b/gfx/menu/wickedx/crosshairbutton_n.tga differ diff --git a/gfx/menu/wickedx/cursor.tga b/gfx/menu/wickedx/cursor.tga new file mode 100644 index 0000000000..0a2e29514d Binary files /dev/null and b/gfx/menu/wickedx/cursor.tga differ diff --git a/gfx/menu/wickedx/cursor_move.tga b/gfx/menu/wickedx/cursor_move.tga new file mode 100644 index 0000000000..02643169b2 Binary files /dev/null and b/gfx/menu/wickedx/cursor_move.tga differ diff --git a/gfx/menu/wickedx/cursor_resize.tga b/gfx/menu/wickedx/cursor_resize.tga new file mode 100644 index 0000000000..475e2244ff Binary files /dev/null and b/gfx/menu/wickedx/cursor_resize.tga differ diff --git a/gfx/menu/wickedx/cursor_resize2.tga b/gfx/menu/wickedx/cursor_resize2.tga new file mode 100644 index 0000000000..6c97fb8d14 Binary files /dev/null and b/gfx/menu/wickedx/cursor_resize2.tga differ diff --git a/gfx/menu/wickedx/icon_aeslevel1.tga b/gfx/menu/wickedx/icon_aeslevel1.tga new file mode 100644 index 0000000000..7103e55b74 Binary files /dev/null and b/gfx/menu/wickedx/icon_aeslevel1.tga differ diff --git a/gfx/menu/wickedx/icon_aeslevel2.tga b/gfx/menu/wickedx/icon_aeslevel2.tga new file mode 100644 index 0000000000..793b457692 Binary files /dev/null and b/gfx/menu/wickedx/icon_aeslevel2.tga differ diff --git a/gfx/menu/wickedx/icon_aeslevel3.tga b/gfx/menu/wickedx/icon_aeslevel3.tga new file mode 100644 index 0000000000..ec2f15bf2f Binary files /dev/null and b/gfx/menu/wickedx/icon_aeslevel3.tga differ diff --git a/gfx/menu/wickedx/icon_aeslevel4.tga b/gfx/menu/wickedx/icon_aeslevel4.tga new file mode 100644 index 0000000000..8f7f4669b8 Binary files /dev/null and b/gfx/menu/wickedx/icon_aeslevel4.tga differ diff --git a/gfx/menu/wickedx/icon_aeslevel5.tga b/gfx/menu/wickedx/icon_aeslevel5.tga new file mode 100644 index 0000000000..8662b137b6 Binary files /dev/null and b/gfx/menu/wickedx/icon_aeslevel5.tga differ diff --git a/gfx/menu/wickedx/icon_ipv4.tga b/gfx/menu/wickedx/icon_ipv4.tga new file mode 100644 index 0000000000..a0484f4e37 Binary files /dev/null and b/gfx/menu/wickedx/icon_ipv4.tga differ diff --git a/gfx/menu/wickedx/icon_ipv6.tga b/gfx/menu/wickedx/icon_ipv6.tga new file mode 100644 index 0000000000..d3fdc03ee3 Binary files /dev/null and b/gfx/menu/wickedx/icon_ipv6.tga differ diff --git a/gfx/menu/wickedx/icon_pure1.tga b/gfx/menu/wickedx/icon_pure1.tga new file mode 100644 index 0000000000..62980d257a Binary files /dev/null and b/gfx/menu/wickedx/icon_pure1.tga differ diff --git a/gfx/menu/wickedx/icon_stats1.tga b/gfx/menu/wickedx/icon_stats1.tga new file mode 100644 index 0000000000..4d8688def8 Binary files /dev/null and b/gfx/menu/wickedx/icon_stats1.tga differ diff --git a/gfx/menu/wickedx/inputbox_f.tga b/gfx/menu/wickedx/inputbox_f.tga new file mode 100644 index 0000000000..6b5bd201fe Binary files /dev/null and b/gfx/menu/wickedx/inputbox_f.tga differ diff --git a/gfx/menu/wickedx/inputbox_n.tga b/gfx/menu/wickedx/inputbox_n.tga new file mode 100644 index 0000000000..ad169c2083 Binary files /dev/null and b/gfx/menu/wickedx/inputbox_n.tga differ diff --git a/gfx/menu/wickedx/nopreview_map.tga b/gfx/menu/wickedx/nopreview_map.tga new file mode 100644 index 0000000000..2fc5c5db9a Binary files /dev/null and b/gfx/menu/wickedx/nopreview_map.tga differ diff --git a/gfx/menu/wickedx/nopreview_menuskin.tga b/gfx/menu/wickedx/nopreview_menuskin.tga new file mode 100644 index 0000000000..2fc5c5db9a Binary files /dev/null and b/gfx/menu/wickedx/nopreview_menuskin.tga differ diff --git a/gfx/menu/wickedx/nopreview_player.tga b/gfx/menu/wickedx/nopreview_player.tga new file mode 100644 index 0000000000..2fc5c5db9a Binary files /dev/null and b/gfx/menu/wickedx/nopreview_player.tga differ diff --git a/gfx/menu/wickedx/radiobutton_c0.tga b/gfx/menu/wickedx/radiobutton_c0.tga new file mode 100644 index 0000000000..68ed15e696 Binary files /dev/null and b/gfx/menu/wickedx/radiobutton_c0.tga differ diff --git a/gfx/menu/wickedx/radiobutton_c1.tga b/gfx/menu/wickedx/radiobutton_c1.tga new file mode 100644 index 0000000000..68ed15e696 Binary files /dev/null and b/gfx/menu/wickedx/radiobutton_c1.tga differ diff --git a/gfx/menu/wickedx/radiobutton_d0.tga b/gfx/menu/wickedx/radiobutton_d0.tga new file mode 100644 index 0000000000..f935318b30 Binary files /dev/null and b/gfx/menu/wickedx/radiobutton_d0.tga differ diff --git a/gfx/menu/wickedx/radiobutton_d1.tga b/gfx/menu/wickedx/radiobutton_d1.tga new file mode 100644 index 0000000000..1bcc41d0fc Binary files /dev/null and b/gfx/menu/wickedx/radiobutton_d1.tga differ diff --git a/gfx/menu/wickedx/radiobutton_f0.tga b/gfx/menu/wickedx/radiobutton_f0.tga new file mode 100644 index 0000000000..237e09b0e2 Binary files /dev/null and b/gfx/menu/wickedx/radiobutton_f0.tga differ diff --git a/gfx/menu/wickedx/radiobutton_f1.tga b/gfx/menu/wickedx/radiobutton_f1.tga new file mode 100644 index 0000000000..68ed15e696 Binary files /dev/null and b/gfx/menu/wickedx/radiobutton_f1.tga differ diff --git a/gfx/menu/wickedx/radiobutton_n0.tga b/gfx/menu/wickedx/radiobutton_n0.tga new file mode 100644 index 0000000000..55dae24026 Binary files /dev/null and b/gfx/menu/wickedx/radiobutton_n0.tga differ diff --git a/gfx/menu/wickedx/radiobutton_n1.tga b/gfx/menu/wickedx/radiobutton_n1.tga new file mode 100644 index 0000000000..68ed15e696 Binary files /dev/null and b/gfx/menu/wickedx/radiobutton_n1.tga differ diff --git a/gfx/menu/wickedx/scrollbar_c.tga b/gfx/menu/wickedx/scrollbar_c.tga new file mode 100644 index 0000000000..eb4326dfb6 Binary files /dev/null and b/gfx/menu/wickedx/scrollbar_c.tga differ diff --git a/gfx/menu/wickedx/scrollbar_f.tga b/gfx/menu/wickedx/scrollbar_f.tga new file mode 100644 index 0000000000..eb4326dfb6 Binary files /dev/null and b/gfx/menu/wickedx/scrollbar_f.tga differ diff --git a/gfx/menu/wickedx/scrollbar_n.tga b/gfx/menu/wickedx/scrollbar_n.tga new file mode 100644 index 0000000000..eb4326dfb6 Binary files /dev/null and b/gfx/menu/wickedx/scrollbar_n.tga differ diff --git a/gfx/menu/wickedx/scrollbar_s.tga b/gfx/menu/wickedx/scrollbar_s.tga new file mode 100644 index 0000000000..c7d47005e6 Binary files /dev/null and b/gfx/menu/wickedx/scrollbar_s.tga differ diff --git a/gfx/menu/wickedx/skinpreview.jpg b/gfx/menu/wickedx/skinpreview.jpg new file mode 100755 index 0000000000..9b8e393898 Binary files /dev/null and b/gfx/menu/wickedx/skinpreview.jpg differ diff --git a/gfx/menu/wickedx/skinvalues.txt b/gfx/menu/wickedx/skinvalues.txt new file mode 100755 index 0000000000..d6b7197a1d --- /dev/null +++ b/gfx/menu/wickedx/skinvalues.txt @@ -0,0 +1,225 @@ +title Default // "WickedX" +author sev + +// Colors: 'Red Green Blue' +// Suffixes: Clicked (_c), Disabled (_d), Focused (_f), Normal (_n) + +// Background layer scaling: +// Crop (c), Letterbox (l), Height (h), Width (w), Stretch (s) +// Background layer positioning: +// Top Left (7), Top Center (8) Top Right (9) +// Middle Left (4), Middle Center (5) Middle Right (6) +// Bottom Left (1), Bottom Center (2) Bottom Right (3) +// ALIGN_BACKGROUND(_INGAME) spspsp, s=Scale p=Position + +//------------------------------------------------------------------------------ +// Structure (e.g. positions, sizes, margins) +//------------------------------------------------------------------------------ +// item: color picker +// uses "colorpicker" images +MARGIN_COLORPICKER '0 0 0' + +// item: dialog +// uses "border" images +// uses "closebutton" images +MARGIN_TOP 8 +MARGIN_BOTTOM 8 +MARGIN_LEFT 16 +MARGIN_RIGHT 16 +MARGIN_COLUMNS 4 +MARGIN_ROWS 4 +HEIGHT_DIALOGBORDER 1 + +// font sizes (used for everything) +FONTSIZE_NORMAL 12 +HEIGHT_NORMAL 1.5 +FONTSIZE_TITLE 16 +HEIGHT_TITLE 1.5 +HEIGHT_ZOOMEDTITLE -1 + +// general +// uses "background" images +// uses "background_ingame" images +ALIGN_BACKGROUND h5h5 +ALIGN_BACKGROUND_INGAME h5 +ALPHA_BACKGROUND_INGAME 1 +ALPHA_DISABLED 0.2 +ALPHA_BEHIND 0.5 +ALPHA_TEXT 0.7 + +// mouse +// uses "cursor" images +SIZE_CURSOR '32 32 0' +OFFSET_CURSOR '0 0 0' +ALPHA_CURSOR_INTRO 0 + +// nexposee positions of windows (they are the scale transformation +// centers, NOT the actual positions of the windows!) +POSITION_DIALOG_MULTIPLAYER '0.8 0.4 0' +POSITION_DIALOG_SINGLEPLAYER '0.2 0.4 0' +POSITION_DIALOG_SETTINGS '0.5 0.95 0' +POSITION_DIALOG_CREDITS '-0.05 1.2 0' +POSITION_DIALOG_QUIT '1.05 1.2 0' + +// tooltips +// uses "tooltip" images +MARGIN_TOOLTIP '8 8 0' +BORDER_TOOLTIP '16 16 0' +FONTSIZE_TOOLTIP 12 +ALPHA_TOOLTIP 0.7 +WIDTH_TOOLTIP 0.3 +AVOID_TOOLTIP '8 8 0' + +//------------------------------------------------------------------------------ +// Colors (e.g. font colors, field colors) +//------------------------------------------------------------------------------ +// item: campaign +ALPHA_CAMPAIGN_SELECTABLE 0.8 +COLOR_CAMPAIGN_SELECTABLE '1 1 1' +ALPHA_CAMPAIGN_CURRENT 1 +COLOR_CAMPAIGN_CURRENT '1 1 1' +ALPHA_CAMPAIGN_FUTURE 0.2 +COLOR_CAMPAIGN_FUTURE '1 1 1' +ALPHA_CAMPAIGN_DESCRIPTION 0.7 + +// item: credits list +COLOR_CREDITS_TITLE '0.875 0.375 0' +ALPHA_CREDITS_TITLE 1 +COLOR_CREDITS_FUNCTION '0 0.1875 0.4375' +ALPHA_CREDITS_FUNCTION 0.5 +COLOR_CREDITS_PERSON '0 0.375 0.75' +ALPHA_CREDITS_PERSON 0.875 +ROWS_CREDITS 20 +WIDTH_CREDITS 0.5 + +// item: cvar list +ALPHA_CVARLIST_SAVED 1 +ALPHA_CVARLIST_TEMPORARY 0.7 +COLOR_CVARLIST_CHANGED '0 0.375 0.75' +COLOR_CVARLIST_REVERTBUTTON '1 0 0' +COLOR_CVARLIST_UNCHANGED '1 1 1' + +// item: list box +COLOR_LISTBOX_SELECTED '0.875 0.375 0' +ALPHA_LISTBOX_SELECTED 1 +COLOR_LISTBOX_WAITING '1 1 1' +ALPHA_LISTBOX_WAITING 0.5 + +// item: map list +COLOR_MAPLIST_TITLE '1 1 1' +COLOR_MAPLIST_AUTHOR '0 0.375 0.75' +COLOR_MAPLIST_INCLUDEDBG '0 0.1875 0.4375' +ALPHA_MAPLIST_INCLUDEDFG 1 +ALPHA_MAPLIST_INCLUDEDBG 0.375 +ALPHA_MAPLIST_NOTINCLUDEDFG 0.25 + +// item: nexposee +ALPHAS_MAINMENU '0.8 0.9 1' + +// item: player model +COLOR_MODELTITLE '1 1 1' +ALPHA_MODELTITLE 1 + +// item: server info +COLOR_SERVERINFO_NAME '1 1 1' +COLOR_SERVERINFO_IP '0.875 0.375 0' + +// item: server list +ALPHA_SERVERLIST_FULL 0.4 +ALPHA_SERVERLIST_EMPTY 0.7 +COLOR_SERVERLIST_LOWPING '0 1 0' +COLOR_SERVERLIST_MEDPING '1 0.75 0' +COLOR_SERVERLIST_HIGHPING '1 0 0' +ALPHA_SERVERLIST_HIGHPING 0.4 +ALPHA_SERVERLIST_FAVORITE 0.8 +COLOR_SERVERLIST_FAVORITE '1 1 1' + +// item: skin list +COLOR_SKINLIST_TITLE '1 1 1' +COLOR_SKINLIST_AUTHOR '0 0.375 0.75' + +//------------------------------------------------------------------------------ +// Images (colors multiplied to images) +//------------------------------------------------------------------------------ +// item: button +// uses "button" images +// uses "buttongray" images +// uses "bigbutton" images +// uses "bigbuttongray" images +COLOR_BUTTON_N '1 1 1' +COLOR_BUTTON_C '1 1 1' +COLOR_BUTTON_F '1 1 1' +COLOR_BUTTON_D '1 1 1' + +// item: checkbox +// uses "checkbox" images +COLOR_CHECKBOX_N '1 1 1' +COLOR_CHECKBOX_C '0.5 0.75 1' +COLOR_CHECKBOX_F '0.5 0.75 1' +COLOR_CHECKBOX_D '1 1 1' + +// item: crosshair button +// uses "crosshairbutton" images + +// dialog background colors +// uses "border" images +COLOR_DIALOG_MULTIPLAYER '1 1 1' +COLOR_DIALOG_SETTINGS '1 1 1' +COLOR_DIALOG_TEAMSELECT '1 1 1' +COLOR_DIALOG_SANDBOXTOOLS '1 1 1' +COLOR_DIALOG_QUIT '1 1 1' +COLOR_DIALOG_ADVANCED '1 1 1' +COLOR_DIALOG_MUTATORS '1 1 1' +COLOR_DIALOG_MAPINFO '1 1 1' +COLOR_DIALOG_USERBIND '1 1 1' +COLOR_DIALOG_SINGLEPLAYER '1 1 1' +COLOR_DIALOG_CREDITS '1 1 1' +COLOR_DIALOG_WEAPONS '1 1 1' +COLOR_DIALOG_WAYPOINTS '1 1 1' +COLOR_DIALOG_SERVERINFO '1 1 1' +COLOR_DIALOG_CVARS '1 0 0' + +// item: input box +// uses "inputbox" images +COLOR_INPUTBOX_N '1 1 1' +COLOR_INPUTBOX_F '1 1 1' +MARGIN_INPUTBOX_CHARS 1 + +// item: key grabber +COLOR_KEYGRABBER_TITLES '1 1 1' +ALPHA_KEYGRABBER_TITLES 1 +COLOR_KEYGRABBER_KEYS '1 1 1' +ALPHA_KEYGRABBER_KEYS 0.7 + +// item: player color button +// uses "colorbutton" images +// uses "color" images + +// item: player name editor +// uses "charmap" images +// uses "charmapbutton" images + +// item: radio button +// uses "radiobutton" images +COLOR_RADIOBUTTON_N '1 1 1' +COLOR_RADIOBUTTON_C '1 1 1' +COLOR_RADIOBUTTON_F '1 1 1' +COLOR_RADIOBUTTON_D '1 1 1' + +// item: scrollbar +// uses "scrollbar" images +COLOR_SCROLLBAR_N '1 1 1' +COLOR_SCROLLBAR_C '0.5 0.75 1' +COLOR_SCROLLBAR_F '0.5 0.75 1' +COLOR_SCROLLBAR_S '0.25 0.25 0.25' +WIDTH_SCROLLBAR 16 + +// item: slider +// uses "slider" images +COLOR_SLIDER_N '1 1 1' +COLOR_SLIDER_C '0.5 0.75 1' +COLOR_SLIDER_F '0.5 0.75 1' +COLOR_SLIDER_D '1 1 1' +COLOR_SLIDER_S '0.25 0.25 0.25' +WIDTH_SLIDERTEXT 0.333333333333 +TOLERANCE_SLIDER '0.2 2 0' diff --git a/gfx/menu/wickedx/slider_c.tga b/gfx/menu/wickedx/slider_c.tga new file mode 100644 index 0000000000..42e3e98a5c Binary files /dev/null and b/gfx/menu/wickedx/slider_c.tga differ diff --git a/gfx/menu/wickedx/slider_d.tga b/gfx/menu/wickedx/slider_d.tga new file mode 100644 index 0000000000..87ccbe5a67 Binary files /dev/null and b/gfx/menu/wickedx/slider_d.tga differ diff --git a/gfx/menu/wickedx/slider_f.tga b/gfx/menu/wickedx/slider_f.tga new file mode 100644 index 0000000000..42e3e98a5c Binary files /dev/null and b/gfx/menu/wickedx/slider_f.tga differ diff --git a/gfx/menu/wickedx/slider_n.tga b/gfx/menu/wickedx/slider_n.tga new file mode 100644 index 0000000000..42e3e98a5c Binary files /dev/null and b/gfx/menu/wickedx/slider_n.tga differ diff --git a/gfx/menu/wickedx/slider_s.tga b/gfx/menu/wickedx/slider_s.tga new file mode 100644 index 0000000000..954c90cffa Binary files /dev/null and b/gfx/menu/wickedx/slider_s.tga differ diff --git a/gfx/menu/wickedx/tooltip.tga b/gfx/menu/wickedx/tooltip.tga new file mode 100644 index 0000000000..1dc567929d Binary files /dev/null and b/gfx/menu/wickedx/tooltip.tga differ diff --git a/gfx/menu/xaw/icon_aeslevel0.tga b/gfx/menu/xaw/icon_aeslevel0.tga deleted file mode 100644 index 5c9e66ac67..0000000000 Binary files a/gfx/menu/xaw/icon_aeslevel0.tga and /dev/null differ diff --git a/gfx/menu/xaw/icon_pure0.tga b/gfx/menu/xaw/icon_pure0.tga deleted file mode 100644 index 5c9e66ac67..0000000000 Binary files a/gfx/menu/xaw/icon_pure0.tga and /dev/null differ diff --git a/gfx/menu/xaw/icon_stats1.tga b/gfx/menu/xaw/icon_stats1.tga new file mode 100644 index 0000000000..4d8688def8 Binary files /dev/null and b/gfx/menu/xaw/icon_stats1.tga differ diff --git a/gfx/menu/xaw/nopreview_map.tga b/gfx/menu/xaw/nopreview_map.tga new file mode 100644 index 0000000000..7b01510211 Binary files /dev/null and b/gfx/menu/xaw/nopreview_map.tga differ diff --git a/gfx/menu/xaw/nopreview_menuskin.tga b/gfx/menu/xaw/nopreview_menuskin.tga new file mode 100644 index 0000000000..7b01510211 Binary files /dev/null and b/gfx/menu/xaw/nopreview_menuskin.tga differ diff --git a/gfx/menu/xaw/nopreview_player.tga b/gfx/menu/xaw/nopreview_player.tga new file mode 100644 index 0000000000..7b01510211 Binary files /dev/null and b/gfx/menu/xaw/nopreview_player.tga differ diff --git a/gfx/menu/xaw/skinvalues.txt b/gfx/menu/xaw/skinvalues.txt index 666b971c23..5afcb09cfe 100644 --- a/gfx/menu/xaw/skinvalues.txt +++ b/gfx/menu/xaw/skinvalues.txt @@ -21,6 +21,7 @@ AVOID_TOOLTIP '8 8 0' COLOR_DIALOG_MULTIPLAYER '1 1 1' COLOR_DIALOG_SETTINGS '1 1 1' COLOR_DIALOG_TEAMSELECT '1 1 1' +COLOR_DIALOG_SANDBOXTOOLS '1 1 1' COLOR_DIALOG_QUIT '1 0 0' COLOR_DIALOG_ADVANCED '1 1 1' COLOR_DIALOG_MUTATORS '1 1 1' @@ -29,7 +30,7 @@ COLOR_DIALOG_USERBIND '1 1 1' COLOR_DIALOG_SINGLEPLAYER '1 1 1' COLOR_DIALOG_CREDITS '1 1 1' COLOR_DIALOG_WEAPONS '1 1 1' -COLOR_DIALOG_RADAR '1 1 1' +COLOR_DIALOG_WAYPOINTS '1 1 1' COLOR_DIALOG_SERVERINFO '1 1 1' COLOR_DIALOG_CVARS '1 0 0' @@ -112,8 +113,8 @@ COLOR_CVARLIST_UNCHANGED '1 1 1' // uses "closebutton" images MARGIN_TOP 8 MARGIN_BOTTOM 8 -MARGIN_LEFT 8 -MARGIN_RIGHT 8 +MARGIN_LEFT 16 +MARGIN_RIGHT 16 MARGIN_COLUMNS 4 MARGIN_ROWS 4 HEIGHT_DIALOGBORDER 1 diff --git a/gfx/ons-frame-team.tga b/gfx/ons-frame-team.tga deleted file mode 100644 index fb97397e34..0000000000 Binary files a/gfx/ons-frame-team.tga and /dev/null differ diff --git a/gfx/ons-frame.tga b/gfx/ons-frame.tga deleted file mode 100644 index 13a89126bf..0000000000 Binary files a/gfx/ons-frame.tga and /dev/null differ diff --git a/gfx/vehicles/axh-bracket.tga b/gfx/vehicles/axh-bracket.tga new file mode 100644 index 0000000000..82f0796602 Binary files /dev/null and b/gfx/vehicles/axh-bracket.tga differ diff --git a/gfx/vehicles/axh-cross.tga b/gfx/vehicles/axh-cross.tga new file mode 100644 index 0000000000..69e1c0be0f Binary files /dev/null and b/gfx/vehicles/axh-cross.tga differ diff --git a/gfx/vehicles/axh-dropcross.tga b/gfx/vehicles/axh-dropcross.tga new file mode 100644 index 0000000000..e8ba095fd5 Binary files /dev/null and b/gfx/vehicles/axh-dropcross.tga differ diff --git a/gfx/vehicles/axh-ring.tga b/gfx/vehicles/axh-ring.tga new file mode 100644 index 0000000000..bb3ade5884 Binary files /dev/null and b/gfx/vehicles/axh-ring.tga differ diff --git a/gfx/vehicles/axh-special1.tga b/gfx/vehicles/axh-special1.tga new file mode 100644 index 0000000000..184a065c0a Binary files /dev/null and b/gfx/vehicles/axh-special1.tga differ diff --git a/gfx/vehicles/axh-special2.tga b/gfx/vehicles/axh-special2.tga new file mode 100644 index 0000000000..caad1d71cc Binary files /dev/null and b/gfx/vehicles/axh-special2.tga differ diff --git a/gfx/vehicles/axh-tag.tga b/gfx/vehicles/axh-tag.tga new file mode 100644 index 0000000000..4eb3b66c22 Binary files /dev/null and b/gfx/vehicles/axh-tag.tga differ diff --git a/gfx/vehicles/axh-target.tga b/gfx/vehicles/axh-target.tga new file mode 100644 index 0000000000..8c05908f2f Binary files /dev/null and b/gfx/vehicles/axh-target.tga differ diff --git a/gfx/vehicles/axh-x.tga b/gfx/vehicles/axh-x.tga new file mode 100644 index 0000000000..f6a4fce779 Binary files /dev/null and b/gfx/vehicles/axh-x.tga differ diff --git a/gfx/vehicles/bar_dwn_left.tga b/gfx/vehicles/bar_dwn_left.tga new file mode 100644 index 0000000000..011f9a9c32 Binary files /dev/null and b/gfx/vehicles/bar_dwn_left.tga differ diff --git a/gfx/vehicles/bar_dwn_right.tga b/gfx/vehicles/bar_dwn_right.tga new file mode 100644 index 0000000000..e93b5e6001 Binary files /dev/null and b/gfx/vehicles/bar_dwn_right.tga differ diff --git a/gfx/vehicles/bar_up_left.tga b/gfx/vehicles/bar_up_left.tga new file mode 100644 index 0000000000..f49d205d0d Binary files /dev/null and b/gfx/vehicles/bar_up_left.tga differ diff --git a/gfx/vehicles/bar_up_right.tga b/gfx/vehicles/bar_up_right.tga new file mode 100644 index 0000000000..a3b5910140 Binary files /dev/null and b/gfx/vehicles/bar_up_right.tga differ diff --git a/gfx/vehicles/bullets.tga b/gfx/vehicles/bullets.tga new file mode 100644 index 0000000000..ff853ee6b8 Binary files /dev/null and b/gfx/vehicles/bullets.tga differ diff --git a/gfx/vehicles/frame.tga b/gfx/vehicles/frame.tga new file mode 100644 index 0000000000..92a657361b Binary files /dev/null and b/gfx/vehicles/frame.tga differ diff --git a/gfx/vehicles/health.tga b/gfx/vehicles/health.tga new file mode 100644 index 0000000000..3956a3ff21 Binary files /dev/null and b/gfx/vehicles/health.tga differ diff --git a/gfx/vehicles/hud_bg.tga b/gfx/vehicles/hud_bg.tga deleted file mode 100644 index a2ba3b3616..0000000000 Binary files a/gfx/vehicles/hud_bg.tga and /dev/null differ diff --git a/gfx/vehicles/raptor.tga b/gfx/vehicles/raptor.tga new file mode 100644 index 0000000000..9a2519a95c Binary files /dev/null and b/gfx/vehicles/raptor.tga differ diff --git a/gfx/vehicles/raptor_bombs.tga b/gfx/vehicles/raptor_bombs.tga new file mode 100644 index 0000000000..9012fb2599 Binary files /dev/null and b/gfx/vehicles/raptor_bombs.tga differ diff --git a/gfx/vehicles/raptor_guns.tga b/gfx/vehicles/raptor_guns.tga new file mode 100644 index 0000000000..0d0012a53d Binary files /dev/null and b/gfx/vehicles/raptor_guns.tga differ diff --git a/gfx/vehicles/rocket.tga b/gfx/vehicles/rocket.tga new file mode 100644 index 0000000000..f0385b97f9 Binary files /dev/null and b/gfx/vehicles/rocket.tga differ diff --git a/gfx/vehicles/shield.tga b/gfx/vehicles/shield.tga new file mode 100644 index 0000000000..916268f05e Binary files /dev/null and b/gfx/vehicles/shield.tga differ diff --git a/gfx/vehicles/shiled.tga b/gfx/vehicles/shiled.tga deleted file mode 100644 index bd728e2838..0000000000 Binary files a/gfx/vehicles/shiled.tga and /dev/null differ diff --git a/gfx/vehicles/vh-shield.tga b/gfx/vehicles/vh-shield.tga new file mode 100644 index 0000000000..bd728e2838 Binary files /dev/null and b/gfx/vehicles/vh-shield.tga differ diff --git a/hook-firing_swap.cfg b/hook-firing_swap.cfg index e556db70e9..4ed1381201 100644 --- a/hook-firing_swap.cfg +++ b/hook-firing_swap.cfg @@ -9,23 +9,24 @@ // after exec'ing them all from your autoexec.cfg // Set the cvars for each gun -seta cl_swapattacks_tuba 0 seta cl_swapattacks_laser 0 seta cl_swapattacks_shotgun 0 seta cl_swapattacks_uzi 0 -seta cl_swapattacks_campingrifle 0 seta cl_swapattacks_grenadelauncher 0 +seta cl_swapattacks_minelayer 0 seta cl_swapattacks_electro 0 -seta cl_swapattacks_hlac 0 seta cl_swapattacks_crylink 0 -seta cl_swapattacks_minstanex 0 seta cl_swapattacks_nex 0 seta cl_swapattacks_hagar 0 -seta cl_swapattacks_seeker 0 -seta cl_swapattacks_fireball 0 seta cl_swapattacks_rocketlauncher 0 -seta cl_swapattacks_hook 0 seta cl_swapattacks_porto 0 +seta cl_swapattacks_minstanex 0 +seta cl_swapattacks_hook 0 +seta cl_swapattacks_hlac 0 +seta cl_swapattacks_tuba 0 +seta cl_swapattacks_rifle 0 +seta cl_swapattacks_fireball 0 +seta cl_swapattacks_seeker 0 // This part of the code is necessary to keep us firing when we switch weapons while holding a fire button pressed // Also updates the keys before firing, so we don't have to switch to another weapon and back to apply the changes diff --git a/hud_luminos.cfg b/hud_luminos.cfg index a3f3ed39e5..f32279f2b9 100644 --- a/hud_luminos.cfg +++ b/hud_luminos.cfg @@ -1,15 +1,15 @@ seta hud_skin "luminos" -seta hud_panel_bg "border_default" -seta hud_panel_bg_color "1 0.4375 0" -seta hud_panel_bg_color_team "0" +seta hud_panel_bg "0" +seta hud_panel_bg_color "0.6875 0.84375 1" +seta hud_panel_bg_color_team "1" seta hud_panel_bg_alpha "1" seta hud_panel_bg_border "8" seta hud_panel_bg_padding "2" seta hud_panel_fg_alpha "1" -seta hud_dock "dock" -seta hud_dock_color "0 0.1875 0.40625" -seta hud_dock_color_team "0.700000" +seta hud_dock "0" +seta hud_dock_color "0 0.449576 0.860796" +seta hud_dock_color_team "1" seta hud_dock_alpha "1" seta hud_progressbar_alpha "0.500000" @@ -19,38 +19,45 @@ 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_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_acceleration_neg_color "0.125 0.25 0.5" -seta _hud_panelorder "10 9 6 8 14 5 0 4 13 2 7 1 3 11 12 " +seta _hud_panelorder "15 12 9 10 5 6 14 0 7 4 11 2 1 3 8 13 16 " seta hud_configure_grid "1" seta hud_configure_grid_xsize "0.010000" seta hud_configure_grid_ysize "0.010000" -seta scr_centerpos "0.25" - seta hud_panel_weapons 1 -seta hud_panel_weapons_pos "0.920000 0.090000" -seta hud_panel_weapons_size "0.060000 0.630000" -seta hud_panel_weapons_bg "" +seta hud_panel_weapons_pos "0.930000 0.170000" +seta hud_panel_weapons_size "0.070000 0.650000" +seta hud_panel_weapons_bg "border_small_weapons" seta hud_panel_weapons_bg_color "" seta hud_panel_weapons_bg_color_team "" seta hud_panel_weapons_bg_alpha "" seta hud_panel_weapons_bg_border "" -seta hud_panel_weapons_bg_padding "" +seta hud_panel_weapons_bg_padding "4" +seta hud_panel_weapons_accuracy "1" +seta hud_panel_weapons_label "1" seta hud_panel_weapons_complainbubble "1" -seta hud_panel_weapons_complainbubble_padding "-10" +seta hud_panel_weapons_complainbubble_padding "2" +seta hud_panel_weapons_complainbubble_time "4" +seta hud_panel_weapons_complainbubble_fadetime "2" seta hud_panel_weapons_complainbubble_color_outofammo "0.8 0 0" seta hud_panel_weapons_complainbubble_color_donthave "0.8 0.5 0" seta hud_panel_weapons_complainbubble_color_unavailable "0 0.3 0.8" +seta hud_panel_weapons_ammo "1" seta hud_panel_weapons_ammo_color "0 1 0" seta hud_panel_weapons_ammo_alpha "1" seta hud_panel_weapons_aspect "2" -seta hud_panel_weapons_timeout "3" -seta hud_panel_weapons_timeout_effect "1" +seta hud_panel_weapons_timeout "5" +seta hud_panel_weapons_timeout_effect "3" +seta hud_panel_weapons_onlyowned "1" seta hud_panel_ammo 1 -seta hud_panel_ammo_pos "0.190000 0.920000" -seta hud_panel_ammo_size "0.120000 0.070000" +seta hud_panel_ammo_pos "0.330000 0.960000" +seta hud_panel_ammo_size "0.350000 0.040000" seta hud_panel_ammo_bg "" seta hud_panel_ammo_bg_color "" seta hud_panel_ammo_bg_color_team "" @@ -60,47 +67,49 @@ seta hud_panel_ammo_bg_padding "" seta hud_panel_ammo_onlycurrent "0" seta hud_panel_ammo_iconalign "0" seta hud_panel_ammo_progressbar "0" -seta hud_panel_ammo_progressbar_xoffset "0" seta hud_panel_ammo_progressbar_name "progressbar" +seta hud_panel_ammo_progressbar_xoffset "0" seta hud_panel_ammo_text "1" seta hud_panel_powerups 1 -seta hud_panel_powerups_pos "0.660000 0.940000" -seta hud_panel_powerups_size "0.330000 0.060000" -seta hud_panel_powerups_bg "0" +seta hud_panel_powerups_pos "0.360000 0.850000" +seta hud_panel_powerups_size "0.290000 0.030000" +seta hud_panel_powerups_bg "border_small_powerups" seta hud_panel_powerups_bg_color "" seta hud_panel_powerups_bg_color_team "" seta hud_panel_powerups_bg_alpha "" seta hud_panel_powerups_bg_border "" seta hud_panel_powerups_bg_padding "" seta hud_panel_powerups_flip "1" -seta hud_panel_powerups_iconalign "4" -seta hud_panel_powerups_baralign "4" +seta hud_panel_powerups_iconalign "3" +seta hud_panel_powerups_baralign "3" seta hud_panel_powerups_progressbar "1" seta hud_panel_powerups_progressbar_strength "progressbar" seta hud_panel_powerups_progressbar_shield "progressbar" seta hud_panel_powerups_text "1" seta hud_panel_healtharmor 1 -seta hud_panel_healtharmor_pos "0.330000 0.920000" -seta hud_panel_healtharmor_size "0.310000 0.070000" -seta hud_panel_healtharmor_bg "" +seta hud_panel_healtharmor_pos "0.320000 0.910000" +seta hud_panel_healtharmor_size "0.370000 0.060000" +seta hud_panel_healtharmor_bg "border_small_healtharmor" seta hud_panel_healtharmor_bg_color "" seta hud_panel_healtharmor_bg_color_team "" seta hud_panel_healtharmor_bg_alpha "" seta hud_panel_healtharmor_bg_border "" seta hud_panel_healtharmor_bg_padding "" seta hud_panel_healtharmor_flip "0" -seta hud_panel_healtharmor_iconalign "4" -seta hud_panel_healtharmor_baralign "4" +seta hud_panel_healtharmor_iconalign "3" +seta hud_panel_healtharmor_baralign "3" seta hud_panel_healtharmor_progressbar "1" seta hud_panel_healtharmor_progressbar_health "progressbar" seta hud_panel_healtharmor_progressbar_armor "progressbar" +seta hud_panel_healtharmor_progressbar_gfx "1" +seta hud_panel_healtharmor_progressbar_gfx_smooth "2" seta hud_panel_healtharmor_text "1" seta hud_panel_notify 1 -seta hud_panel_notify_pos "0.660000 0.730000" -seta hud_panel_notify_size "0.320000 0.190000" +seta hud_panel_notify_pos "0.710000 0.800000" +seta hud_panel_notify_size "0.290000 0.190000" seta hud_panel_notify_bg "0" seta hud_panel_notify_bg_color "" seta hud_panel_notify_bg_color_team "" @@ -108,41 +117,51 @@ seta hud_panel_notify_bg_alpha "" seta hud_panel_notify_bg_border "" seta hud_panel_notify_bg_padding "" seta hud_panel_notify_flip "0" +seta hud_panel_notify_fontsize "0.8" seta hud_panel_notify_print "1" +seta hud_panel_notify_time "10" +seta hud_panel_notify_fadetime "3" seta hud_panel_timer 1 -seta hud_panel_timer_pos "0.870000 0" -seta hud_panel_timer_size "0.130000 0.060000" -seta hud_panel_timer_bg "0" +seta hud_panel_timer_pos "0.800000 0.040000" +seta hud_panel_timer_size "0.070000 0.040000" +seta hud_panel_timer_bg "border_small_timer" seta hud_panel_timer_bg_color "" seta hud_panel_timer_bg_color_team "" seta hud_panel_timer_bg_alpha "" seta hud_panel_timer_bg_border "" seta hud_panel_timer_bg_padding "0" +seta hud_panel_timer_increment "0" -seta hud_panel_radar 1 -seta hud_panel_radar_pos "0.030000 0.020000" -seta hud_panel_radar_size "0.170000 0.220000" -seta hud_panel_radar_bg "" +seta hud_panel_radar 2 +seta hud_panel_radar_pos "0 0" +seta hud_panel_radar_size "0.200000 0.240000" +seta hud_panel_radar_bg "border_small_radar" seta hud_panel_radar_bg_color "" seta hud_panel_radar_bg_color_team "" -seta hud_panel_radar_bg_alpha "" +seta hud_panel_radar_bg_alpha "0.800000" seta hud_panel_radar_bg_border "" -seta hud_panel_radar_bg_padding "-3" +seta hud_panel_radar_bg_padding "-1" seta hud_panel_radar_foreground_alpha "0.800000" +seta hud_panel_radar_rotation "0" +seta hud_panel_radar_zoommode "0" +seta hud_panel_radar_scale "4096" +seta hud_panel_radar_maximized_scale "8192" +seta hud_panel_radar_maximized_size "0.5 0.5" seta hud_panel_score 1 -seta hud_panel_score_pos "0.020000 0.920000" -seta hud_panel_score_size "0.150000 0.070000" -seta hud_panel_score_bg "" +seta hud_panel_score_pos "0.890000 0.030000" +seta hud_panel_score_size "0.100000 0.050000" +seta hud_panel_score_bg "border_small_score" seta hud_panel_score_bg_color "" seta hud_panel_score_bg_color_team "" seta hud_panel_score_bg_alpha "" seta hud_panel_score_bg_border "" -seta hud_panel_score_bg_padding "" +seta hud_panel_score_bg_padding "0" +seta hud_panel_score_rankings "1" seta hud_panel_racetimer 1 -seta hud_panel_racetimer_pos "0.360000 0.090000" +seta hud_panel_racetimer_pos "0.360000 0.110000" seta hud_panel_racetimer_size "0.280000 0.090000" seta hud_panel_racetimer_bg "0" seta hud_panel_racetimer_bg_color "" @@ -152,29 +171,30 @@ seta hud_panel_racetimer_bg_border "" seta hud_panel_racetimer_bg_padding "" seta hud_panel_vote 1 -seta hud_panel_vote_pos "0.020000 0.650000" -seta hud_panel_vote_size "0.230000 0.110000" +seta hud_panel_vote_pos "0.710000 0.660000" +seta hud_panel_vote_size "0.210000 0.100000" seta hud_panel_vote_bg "" seta hud_panel_vote_bg_color "" seta hud_panel_vote_bg_color_team "" seta hud_panel_vote_bg_alpha "" seta hud_panel_vote_bg_border "" seta hud_panel_vote_bg_padding "" -seta hud_panel_vote_alreadyvoted_alpha "0.800000" +seta hud_panel_vote_alreadyvoted_alpha "0.500000" seta hud_panel_modicons 1 -seta hud_panel_modicons_pos "0.040000 0.270000" -seta hud_panel_modicons_size "0.080000 0.200000" -seta hud_panel_modicons_bg "" +seta hud_panel_modicons_pos "0.410000 0" +seta hud_panel_modicons_size "0.180000 0.080000" +seta hud_panel_modicons_bg "border_small_modicons" seta hud_panel_modicons_bg_color "" seta hud_panel_modicons_bg_color_team "" seta hud_panel_modicons_bg_alpha "" seta hud_panel_modicons_bg_border "" -seta hud_panel_modicons_bg_padding "" +seta hud_panel_modicons_bg_padding "0" +seta hud_panel_modicons_dom_layout "1" seta hud_panel_pressedkeys 1 -seta hud_panel_pressedkeys_pos "0.410000 0.710000" -seta hud_panel_pressedkeys_size "0.180000 0.130000" +seta hud_panel_pressedkeys_pos "0.450000 0.720000" +seta hud_panel_pressedkeys_size "0.110000 0.090000" seta hud_panel_pressedkeys_bg "0" seta hud_panel_pressedkeys_bg_color "" seta hud_panel_pressedkeys_bg_color_team "" @@ -184,8 +204,8 @@ seta hud_panel_pressedkeys_bg_padding "" seta hud_panel_pressedkeys_aspect "1.600000" seta hud_panel_chat 1 -seta hud_panel_chat_pos "0.020000 0.780000" -seta hud_panel_chat_size "0.630000 0.110000" +seta hud_panel_chat_pos "0.010000 0.700000" +seta hud_panel_chat_size "0.460000 0.190000" seta hud_panel_chat_bg "0" seta hud_panel_chat_bg_color "" seta hud_panel_chat_bg_color_team "" @@ -194,18 +214,20 @@ seta hud_panel_chat_bg_border "" seta hud_panel_chat_bg_padding "" seta hud_panel_engineinfo 0 -seta hud_panel_engineinfo_pos "0.910000 0.970000" -seta hud_panel_engineinfo_size "0.090000 0.030000" +seta hud_panel_engineinfo_pos "0.930000 0.970000" +seta hud_panel_engineinfo_size "0.070000 0.030000" seta hud_panel_engineinfo_bg "0" seta hud_panel_engineinfo_bg_color "" seta hud_panel_engineinfo_bg_color_team "" seta hud_panel_engineinfo_bg_alpha "" seta hud_panel_engineinfo_bg_border "" seta hud_panel_engineinfo_bg_padding "" +seta hud_panel_engineinfo_framecounter_time "0.1" +seta hud_panel_engineinfo_framecounter_decimals "0" seta hud_panel_infomessages 1 -seta hud_panel_infomessages_pos "0.510000 0" -seta hud_panel_infomessages_size "0.340000 0.090000" +seta hud_panel_infomessages_pos "0.720000 0.100000" +seta hud_panel_infomessages_size "0.280000 0.080000" seta hud_panel_infomessages_bg "0" seta hud_panel_infomessages_bg_color "" seta hud_panel_infomessages_bg_color_team "" @@ -214,4 +236,50 @@ seta hud_panel_infomessages_bg_border "" seta hud_panel_infomessages_bg_padding "0" seta hud_panel_infomessages_flip "1" +seta hud_panel_physics 3 +seta hud_panel_physics_pos "0.420000 0.620000" +seta hud_panel_physics_size "0.170000 0.080000" +seta hud_panel_physics_bg "" +seta hud_panel_physics_bg_color "" +seta hud_panel_physics_bg_color_team "" +seta hud_panel_physics_bg_alpha "" +seta hud_panel_physics_bg_border "" +seta hud_panel_physics_bg_padding "" +seta hud_panel_physics_speed_unit "3" +seta hud_panel_physics_speed_unit_show "1" +seta hud_panel_physics_speed_max "1800" +seta hud_panel_physics_speed_vertical "0" +seta hud_panel_physics_topspeed "1" +seta hud_panel_physics_topspeed_time "4" +seta hud_panel_physics_acceleration_max "1.5" +seta hud_panel_physics_acceleration_vertical "0" +seta hud_panel_physics_flip "0" +seta hud_panel_physics_baralign "0" +seta hud_panel_physics_progressbar "1" +seta hud_panel_physics_acceleration_mode "0" +seta hud_panel_physics_text "1" + +seta hud_panel_centerprint 1 +seta hud_panel_centerprint_pos "0.175000 0.220000" +seta hud_panel_centerprint_size "0.650000 0.220000" +seta hud_panel_centerprint_bg "0" +seta hud_panel_centerprint_bg_color "" +seta hud_panel_centerprint_bg_color_team "" +seta hud_panel_centerprint_bg_alpha "" +seta hud_panel_centerprint_bg_border "" +seta hud_panel_centerprint_bg_padding "" +seta hud_panel_centerprint_align "0.5" +seta hud_panel_centerprint_flip "0" +seta hud_panel_centerprint_fontscale "1" +seta hud_panel_centerprint_time "3" +seta hud_panel_centerprint_fade_in "0.2" +seta hud_panel_centerprint_fade_out "0.5" +seta hud_panel_centerprint_fade_subsequent "1" +seta hud_panel_centerprint_fade_subsequent_passone "3" +seta hud_panel_centerprint_fade_subsequent_passone_minalpha "0.5" +seta hud_panel_centerprint_fade_subsequent_passtwo "10" +seta hud_panel_centerprint_fade_subsequent_passtwo_minalpha "0.5" +seta hud_panel_centerprint_fade_subsequent_minfontsize "0.75" +seta hud_panel_centerprint_fade_minfontsize "0" + menu_sync diff --git a/hud_luminos_minimal.cfg b/hud_luminos_minimal.cfg index 8e39416314..52a7d96c13 100644 --- a/hud_luminos_minimal.cfg +++ b/hud_luminos_minimal.cfg @@ -19,15 +19,16 @@ 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_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_acceleration_neg_color "0.125 0.25 0.5" -seta _hud_panelorder "10 3 0 14 6 9 13 4 1 2 11 12 7 5 8 " +seta _hud_panelorder "10 3 0 14 6 9 13 4 1 2 11 12 7 5 8 15 16 " seta hud_configure_grid "1" seta hud_configure_grid_xsize "0.010000" seta hud_configure_grid_ysize "0.010000" -seta scr_centerpos "0.25" - seta hud_panel_weapons 1 seta hud_panel_weapons_pos "0.350000 0.940000" seta hud_panel_weapons_size "0.300000 0.060000" @@ -37,16 +38,22 @@ seta hud_panel_weapons_bg_color_team "" seta hud_panel_weapons_bg_alpha "" seta hud_panel_weapons_bg_border "" seta hud_panel_weapons_bg_padding "" +seta hud_panel_weapons_accuracy "1" +seta hud_panel_weapons_label "1" seta hud_panel_weapons_complainbubble "1" seta hud_panel_weapons_complainbubble_padding "-10" +seta hud_panel_weapons_complainbubble_time "1" +seta hud_panel_weapons_complainbubble_fadetime "0.25" seta hud_panel_weapons_complainbubble_color_outofammo "0.8 0 0" seta hud_panel_weapons_complainbubble_color_donthave "0.8 0.5 0" seta hud_panel_weapons_complainbubble_color_unavailable "0 0.3 0.8" +seta hud_panel_weapons_ammo "1" seta hud_panel_weapons_ammo_color "0 1 0" seta hud_panel_weapons_ammo_alpha "1" seta hud_panel_weapons_aspect "2" seta hud_panel_weapons_timeout "0" seta hud_panel_weapons_timeout_effect "0" +seta hud_panel_weapons_onlyowned "1" seta hud_panel_ammo 1 seta hud_panel_ammo_pos "0.650000 0.890000" @@ -60,8 +67,8 @@ seta hud_panel_ammo_bg_padding "" seta hud_panel_ammo_onlycurrent "0" seta hud_panel_ammo_iconalign "0" seta hud_panel_ammo_progressbar "0" -seta hud_panel_ammo_progressbar_xoffset "0" seta hud_panel_ammo_progressbar_name "progressbar" +seta hud_panel_ammo_progressbar_xoffset "0" seta hud_panel_ammo_text "1" seta hud_panel_powerups 1 @@ -96,6 +103,8 @@ seta hud_panel_healtharmor_baralign "3" seta hud_panel_healtharmor_progressbar "1" seta hud_panel_healtharmor_progressbar_health "progressbar" seta hud_panel_healtharmor_progressbar_armor "progressbar" +seta hud_panel_healtharmor_progressbar_gfx "1" +seta hud_panel_healtharmor_progressbar_gfx_smooth "2" seta hud_panel_healtharmor_text "1" seta hud_panel_notify 1 @@ -108,7 +117,10 @@ seta hud_panel_notify_bg_alpha "" seta hud_panel_notify_bg_border "" seta hud_panel_notify_bg_padding "" seta hud_panel_notify_flip "1" +seta hud_panel_notify_fontsize "0.8" seta hud_panel_notify_print "0" +seta hud_panel_notify_time "10" +seta hud_panel_notify_fadetime "3" seta hud_panel_timer 1 seta hud_panel_timer_pos "0.435000 0" @@ -119,6 +131,7 @@ seta hud_panel_timer_bg_color_team "" seta hud_panel_timer_bg_alpha "" seta hud_panel_timer_bg_border "" seta hud_panel_timer_bg_padding "0" +seta hud_panel_timer_increment "0" seta hud_panel_radar 2 seta hud_panel_radar_pos "0.810000 0" @@ -130,6 +143,11 @@ seta hud_panel_radar_bg_alpha "0.500000" seta hud_panel_radar_bg_border "0" seta hud_panel_radar_bg_padding "0" seta hud_panel_radar_foreground_alpha "0.500000" +seta hud_panel_radar_rotation "0" +seta hud_panel_radar_zoommode "0" +seta hud_panel_radar_scale "4096" +seta hud_panel_radar_maximized_scale "8192" +seta hud_panel_radar_maximized_size "0.5 0.5" seta hud_panel_score 1 seta hud_panel_score_pos "0.465000 0.045000" @@ -140,6 +158,7 @@ seta hud_panel_score_bg_color_team "" seta hud_panel_score_bg_alpha "" seta hud_panel_score_bg_border "" seta hud_panel_score_bg_padding "" +seta hud_panel_score_rankings "1" seta hud_panel_racetimer 1 seta hud_panel_racetimer_pos "0.360000 0.090000" @@ -171,6 +190,7 @@ seta hud_panel_modicons_bg_color_team "" seta hud_panel_modicons_bg_alpha "" seta hud_panel_modicons_bg_border "" seta hud_panel_modicons_bg_padding "" +seta hud_panel_modicons_dom_layout "1" seta hud_panel_pressedkeys 1 seta hud_panel_pressedkeys_pos "0.450000 0.650000" @@ -202,6 +222,8 @@ seta hud_panel_engineinfo_bg_color_team "" seta hud_panel_engineinfo_bg_alpha "" seta hud_panel_engineinfo_bg_border "" seta hud_panel_engineinfo_bg_padding "" +seta hud_panel_engineinfo_framecounter_time "0.1" +seta hud_panel_engineinfo_framecounter_decimals "0" seta hud_panel_infomessages 1 seta hud_panel_infomessages_pos "0.710000 0" @@ -214,4 +236,50 @@ seta hud_panel_infomessages_bg_border "" seta hud_panel_infomessages_bg_padding "0" seta hud_panel_infomessages_flip "1" +seta hud_panel_physics 3 +seta hud_panel_physics_pos "0.440000 0.590000" +seta hud_panel_physics_size "0.120000 0.050000" +seta hud_panel_physics_bg "" +seta hud_panel_physics_bg_color "" +seta hud_panel_physics_bg_color_team "" +seta hud_panel_physics_bg_alpha "" +seta hud_panel_physics_bg_border "" +seta hud_panel_physics_bg_padding "" +seta hud_panel_physics_speed_unit "3" +seta hud_panel_physics_speed_unit_show "1" +seta hud_panel_physics_speed_max "1800" +seta hud_panel_physics_speed_vertical "0" +seta hud_panel_physics_topspeed "1" +seta hud_panel_physics_topspeed_time "4" +seta hud_panel_physics_acceleration_max "1.5" +seta hud_panel_physics_acceleration_vertical "0" +seta hud_panel_physics_flip "0" +seta hud_panel_physics_baralign "0" +seta hud_panel_physics_progressbar "3" +seta hud_panel_physics_acceleration_mode "0" +seta hud_panel_physics_text "1" + +seta hud_panel_centerprint 1 +seta hud_panel_centerprint_pos "0.175000 0.220000" +seta hud_panel_centerprint_size "0.650000 0.220000" +seta hud_panel_centerprint_bg "0" +seta hud_panel_centerprint_bg_color "" +seta hud_panel_centerprint_bg_color_team "" +seta hud_panel_centerprint_bg_alpha "" +seta hud_panel_centerprint_bg_border "" +seta hud_panel_centerprint_bg_padding "" +seta hud_panel_centerprint_align "0.5" +seta hud_panel_centerprint_flip "0" +seta hud_panel_centerprint_fontscale "1" +seta hud_panel_centerprint_time "3" +seta hud_panel_centerprint_fade_in "0.2" +seta hud_panel_centerprint_fade_out "0.5" +seta hud_panel_centerprint_fade_subsequent "1" +seta hud_panel_centerprint_fade_subsequent_passone "3" +seta hud_panel_centerprint_fade_subsequent_passone_minalpha "0.5" +seta hud_panel_centerprint_fade_subsequent_passtwo "10" +seta hud_panel_centerprint_fade_subsequent_passtwo_minalpha "0.5" +seta hud_panel_centerprint_fade_subsequent_minfontsize "0.75" +seta hud_panel_centerprint_fade_minfontsize "0" + menu_sync diff --git a/hud_luminos_minimal_xhair.cfg b/hud_luminos_minimal_xhair.cfg new file mode 100644 index 0000000000..2d5e07600c --- /dev/null +++ b/hud_luminos_minimal_xhair.cfg @@ -0,0 +1,285 @@ +seta hud_skin "luminos_xhair" +seta hud_panel_bg "0" +seta hud_panel_bg_color "1 0.4375 0" +seta hud_panel_bg_color_team "0" +seta hud_panel_bg_alpha "1" +seta hud_panel_bg_border "8" +seta hud_panel_bg_padding "2" +seta hud_panel_fg_alpha "1" + +seta hud_dock "0" +seta hud_dock_color "0 0.449576 0.860796" +seta hud_dock_color_team "0.700000" +seta hud_dock_alpha "1" + +seta hud_progressbar_alpha "0.3" +seta hud_progressbar_strength_color "0 0 0.6" +seta hud_progressbar_shield_color "0.6 0 0.6" +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_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_acceleration_neg_color "0.125 0.25 0.5" + +seta _hud_panelorder "15 3 1 2 11 10 0 14 6 9 13 4 12 7 5 8 16 " + +seta hud_configure_grid "1" +seta hud_configure_grid_xsize "0.010000" +seta hud_configure_grid_ysize "0.010000" + +seta hud_panel_weapons 1 +seta hud_panel_weapons_pos "0.350000 0.940000" +seta hud_panel_weapons_size "0.300000 0.060000" +seta hud_panel_weapons_bg "" +seta hud_panel_weapons_bg_color "" +seta hud_panel_weapons_bg_color_team "" +seta hud_panel_weapons_bg_alpha "" +seta hud_panel_weapons_bg_border "" +seta hud_panel_weapons_bg_padding "" +seta hud_panel_weapons_accuracy "1" +seta hud_panel_weapons_label "1" +seta hud_panel_weapons_complainbubble "1" +seta hud_panel_weapons_complainbubble_padding "-10" +seta hud_panel_weapons_complainbubble_time "1" +seta hud_panel_weapons_complainbubble_fadetime "0.25" +seta hud_panel_weapons_complainbubble_color_outofammo "0.8 0 0" +seta hud_panel_weapons_complainbubble_color_donthave "0.8 0.5 0" +seta hud_panel_weapons_complainbubble_color_unavailable "0 0.3 0.8" +seta hud_panel_weapons_ammo "1" +seta hud_panel_weapons_ammo_color "0 1 0" +seta hud_panel_weapons_ammo_alpha "1" +seta hud_panel_weapons_aspect "2" +seta hud_panel_weapons_timeout "0" +seta hud_panel_weapons_timeout_effect "0" +seta hud_panel_weapons_onlyowned "1" + +seta hud_panel_ammo 1 +seta hud_panel_ammo_pos "0.450000 0.630000" +seta hud_panel_ammo_size "0.080000 0.040000" +seta hud_panel_ammo_bg "" +seta hud_panel_ammo_bg_color "" +seta hud_panel_ammo_bg_color_team "" +seta hud_panel_ammo_bg_alpha "" +seta hud_panel_ammo_bg_border "" +seta hud_panel_ammo_bg_padding "" +seta hud_panel_ammo_onlycurrent "1" +seta hud_panel_ammo_iconalign "0" +seta hud_panel_ammo_progressbar "1" +seta hud_panel_ammo_progressbar_name "progressbar_ammo" +seta hud_panel_ammo_progressbar_xoffset "0.32" +seta hud_panel_ammo_text "1" + +seta hud_panel_powerups 1 +seta hud_panel_powerups_pos "0.270000 0.940000" +seta hud_panel_powerups_size "0.080000 0.060000" +seta hud_panel_powerups_bg "0" +seta hud_panel_powerups_bg_color "" +seta hud_panel_powerups_bg_color_team "" +seta hud_panel_powerups_bg_alpha "" +seta hud_panel_powerups_bg_border "" +seta hud_panel_powerups_bg_padding "-3" +seta hud_panel_powerups_flip "1" +seta hud_panel_powerups_iconalign "1" +seta hud_panel_powerups_baralign "1" +seta hud_panel_powerups_progressbar "1" +seta hud_panel_powerups_progressbar_strength "progressbar" +seta hud_panel_powerups_progressbar_shield "progressbar" +seta hud_panel_powerups_text "1" + +seta hud_panel_healtharmor 1 +seta hud_panel_healtharmor_pos "0.350000 0.380000" +seta hud_panel_healtharmor_size "0.070000 0.240000" +seta hud_panel_healtharmor_bg "border_healtharmor" +seta hud_panel_healtharmor_bg_color "0.464391 0.464391 0.464391" +seta hud_panel_healtharmor_bg_color_team "" +seta hud_panel_healtharmor_bg_alpha "0.600000" +seta hud_panel_healtharmor_bg_border "-1" +seta hud_panel_healtharmor_bg_padding "0" +seta hud_panel_healtharmor_flip "0" +seta hud_panel_healtharmor_iconalign "1" +seta hud_panel_healtharmor_baralign "1" +seta hud_panel_healtharmor_progressbar "1" +seta hud_panel_healtharmor_progressbar_health "progressbar_health" +seta hud_panel_healtharmor_progressbar_armor "progressbar_armor" +seta hud_panel_healtharmor_progressbar_gfx "1" +seta hud_panel_healtharmor_progressbar_gfx_smooth "2" +seta hud_panel_healtharmor_text "0" + +seta hud_panel_notify 1 +seta hud_panel_notify_pos "0 0" +seta hud_panel_notify_size "0.210000 0.260000" +seta hud_panel_notify_bg "0" +seta hud_panel_notify_bg_color "" +seta hud_panel_notify_bg_color_team "" +seta hud_panel_notify_bg_alpha "" +seta hud_panel_notify_bg_border "" +seta hud_panel_notify_bg_padding "" +seta hud_panel_notify_flip "1" +seta hud_panel_notify_fontsize "0.8" +seta hud_panel_notify_print "0" +seta hud_panel_notify_time "10" +seta hud_panel_notify_fadetime "3" + +seta hud_panel_timer 1 +seta hud_panel_timer_pos "0.435000 0" +seta hud_panel_timer_size "0.135000 0.060000" +seta hud_panel_timer_bg "0" +seta hud_panel_timer_bg_color "" +seta hud_panel_timer_bg_color_team "" +seta hud_panel_timer_bg_alpha "" +seta hud_panel_timer_bg_border "" +seta hud_panel_timer_bg_padding "0" +seta hud_panel_timer_increment "0" + +seta hud_panel_radar 2 +seta hud_panel_radar_pos "0.810000 0" +seta hud_panel_radar_size "0.190000 0.250000" +seta hud_panel_radar_bg "border_radar" +seta hud_panel_radar_bg_color "" +seta hud_panel_radar_bg_color_team "" +seta hud_panel_radar_bg_alpha "0.500000" +seta hud_panel_radar_bg_border "0" +seta hud_panel_radar_bg_padding "0" +seta hud_panel_radar_foreground_alpha "0.500000" +seta hud_panel_radar_rotation "0" +seta hud_panel_radar_zoommode "0" +seta hud_panel_radar_scale "4096" +seta hud_panel_radar_maximized_scale "8192" +seta hud_panel_radar_maximized_size "0.5 0.5" + +seta hud_panel_score 1 +seta hud_panel_score_pos "0.465000 0.045000" +seta hud_panel_score_size "0.090000 0.060000" +seta hud_panel_score_bg "" +seta hud_panel_score_bg_color "" +seta hud_panel_score_bg_color_team "" +seta hud_panel_score_bg_alpha "" +seta hud_panel_score_bg_border "" +seta hud_panel_score_bg_padding "" +seta hud_panel_score_rankings "1" + +seta hud_panel_racetimer 1 +seta hud_panel_racetimer_pos "0.360000 0.090000" +seta hud_panel_racetimer_size "0.280000 0.090000" +seta hud_panel_racetimer_bg "0" +seta hud_panel_racetimer_bg_color "" +seta hud_panel_racetimer_bg_color_team "" +seta hud_panel_racetimer_bg_alpha "" +seta hud_panel_racetimer_bg_border "" +seta hud_panel_racetimer_bg_padding "" + +seta hud_panel_vote 1 +seta hud_panel_vote_pos "0 0.890000" +seta hud_panel_vote_size "0.170000 0.110000" +seta hud_panel_vote_bg "" +seta hud_panel_vote_bg_color "" +seta hud_panel_vote_bg_color_team "" +seta hud_panel_vote_bg_alpha "" +seta hud_panel_vote_bg_border "" +seta hud_panel_vote_bg_padding "" +seta hud_panel_vote_alreadyvoted_alpha "0.800000" + +seta hud_panel_modicons 1 +seta hud_panel_modicons_pos "0.560000 0" +seta hud_panel_modicons_size "0.050000 0.100000" +seta hud_panel_modicons_bg "" +seta hud_panel_modicons_bg_color "" +seta hud_panel_modicons_bg_color_team "" +seta hud_panel_modicons_bg_alpha "" +seta hud_panel_modicons_bg_border "" +seta hud_panel_modicons_bg_padding "" +seta hud_panel_modicons_dom_layout "1" + +seta hud_panel_pressedkeys 1 +seta hud_panel_pressedkeys_pos "0.450000 0.690000" +seta hud_panel_pressedkeys_size "0.100000 0.110000" +seta hud_panel_pressedkeys_bg "0" +seta hud_panel_pressedkeys_bg_color "" +seta hud_panel_pressedkeys_bg_color_team "" +seta hud_panel_pressedkeys_bg_alpha "" +seta hud_panel_pressedkeys_bg_border "" +seta hud_panel_pressedkeys_bg_padding "" +seta hud_panel_pressedkeys_aspect "1.600000" + +seta hud_panel_chat 1 +seta hud_panel_chat_pos "0 0.775000" +seta hud_panel_chat_size "0.460000 0.110000" +seta hud_panel_chat_bg "0" +seta hud_panel_chat_bg_color "" +seta hud_panel_chat_bg_color_team "" +seta hud_panel_chat_bg_alpha "" +seta hud_panel_chat_bg_border "" +seta hud_panel_chat_bg_padding "" + +seta hud_panel_engineinfo 0 +seta hud_panel_engineinfo_pos "0.910000 0.970000" +seta hud_panel_engineinfo_size "0.090000 0.030000" +seta hud_panel_engineinfo_bg "0" +seta hud_panel_engineinfo_bg_color "" +seta hud_panel_engineinfo_bg_color_team "" +seta hud_panel_engineinfo_bg_alpha "" +seta hud_panel_engineinfo_bg_border "" +seta hud_panel_engineinfo_bg_padding "" +seta hud_panel_engineinfo_framecounter_time "0.1" +seta hud_panel_engineinfo_framecounter_decimals "0" + +seta hud_panel_infomessages 1 +seta hud_panel_infomessages_pos "0.710000 0" +seta hud_panel_infomessages_size "0.290000 0.100000" +seta hud_panel_infomessages_bg "0" +seta hud_panel_infomessages_bg_color "" +seta hud_panel_infomessages_bg_color_team "" +seta hud_panel_infomessages_bg_alpha "" +seta hud_panel_infomessages_bg_border "" +seta hud_panel_infomessages_bg_padding "0" +seta hud_panel_infomessages_flip "1" + +seta hud_panel_physics 3 +seta hud_panel_physics_pos "0.270000 0.730000" +seta hud_panel_physics_size "0.170000 0.030000" +seta hud_panel_physics_bg "" +seta hud_panel_physics_bg_color "" +seta hud_panel_physics_bg_color_team "" +seta hud_panel_physics_bg_alpha "" +seta hud_panel_physics_bg_border "" +seta hud_panel_physics_bg_padding "" +seta hud_panel_physics_speed_unit "3" +seta hud_panel_physics_speed_unit_show "1" +seta hud_panel_physics_speed_max "1800" +seta hud_panel_physics_speed_vertical "0" +seta hud_panel_physics_topspeed "1" +seta hud_panel_physics_topspeed_time "4" +seta hud_panel_physics_acceleration_max "1.5" +seta hud_panel_physics_acceleration_vertical "0" +seta hud_panel_physics_flip "0" +seta hud_panel_physics_baralign "0" +seta hud_panel_physics_progressbar "3" +seta hud_panel_physics_acceleration_mode "0" +seta hud_panel_physics_text "1" + +seta hud_panel_centerprint 1 +seta hud_panel_centerprint_pos "0.175000 0.220000" +seta hud_panel_centerprint_size "0.650000 0.220000" +seta hud_panel_centerprint_bg "0" +seta hud_panel_centerprint_bg_color "" +seta hud_panel_centerprint_bg_color_team "" +seta hud_panel_centerprint_bg_alpha "" +seta hud_panel_centerprint_bg_border "" +seta hud_panel_centerprint_bg_padding "" +seta hud_panel_centerprint_align "0.5" +seta hud_panel_centerprint_flip "0" +seta hud_panel_centerprint_fontscale "1" +seta hud_panel_centerprint_time "3" +seta hud_panel_centerprint_fade_in "0.2" +seta hud_panel_centerprint_fade_out "0.5" +seta hud_panel_centerprint_fade_subsequent "1" +seta hud_panel_centerprint_fade_subsequent_passone "3" +seta hud_panel_centerprint_fade_subsequent_passone_minalpha "0.5" +seta hud_panel_centerprint_fade_subsequent_passtwo "10" +seta hud_panel_centerprint_fade_subsequent_passtwo_minalpha "0.5" +seta hud_panel_centerprint_fade_subsequent_minfontsize "0.75" +seta hud_panel_centerprint_fade_minfontsize "0" + +menu_sync diff --git a/hud_luminos_old.cfg b/hud_luminos_old.cfg new file mode 100644 index 0000000000..fe7f660855 --- /dev/null +++ b/hud_luminos_old.cfg @@ -0,0 +1,285 @@ +seta hud_skin "luminos" +seta hud_panel_bg "border_default" +seta hud_panel_bg_color "1 0.4375 0" +seta hud_panel_bg_color_team "0" +seta hud_panel_bg_alpha "1" +seta hud_panel_bg_border "8" +seta hud_panel_bg_padding "2" +seta hud_panel_fg_alpha "1" + +seta hud_dock "dock" +seta hud_dock_color "0 0.1875 0.40625" +seta hud_dock_color_team "0.700000" +seta hud_dock_alpha "1" + +seta hud_progressbar_alpha "0.500000" +seta hud_progressbar_strength_color "0 0 0.6" +seta hud_progressbar_shield_color "0.6 0 0.6" +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_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_acceleration_neg_color "0.125 0.25 0.5" + +seta _hud_panelorder "15 10 9 6 8 14 5 0 4 13 2 7 1 3 11 12 16 " + +seta hud_configure_grid "1" +seta hud_configure_grid_xsize "0.010000" +seta hud_configure_grid_ysize "0.010000" + +seta hud_panel_weapons 1 +seta hud_panel_weapons_pos "0.920000 0.090000" +seta hud_panel_weapons_size "0.060000 0.630000" +seta hud_panel_weapons_bg "" +seta hud_panel_weapons_bg_color "" +seta hud_panel_weapons_bg_color_team "" +seta hud_panel_weapons_bg_alpha "" +seta hud_panel_weapons_bg_border "" +seta hud_panel_weapons_bg_padding "" +seta hud_panel_weapons_accuracy "1" +seta hud_panel_weapons_label "1" +seta hud_panel_weapons_complainbubble "1" +seta hud_panel_weapons_complainbubble_padding "-10" +seta hud_panel_weapons_complainbubble_time "1" +seta hud_panel_weapons_complainbubble_fadetime "0.25" +seta hud_panel_weapons_complainbubble_color_outofammo "0.8 0 0" +seta hud_panel_weapons_complainbubble_color_donthave "0.8 0.5 0" +seta hud_panel_weapons_complainbubble_color_unavailable "0 0.3 0.8" +seta hud_panel_weapons_ammo "1" +seta hud_panel_weapons_ammo_color "0 1 0" +seta hud_panel_weapons_ammo_alpha "1" +seta hud_panel_weapons_aspect "2" +seta hud_panel_weapons_timeout "3" +seta hud_panel_weapons_timeout_effect "1" +seta hud_panel_weapons_onlyowned "1" + +seta hud_panel_ammo 1 +seta hud_panel_ammo_pos "0.190000 0.920000" +seta hud_panel_ammo_size "0.120000 0.070000" +seta hud_panel_ammo_bg "" +seta hud_panel_ammo_bg_color "" +seta hud_panel_ammo_bg_color_team "" +seta hud_panel_ammo_bg_alpha "" +seta hud_panel_ammo_bg_border "" +seta hud_panel_ammo_bg_padding "" +seta hud_panel_ammo_onlycurrent "0" +seta hud_panel_ammo_iconalign "0" +seta hud_panel_ammo_progressbar "0" +seta hud_panel_ammo_progressbar_name "progressbar" +seta hud_panel_ammo_progressbar_xoffset "0" +seta hud_panel_ammo_text "1" + +seta hud_panel_powerups 1 +seta hud_panel_powerups_pos "0.660000 0.940000" +seta hud_panel_powerups_size "0.330000 0.060000" +seta hud_panel_powerups_bg "0" +seta hud_panel_powerups_bg_color "" +seta hud_panel_powerups_bg_color_team "" +seta hud_panel_powerups_bg_alpha "" +seta hud_panel_powerups_bg_border "" +seta hud_panel_powerups_bg_padding "" +seta hud_panel_powerups_flip "1" +seta hud_panel_powerups_iconalign "3" +seta hud_panel_powerups_baralign "3" +seta hud_panel_powerups_progressbar "1" +seta hud_panel_powerups_progressbar_strength "progressbar" +seta hud_panel_powerups_progressbar_shield "progressbar" +seta hud_panel_powerups_text "1" + +seta hud_panel_healtharmor 1 +seta hud_panel_healtharmor_pos "0.330000 0.920000" +seta hud_panel_healtharmor_size "0.310000 0.070000" +seta hud_panel_healtharmor_bg "" +seta hud_panel_healtharmor_bg_color "" +seta hud_panel_healtharmor_bg_color_team "" +seta hud_panel_healtharmor_bg_alpha "" +seta hud_panel_healtharmor_bg_border "" +seta hud_panel_healtharmor_bg_padding "" +seta hud_panel_healtharmor_flip "0" +seta hud_panel_healtharmor_iconalign "3" +seta hud_panel_healtharmor_baralign "3" +seta hud_panel_healtharmor_progressbar "1" +seta hud_panel_healtharmor_progressbar_health "progressbar" +seta hud_panel_healtharmor_progressbar_armor "progressbar" +seta hud_panel_healtharmor_progressbar_gfx "1" +seta hud_panel_healtharmor_progressbar_gfx_smooth "2" +seta hud_panel_healtharmor_text "1" + +seta hud_panel_notify 1 +seta hud_panel_notify_pos "0.660000 0.730000" +seta hud_panel_notify_size "0.320000 0.190000" +seta hud_panel_notify_bg "0" +seta hud_panel_notify_bg_color "" +seta hud_panel_notify_bg_color_team "" +seta hud_panel_notify_bg_alpha "" +seta hud_panel_notify_bg_border "" +seta hud_panel_notify_bg_padding "" +seta hud_panel_notify_flip "0" +seta hud_panel_notify_fontsize "0.8" +seta hud_panel_notify_print "1" +seta hud_panel_notify_time "10" +seta hud_panel_notify_fadetime "3" + +seta hud_panel_timer 1 +seta hud_panel_timer_pos "0.870000 0" +seta hud_panel_timer_size "0.130000 0.060000" +seta hud_panel_timer_bg "0" +seta hud_panel_timer_bg_color "" +seta hud_panel_timer_bg_color_team "" +seta hud_panel_timer_bg_alpha "" +seta hud_panel_timer_bg_border "" +seta hud_panel_timer_bg_padding "0" +seta hud_panel_timer_increment "0" + +seta hud_panel_radar 2 +seta hud_panel_radar_pos "0.030000 0.020000" +seta hud_panel_radar_size "0.170000 0.220000" +seta hud_panel_radar_bg "" +seta hud_panel_radar_bg_color "" +seta hud_panel_radar_bg_color_team "" +seta hud_panel_radar_bg_alpha "" +seta hud_panel_radar_bg_border "" +seta hud_panel_radar_bg_padding "-3" +seta hud_panel_radar_foreground_alpha "0.800000" +seta hud_panel_radar_rotation "0" +seta hud_panel_radar_zoommode "0" +seta hud_panel_radar_scale "4096" +seta hud_panel_radar_maximized_scale "8192" +seta hud_panel_radar_maximized_size "0.5 0.5" + +seta hud_panel_score 1 +seta hud_panel_score_pos "0.020000 0.920000" +seta hud_panel_score_size "0.150000 0.070000" +seta hud_panel_score_bg "" +seta hud_panel_score_bg_color "" +seta hud_panel_score_bg_color_team "" +seta hud_panel_score_bg_alpha "" +seta hud_panel_score_bg_border "" +seta hud_panel_score_bg_padding "" +seta hud_panel_score_rankings "1" + +seta hud_panel_racetimer 1 +seta hud_panel_racetimer_pos "0.360000 0.090000" +seta hud_panel_racetimer_size "0.280000 0.090000" +seta hud_panel_racetimer_bg "0" +seta hud_panel_racetimer_bg_color "" +seta hud_panel_racetimer_bg_color_team "" +seta hud_panel_racetimer_bg_alpha "" +seta hud_panel_racetimer_bg_border "" +seta hud_panel_racetimer_bg_padding "" + +seta hud_panel_vote 1 +seta hud_panel_vote_pos "0.020000 0.650000" +seta hud_panel_vote_size "0.230000 0.110000" +seta hud_panel_vote_bg "" +seta hud_panel_vote_bg_color "" +seta hud_panel_vote_bg_color_team "" +seta hud_panel_vote_bg_alpha "" +seta hud_panel_vote_bg_border "" +seta hud_panel_vote_bg_padding "" +seta hud_panel_vote_alreadyvoted_alpha "0.800000" + +seta hud_panel_modicons 1 +seta hud_panel_modicons_pos "0.040000 0.270000" +seta hud_panel_modicons_size "0.080000 0.200000" +seta hud_panel_modicons_bg "" +seta hud_panel_modicons_bg_color "" +seta hud_panel_modicons_bg_color_team "" +seta hud_panel_modicons_bg_alpha "" +seta hud_panel_modicons_bg_border "" +seta hud_panel_modicons_bg_padding "" +seta hud_panel_modicons_dom_layout "1" + +seta hud_panel_pressedkeys 1 +seta hud_panel_pressedkeys_pos "0.410000 0.710000" +seta hud_panel_pressedkeys_size "0.180000 0.130000" +seta hud_panel_pressedkeys_bg "0" +seta hud_panel_pressedkeys_bg_color "" +seta hud_panel_pressedkeys_bg_color_team "" +seta hud_panel_pressedkeys_bg_alpha "" +seta hud_panel_pressedkeys_bg_border "" +seta hud_panel_pressedkeys_bg_padding "" +seta hud_panel_pressedkeys_aspect "1.600000" + +seta hud_panel_chat 1 +seta hud_panel_chat_pos "0.020000 0.780000" +seta hud_panel_chat_size "0.630000 0.110000" +seta hud_panel_chat_bg "0" +seta hud_panel_chat_bg_color "" +seta hud_panel_chat_bg_color_team "" +seta hud_panel_chat_bg_alpha "" +seta hud_panel_chat_bg_border "" +seta hud_panel_chat_bg_padding "" + +seta hud_panel_engineinfo 0 +seta hud_panel_engineinfo_pos "0.910000 0.970000" +seta hud_panel_engineinfo_size "0.090000 0.030000" +seta hud_panel_engineinfo_bg "0" +seta hud_panel_engineinfo_bg_color "" +seta hud_panel_engineinfo_bg_color_team "" +seta hud_panel_engineinfo_bg_alpha "" +seta hud_panel_engineinfo_bg_border "" +seta hud_panel_engineinfo_bg_padding "" +seta hud_panel_engineinfo_framecounter_time "0.1" +seta hud_panel_engineinfo_framecounter_decimals "0" + +seta hud_panel_infomessages 1 +seta hud_panel_infomessages_pos "0.510000 0" +seta hud_panel_infomessages_size "0.340000 0.090000" +seta hud_panel_infomessages_bg "0" +seta hud_panel_infomessages_bg_color "" +seta hud_panel_infomessages_bg_color_team "" +seta hud_panel_infomessages_bg_alpha "" +seta hud_panel_infomessages_bg_border "" +seta hud_panel_infomessages_bg_padding "0" +seta hud_panel_infomessages_flip "1" + +seta hud_panel_physics 3 +seta hud_panel_physics_pos "0.410000 0.590000" +seta hud_panel_physics_size "0.180000 0.100000" +seta hud_panel_physics_bg "" +seta hud_panel_physics_bg_color "" +seta hud_panel_physics_bg_color_team "" +seta hud_panel_physics_bg_alpha "" +seta hud_panel_physics_bg_border "" +seta hud_panel_physics_bg_padding "" +seta hud_panel_physics_speed_unit "3" +seta hud_panel_physics_speed_unit_show "1" +seta hud_panel_physics_speed_max "1800" +seta hud_panel_physics_speed_vertical "0" +seta hud_panel_physics_topspeed "1" +seta hud_panel_physics_topspeed_time "4" +seta hud_panel_physics_acceleration_max "1.5" +seta hud_panel_physics_acceleration_vertical "0" +seta hud_panel_physics_flip "0" +seta hud_panel_physics_baralign "0" +seta hud_panel_physics_progressbar "1" +seta hud_panel_physics_acceleration_mode "0" +seta hud_panel_physics_text "1" + +seta hud_panel_centerprint 1 +seta hud_panel_centerprint_pos "0.175000 0.220000" +seta hud_panel_centerprint_size "0.650000 0.220000" +seta hud_panel_centerprint_bg "0" +seta hud_panel_centerprint_bg_color "" +seta hud_panel_centerprint_bg_color_team "" +seta hud_panel_centerprint_bg_alpha "" +seta hud_panel_centerprint_bg_border "" +seta hud_panel_centerprint_bg_padding "" +seta hud_panel_centerprint_align "0.5" +seta hud_panel_centerprint_flip "0" +seta hud_panel_centerprint_fontscale "1" +seta hud_panel_centerprint_time "3" +seta hud_panel_centerprint_fade_in "0.2" +seta hud_panel_centerprint_fade_out "0.5" +seta hud_panel_centerprint_fade_subsequent "1" +seta hud_panel_centerprint_fade_subsequent_passone "3" +seta hud_panel_centerprint_fade_subsequent_passone_minalpha "0.5" +seta hud_panel_centerprint_fade_subsequent_passtwo "10" +seta hud_panel_centerprint_fade_subsequent_passtwo_minalpha "0.5" +seta hud_panel_centerprint_fade_subsequent_minfontsize "0.75" +seta hud_panel_centerprint_fade_minfontsize "0" + +menu_sync diff --git a/hud_luminos_xhair_minimal.cfg b/hud_luminos_xhair_minimal.cfg deleted file mode 100644 index 10f7afd149..0000000000 --- a/hud_luminos_xhair_minimal.cfg +++ /dev/null @@ -1,216 +0,0 @@ -seta hud_skin "luminos_xhair" -seta hud_panel_bg "0" -seta hud_panel_bg_color "1 0.4375 0" -seta hud_panel_bg_color_team "0" -seta hud_panel_bg_alpha "1" -seta hud_panel_bg_border "8" -seta hud_panel_bg_padding "2" -seta hud_panel_fg_alpha "1" - -seta hud_dock "0" -seta hud_dock_color "0 0.449576 0.860796" -seta hud_dock_color_team "0.700000" -seta hud_dock_alpha "1" - -seta hud_progressbar_alpha "0.3" -seta hud_progressbar_strength_color "0 0 0.6" -seta hud_progressbar_shield_color "0.6 0 0.6" -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_nexball_color "0.7 0.1 0" - -seta _hud_panelorder "3 1 2 11 10 0 14 6 9 13 4 12 7 5 8 " - -seta hud_configure_grid "1" -seta hud_configure_grid_xsize "0.010000" -seta hud_configure_grid_ysize "0.010000" - -seta scr_centerpos "0.25" - -seta hud_panel_weapons 1 -seta hud_panel_weapons_pos "0.350000 0.940000" -seta hud_panel_weapons_size "0.300000 0.060000" -seta hud_panel_weapons_bg "" -seta hud_panel_weapons_bg_color "" -seta hud_panel_weapons_bg_color_team "" -seta hud_panel_weapons_bg_alpha "" -seta hud_panel_weapons_bg_border "" -seta hud_panel_weapons_bg_padding "" -seta hud_panel_weapons_complainbubble "1" -seta hud_panel_weapons_complainbubble_padding "-10" -seta hud_panel_weapons_complainbubble_color_outofammo "0.8 0 0" -seta hud_panel_weapons_complainbubble_color_donthave "0.8 0.5 0" -seta hud_panel_weapons_complainbubble_color_unavailable "0 0.3 0.8" -seta hud_panel_weapons_ammo_color "0 1 0" -seta hud_panel_weapons_ammo_alpha "1" -seta hud_panel_weapons_aspect "2" -seta hud_panel_weapons_timeout "0" -seta hud_panel_weapons_timeout_effect "0" - -seta hud_panel_ammo 1 -seta hud_panel_ammo_pos "0.450000 0.630000" -seta hud_panel_ammo_size "0.080000 0.040000" -seta hud_panel_ammo_bg "" -seta hud_panel_ammo_bg_color "" -seta hud_panel_ammo_bg_color_team "" -seta hud_panel_ammo_bg_alpha "" -seta hud_panel_ammo_bg_border "" -seta hud_panel_ammo_bg_padding "" -seta hud_panel_ammo_onlycurrent "1" -seta hud_panel_ammo_iconalign "0" -seta hud_panel_ammo_progressbar "1" -seta hud_panel_ammo_progressbar_name "progressbar_ammo" -seta hud_panel_ammo_progressbar_xoffset "0.32" -seta hud_panel_ammo_text "1" - -seta hud_panel_powerups 1 -seta hud_panel_powerups_pos "0.270000 0.940000" -seta hud_panel_powerups_size "0.080000 0.060000" -seta hud_panel_powerups_bg "0" -seta hud_panel_powerups_bg_color "" -seta hud_panel_powerups_bg_color_team "" -seta hud_panel_powerups_bg_alpha "" -seta hud_panel_powerups_bg_border "" -seta hud_panel_powerups_bg_padding "-3" -seta hud_panel_powerups_flip "1" -seta hud_panel_powerups_iconalign "1" -seta hud_panel_powerups_baralign "1" -seta hud_panel_powerups_progressbar "1" -seta hud_panel_powerups_progressbar_strength "progressbar" -seta hud_panel_powerups_progressbar_shield "progressbar" - -seta hud_panel_healtharmor 1 -seta hud_panel_healtharmor_pos "0.350000 0.380000" -seta hud_panel_healtharmor_size "0.070000 0.240000" -seta hud_panel_healtharmor_bg "border_healtharmor" -seta hud_panel_healtharmor_bg_color "0.464391 0.464391 0.464391" -seta hud_panel_healtharmor_bg_color_team "" -seta hud_panel_healtharmor_bg_alpha "0.600000" -seta hud_panel_healtharmor_bg_border "-1" -seta hud_panel_healtharmor_bg_padding "0" -seta hud_panel_healtharmor_flip "0" -seta hud_panel_healtharmor_iconalign "1" -seta hud_panel_healtharmor_baralign "1" -seta hud_panel_healtharmor_progressbar "1" -seta hud_panel_healtharmor_progressbar_health "progressbar_health" -seta hud_panel_healtharmor_progressbar_armor "progressbar_armor" -seta hud_panel_healtharmor_text "0" - -seta hud_panel_notify 1 -seta hud_panel_notify_pos "0 0" -seta hud_panel_notify_size "0.210000 0.260000" -seta hud_panel_notify_bg "0" -seta hud_panel_notify_bg_color "" -seta hud_panel_notify_bg_color_team "" -seta hud_panel_notify_bg_alpha "" -seta hud_panel_notify_bg_border "" -seta hud_panel_notify_bg_padding "" -seta hud_panel_notify_flip "1" -seta hud_panel_notify_print "0" - -seta hud_panel_timer 1 -seta hud_panel_timer_pos "0.435000 0" -seta hud_panel_timer_size "0.135000 0.060000" -seta hud_panel_timer_bg "0" -seta hud_panel_timer_bg_color "" -seta hud_panel_timer_bg_color_team "" -seta hud_panel_timer_bg_alpha "" -seta hud_panel_timer_bg_border "" -seta hud_panel_timer_bg_padding "0" - -seta hud_panel_radar 2 -seta hud_panel_radar_pos "0.810000 0" -seta hud_panel_radar_size "0.190000 0.250000" -seta hud_panel_radar_bg "border_radar" -seta hud_panel_radar_bg_color "" -seta hud_panel_radar_bg_color_team "" -seta hud_panel_radar_bg_alpha "0.500000" -seta hud_panel_radar_bg_border "0" -seta hud_panel_radar_bg_padding "0" -seta hud_panel_radar_foreground_alpha "0.500000" - -seta hud_panel_score 1 -seta hud_panel_score_pos "0.465000 0.045000" -seta hud_panel_score_size "0.090000 0.060000" -seta hud_panel_score_bg "" -seta hud_panel_score_bg_color "" -seta hud_panel_score_bg_color_team "" -seta hud_panel_score_bg_alpha "" -seta hud_panel_score_bg_border "" -seta hud_panel_score_bg_padding "" - -seta hud_panel_racetimer 1 -seta hud_panel_racetimer_pos "0.360000 0.090000" -seta hud_panel_racetimer_size "0.280000 0.090000" -seta hud_panel_racetimer_bg "0" -seta hud_panel_racetimer_bg_color "" -seta hud_panel_racetimer_bg_color_team "" -seta hud_panel_racetimer_bg_alpha "" -seta hud_panel_racetimer_bg_border "" -seta hud_panel_racetimer_bg_padding "" - -seta hud_panel_vote 1 -seta hud_panel_vote_pos "0 0.890000" -seta hud_panel_vote_size "0.170000 0.110000" -seta hud_panel_vote_bg "" -seta hud_panel_vote_bg_color "" -seta hud_panel_vote_bg_color_team "" -seta hud_panel_vote_bg_alpha "" -seta hud_panel_vote_bg_border "" -seta hud_panel_vote_bg_padding "" -seta hud_panel_vote_alreadyvoted_alpha "0.800000" - -seta hud_panel_modicons 1 -seta hud_panel_modicons_pos "0.560000 0" -seta hud_panel_modicons_size "0.050000 0.100000" -seta hud_panel_modicons_bg "" -seta hud_panel_modicons_bg_color "" -seta hud_panel_modicons_bg_color_team "" -seta hud_panel_modicons_bg_alpha "" -seta hud_panel_modicons_bg_border "" -seta hud_panel_modicons_bg_padding "" - -seta hud_panel_pressedkeys 1 -seta hud_panel_pressedkeys_pos "0.450000 0.690000" -seta hud_panel_pressedkeys_size "0.100000 0.110000" -seta hud_panel_pressedkeys_bg "0" -seta hud_panel_pressedkeys_bg_color "" -seta hud_panel_pressedkeys_bg_color_team "" -seta hud_panel_pressedkeys_bg_alpha "" -seta hud_panel_pressedkeys_bg_border "" -seta hud_panel_pressedkeys_bg_padding "" -seta hud_panel_pressedkeys_aspect "1.600000" - -seta hud_panel_chat 1 -seta hud_panel_chat_pos "0 0.775000" -seta hud_panel_chat_size "0.460000 0.110000" -seta hud_panel_chat_bg "0" -seta hud_panel_chat_bg_color "" -seta hud_panel_chat_bg_color_team "" -seta hud_panel_chat_bg_alpha "" -seta hud_panel_chat_bg_border "" -seta hud_panel_chat_bg_padding "" - -seta hud_panel_engineinfo 0 -seta hud_panel_engineinfo_pos "0.910000 0.970000" -seta hud_panel_engineinfo_size "0.090000 0.030000" -seta hud_panel_engineinfo_bg "0" -seta hud_panel_engineinfo_bg_color "" -seta hud_panel_engineinfo_bg_color_team "" -seta hud_panel_engineinfo_bg_alpha "" -seta hud_panel_engineinfo_bg_border "" -seta hud_panel_engineinfo_bg_padding "" - -seta hud_panel_infomessages 1 -seta hud_panel_infomessages_pos "0.710000 0" -seta hud_panel_infomessages_size "0.290000 0.100000" -seta hud_panel_infomessages_bg "0" -seta hud_panel_infomessages_bg_color "" -seta hud_panel_infomessages_bg_color_team "" -seta hud_panel_infomessages_bg_alpha "" -seta hud_panel_infomessages_bg_border "" -seta hud_panel_infomessages_bg_padding "0" -seta hud_panel_infomessages_flip "1" - -menu_sync diff --git a/hud_nexuiz.cfg b/hud_nexuiz.cfg index 681b7378e0..5c21383706 100644 --- a/hud_nexuiz.cfg +++ b/hud_nexuiz.cfg @@ -19,34 +19,41 @@ 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_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_acceleration_neg_color "0.125 0.25 0.5" -seta _hud_panelorder "0 11 8 5 6 14 9 13 7 2 3 1 10 12 4 " +seta _hud_panelorder "15 0 11 8 5 6 14 9 13 7 2 3 1 10 12 4 16 " seta hud_configure_grid "1" seta hud_configure_grid_xsize "0.01" seta hud_configure_grid_ysize "0.01" -seta scr_centerpos "0.25" - seta hud_panel_weapons 1 -seta hud_panel_weapons_pos "0.370000 0.870000" -seta hud_panel_weapons_size "0.340000 0.060000" +seta hud_panel_weapons_pos "0.375000 0.870000" +seta hud_panel_weapons_size "0.300000 0.060000" seta hud_panel_weapons_bg "0" seta hud_panel_weapons_bg_color "" seta hud_panel_weapons_bg_color_team "" seta hud_panel_weapons_bg_alpha "" seta hud_panel_weapons_bg_border "" seta hud_panel_weapons_bg_padding "-5" +seta hud_panel_weapons_accuracy "1" +seta hud_panel_weapons_label "1" seta hud_panel_weapons_complainbubble "1" seta hud_panel_weapons_complainbubble_padding "-10" +seta hud_panel_weapons_complainbubble_time "1" +seta hud_panel_weapons_complainbubble_fadetime "0.25" seta hud_panel_weapons_complainbubble_color_outofammo "0.8 0 0" seta hud_panel_weapons_complainbubble_color_donthave "0.8 0.5 0" seta hud_panel_weapons_complainbubble_color_unavailable "0 0.3 0.8" +seta hud_panel_weapons_ammo "1" seta hud_panel_weapons_ammo_color "0 1 0" seta hud_panel_weapons_ammo_alpha "1" seta hud_panel_weapons_aspect "2" seta hud_panel_weapons_timeout "0" seta hud_panel_weapons_timeout_effect "0" +seta hud_panel_weapons_onlyowned "0" seta hud_panel_ammo 1 seta hud_panel_ammo_pos "0.160000 0.910000" @@ -60,8 +67,8 @@ seta hud_panel_ammo_bg_padding "" seta hud_panel_ammo_onlycurrent "0" seta hud_panel_ammo_iconalign "0" seta hud_panel_ammo_progressbar "0" -seta hud_panel_ammo_progressbar_xoffset "0" seta hud_panel_ammo_progressbar_name "progressbar" +seta hud_panel_ammo_progressbar_xoffset "0" seta hud_panel_ammo_text "1" seta hud_panel_powerups 1 @@ -96,19 +103,24 @@ seta hud_panel_healtharmor_baralign "0" seta hud_panel_healtharmor_progressbar "0" seta hud_panel_healtharmor_progressbar_health "progressbar" seta hud_panel_healtharmor_progressbar_armor "progressbar" +seta hud_panel_healtharmor_progressbar_gfx "1" +seta hud_panel_healtharmor_progressbar_gfx_smooth "2" seta hud_panel_healtharmor_text "1" seta hud_panel_notify 0 seta hud_panel_notify_pos "0 0.650000" seta hud_panel_notify_size "0.300000 0.070000" -seta hud_panel_notify_bg "" +seta hud_panel_notify_bg "0" seta hud_panel_notify_bg_color "" seta hud_panel_notify_bg_color_team "" -seta hud_panel_notify_bg_alpha "0" +seta hud_panel_notify_bg_alpha "" seta hud_panel_notify_bg_border "" seta hud_panel_notify_bg_padding "" seta hud_panel_notify_flip "0" +seta hud_panel_notify_fontsize "1" seta hud_panel_notify_print "1" +seta hud_panel_notify_time "10" +seta hud_panel_notify_fadetime "3" seta hud_panel_timer 1 seta hud_panel_timer_pos "0.850000 0" @@ -119,9 +131,10 @@ seta hud_panel_timer_bg_color_team "" seta hud_panel_timer_bg_alpha "" seta hud_panel_timer_bg_border "" seta hud_panel_timer_bg_padding "0" +seta hud_panel_timer_increment "0" seta hud_panel_radar 2 -seta hud_panel_radar_pos "0.800000 0" +seta hud_panel_radar_pos "0 0" seta hud_panel_radar_size "0.200000 0.260000" seta hud_panel_radar_bg "border_radar" seta hud_panel_radar_bg_color "" @@ -130,16 +143,22 @@ seta hud_panel_radar_bg_alpha "0.500000" seta hud_panel_radar_bg_border "0" seta hud_panel_radar_bg_padding "0" seta hud_panel_radar_foreground_alpha "1" +seta hud_panel_radar_rotation "0" +seta hud_panel_radar_zoommode "0" +seta hud_panel_radar_scale "4096" +seta hud_panel_radar_maximized_scale "8192" +seta hud_panel_radar_maximized_size "0.5 0.5" seta hud_panel_score 1 seta hud_panel_score_pos "0.760000 0.910000" -seta hud_panel_score_size "0.240000 0.090000" +seta hud_panel_score_size "0.200000 0.080000" seta hud_panel_score_bg "0" seta hud_panel_score_bg_color "" seta hud_panel_score_bg_color_team "" seta hud_panel_score_bg_alpha "" seta hud_panel_score_bg_border "" seta hud_panel_score_bg_padding "" +seta hud_panel_score_rankings "0" seta hud_panel_racetimer 1 seta hud_panel_racetimer_pos "0.360000 0.140000" @@ -171,6 +190,7 @@ seta hud_panel_modicons_bg_color_team "" seta hud_panel_modicons_bg_alpha "" seta hud_panel_modicons_bg_border "" seta hud_panel_modicons_bg_padding "" +seta hud_panel_modicons_dom_layout "1" seta hud_panel_pressedkeys 1 seta hud_panel_pressedkeys_pos "0.440000 0.760000" @@ -202,6 +222,8 @@ seta hud_panel_engineinfo_bg_color_team "" seta hud_panel_engineinfo_bg_alpha "" seta hud_panel_engineinfo_bg_border "" seta hud_panel_engineinfo_bg_padding "" +seta hud_panel_engineinfo_framecounter_time "0.1" +seta hud_panel_engineinfo_framecounter_decimals "0" seta hud_panel_infomessages 1 seta hud_panel_infomessages_pos "0.700000 0.620000" @@ -214,4 +236,50 @@ seta hud_panel_infomessages_bg_border "" seta hud_panel_infomessages_bg_padding "" seta hud_panel_infomessages_flip "1" +seta hud_panel_physics 3 +seta hud_panel_physics_pos "0.430000 0.640000" +seta hud_panel_physics_size "0.140000 0.100000" +seta hud_panel_physics_bg "0" +seta hud_panel_physics_bg_color "" +seta hud_panel_physics_bg_color_team "" +seta hud_panel_physics_bg_alpha "" +seta hud_panel_physics_bg_border "" +seta hud_panel_physics_bg_padding "" +seta hud_panel_physics_speed_unit "3" +seta hud_panel_physics_speed_unit_show "1" +seta hud_panel_physics_speed_max "1800" +seta hud_panel_physics_speed_vertical "0" +seta hud_panel_physics_topspeed "1" +seta hud_panel_physics_topspeed_time "4" +seta hud_panel_physics_acceleration_max "1.5" +seta hud_panel_physics_acceleration_vertical "0" +seta hud_panel_physics_flip "0" +seta hud_panel_physics_baralign "0" +seta hud_panel_physics_progressbar "3" +seta hud_panel_physics_acceleration_mode "0" +seta hud_panel_physics_text "1" + +seta hud_panel_centerprint 1 +seta hud_panel_centerprint_pos "0.175000 0.260000" +seta hud_panel_centerprint_size "0.650000 0.200000" +seta hud_panel_centerprint_bg "0" +seta hud_panel_centerprint_bg_color "" +seta hud_panel_centerprint_bg_color_team "" +seta hud_panel_centerprint_bg_alpha "" +seta hud_panel_centerprint_bg_border "" +seta hud_panel_centerprint_bg_padding "" +seta hud_panel_centerprint_align "0.5" +seta hud_panel_centerprint_flip "0" +seta hud_panel_centerprint_fontscale "1" +seta hud_panel_centerprint_time "3" +seta hud_panel_centerprint_fade_in "0.2" +seta hud_panel_centerprint_fade_out "0.5" +seta hud_panel_centerprint_fade_subsequent "1" +seta hud_panel_centerprint_fade_subsequent_passone "3" +seta hud_panel_centerprint_fade_subsequent_passone_minalpha "0.5" +seta hud_panel_centerprint_fade_subsequent_passtwo "10" +seta hud_panel_centerprint_fade_subsequent_passtwo_minalpha "0.5" +seta hud_panel_centerprint_fade_subsequent_minfontsize "0.75" +seta hud_panel_centerprint_fade_minfontsize "0" + menu_sync diff --git a/input-demoseeking.cfg b/input-demoseeking.cfg new file mode 100644 index 0000000000..e069ad94ad --- /dev/null +++ b/input-demoseeking.cfg @@ -0,0 +1,32 @@ +alias playdemo "set _demo_name \"$1\"" +set _demo_name "" +set _demo_seeking 0 +set _demo_good 0 +set _demo_time_increasing 0 +set _demo_time 0 +set _demo_time_step 0 +alias seekdemo "_seekdemo_1_$_demo_seeking $1" +alias _seekdemo_1_0 "cl_cmd rpn time dup \"$1\" add dup /_demo_time exch def le /_demo_time_increasing exch def; _seekdemo_2" +alias _seekdemo_1_1 "cl_cmd rpn time _demo_time \"$1\" add dup /_demo_time exch def le /_demo_time_increasing exch def; _seekdemo_2" +alias _seekdemo_2 "_demo_seeking 1; r_render 0; snd_startnonloopingsounds 0; _seekdemo_3_$_demo_time_increasing" +alias _seekdemo_3_0 "playdemo \"$_demo_name\"; _seekdemo_4; defer 10 _seekdemo_9_2" +alias _seekdemo_3_1 "_seekdemo_7" +alias _seekdemo_4 "set _demo_good 0; cl_cmd rpn /_demo_good 1 def; _seekdemo_5" +alias _seekdemo_5 "_seekdemo_6_$_demo_good" +alias _seekdemo_6_0 "defer 0.02 _seekdemo_4" +alias _seekdemo_6_1 "defer clear; _seekdemo_7" +alias _seekdemo_7 "set _demo_time_step 2; cl_cmd rpn _demo_time time gt /_demo_time_step exch def; _seekdemo_8" +alias _seekdemo_8 "_seekdemo_9_$_demo_time_step" +alias _seekdemo_9_0 "slowmo 1; set _demo_seeking 0; r_render 1; snd_startnonloopingsounds 1" +alias _seekdemo_9_1 "cl_cmd rpn _demo_time time sub 10 mul 1 add /slowmo exch def; defer 0.001 _seekdemo_7" +alias _seekdemo_9_2 "slowmo 1; set _demo_seeking 0; r_render 1; snd_startnonloopingsounds 1; echo SEEK FAILED" +bind , "seekdemo -5" +bind . "seekdemo +5" +bind m "seekdemo -30" +bind - "seekdemo +30" +bind / "seekdemo +30" + +// Usage: +// start a demo +// use ,. keys to seek -5/+5 seconds +// use m/ keys (left/right of ,.) to seek -30/+30 seconds diff --git a/input-tuba.cfg b/input-tuba.cfg index b83af0752b..a129ed766f 100644 --- a/input-tuba.cfg +++ b/input-tuba.cfg @@ -11,10 +11,10 @@ // Then, grab a Tuba, then play notes on your MIDI keyboard! // // If you have no keyboard input, you can map the tuba notes to your keyboard: +// for German keyboard layout // in_bindmap 3 0 -// for US keyboard layout, and +// for US keyboard layout // in_bindmap 4 0 -// for German keyboard layout alias +tuba_l "+moveleft; +tuba_$*" alias -tuba_l "-moveleft; -tuba_$*" diff --git a/keybinds.txt b/keybinds.txt index 453e09165f..5cba08f707 100644 --- a/keybinds.txt +++ b/keybinds.txt @@ -17,21 +17,23 @@ "weaplast" "previously used" "weapbest" "best" "reload" "reload" -"impulse 1" "laser" -"impulse 2" "shotgun" -"impulse 3" "machine gun / rifle" -"impulse 4" "mortar" -"impulse 5" "electro" -"impulse 6" "crylink / hlac" -"impulse 7" "nex / minstanex" -"impulse 8" "hagar" -"impulse 9" "rocket launcher / fireball" -"impulse 14" "porto / hook" +"weapon_group_1" "Laser" +"weapon_group_2" "Shotgun" +"weapon_group_3" "Machine Gun" +"weapon_group_4" "Mortar / Mine Layer" +"weapon_group_5" "Electro" +"weapon_group_6" "Crylink / HLAC" +"weapon_group_7" "Nex / Rifle" +"weapon_group_8" "Hagar / Seeker" +"weapon_group_9" "Rocket Launcher / Fireball" +"weapon_group_0" "Port-O-Launch / Hook" "" "" "" "View" -"+zoom" "zoom" +"+zoom" "hold zoom" +"togglezoom" "toggle zoom" "+showscores" "show scores" "screenshot" "screen shot" +"+hud_panel_radar_maximized" "maximize radar" "" "" "" "Communicate" "messagemode" "public chat" @@ -51,9 +53,11 @@ "messagemode2" "team chat" "team_auto" "auto-join team" "menu_showteamselect" "team menu" +"menu_showsandboxtools" "sandbox menu" "spec" "enter spectator mode" "dropweapon" "drop weapon" "+use" "drop key / drop flag" +"+button8" "drag object" "" "" "" "User defined" "+userbind 1" "$userbind1" diff --git a/keybinds.txt.de b/keybinds.txt.de new file mode 100644 index 0000000000..6f2c78b511 --- /dev/null +++ b/keybinds.txt.de @@ -0,0 +1,91 @@ +"" "Bewegung" +"+forward" "vorwärts" +"+back" "rückwärts" +"+moveleft" "links" +"+moveright" "rechts" +"+jump" "springen / schwimmen" +"+crouch" "ducken / sinken" +"+hook" "Enterhaken / Jetpack" +"" "" +"" "Angriff" +"+fire" "1. Feuermodus" +"+fire2" "2. Feuermodus" +"" "" +"" "Waffe wechseln" +"weapprev" "vorherige" +"weapnext" "nächste" +"weaplast" "zuletzt benutzte" +"weapbest" "beste" +"reload" "nachladen" +"impulse 1" "Laser" +"impulse 2" "Shotgun" +"impulse 3" "Machine Gun" +"impulse 4" "Mortar / Mine Layer" +"impulse 5" "Electro" +"impulse 6" "Crylink / HLAC" +"impulse 7" "Nex / MinstaNex / Rifle" +"impulse 8" "Hagar / Seeker" +"impulse 9" "Rocket Launcher / Fireball" +"impulse 14" "Port-O-Launch / Hook" +"" "" +"" "Anzeige" +"+zoom" "Vergrößern (festhalten)" +"togglezoom" "Vergrößern (umschalten)" +"+showscores" "Tabelle anzeigen" +"screenshot" "Bildschirmfoto" +"" "" +"" "Kommunikation" +"messagemode" "Nachricht an alle" +"messagemode2" "Nachricht ans Team" +"+con_chat_maximize" "Chat-Historie zeigen" +"vyes" "Abstimmung: JA" +"vno" "Abstimmung: Nein" +"ready" "Bereitschaft signalisieren" +"" "" +"" "Client" +"+show_info" "Serverinfo anzeigen" +"toggleconsole" "Konsole öffnen" +"disconnect" "Verbindung trennen" +"quit" "Beenden" +"" "" +"" "Teamplay" +"messagemode2" "Nachricht ans Team" +"team_auto" "Team automatisch wählen" +"menu_showteamselect" "Team auswählen" +"spec" "Zuschauen" +"dropweapon" "Waffe wegwerfen" +"+use" "Schlüssel oder Flagge wegwerfen" +"" "" +"" "Benutzerdefiniert" +"+userbind 1" "$userbind1" +"+userbind 2" "$userbind2" +"+userbind 3" "$userbind3" +"+userbind 4" "$userbind4" +"+userbind 5" "$userbind5" +"+userbind 6" "$userbind6" +"+userbind 7" "$userbind7" +"+userbind 8" "$userbind8" +"+userbind 9" "$userbind9" +"+userbind 10" "$userbind10" +"+userbind 11" "$userbind11" +"+userbind 12" "$userbind12" +"+userbind 13" "$userbind13" +"+userbind 14" "$userbind14" +"+userbind 15" "$userbind15" +"+userbind 16" "$userbind16" +"+userbind 17" "$userbind17" +"+userbind 18" "$userbind18" +"+userbind 19" "$userbind19" +"+userbind 20" "$userbind20" +"+userbind 21" "$userbind21" +"+userbind 22" "$userbind22" +"+userbind 23" "$userbind23" +"+userbind 24" "$userbind24" +"+userbind 25" "$userbind25" +"+userbind 26" "$userbind26" +"+userbind 27" "$userbind27" +"+userbind 28" "$userbind28" +"+userbind 29" "$userbind29" +"+userbind 30" "$userbind30" +"+userbind 31" "$userbind31" +"+userbind 32" "$userbind32" diff --git a/keybinds.txt.es b/keybinds.txt.es new file mode 100644 index 0000000000..e92f03b80e --- /dev/null +++ b/keybinds.txt.es @@ -0,0 +1,91 @@ +"" "Movimiento" +"+forward" "adelante" +"+back" "atrás" +"+moveleft" "izquierda" +"+moveright" "derecha" +"+jump" "saltar / nadar" +"+crouch" "agacharse / bajar" +"+hook" "gancho / jet pack" +"" "" +"" "Ataque" +"+fire" "ataque primario" +"+fire2" "ataque secundario" +"" "" +"" "Cambio de arma" +"weapprev" "anterior" +"weapnext" "siguiente" +"weaplast" "anteriormente usado" +"weapbest" "mejor" +"reload" "recargar" +"impulse 1" "Laser" +"impulse 2" "Shotgun" +"impulse 3" "Machine Gun" +"impulse 4" "Mortar / Mine Layer" +"impulse 5" "Electro" +"impulse 6" "Crylink / HLAC" +"impulse 7" "Nex / MinstaNex / Rifle" +"impulse 8" "Hagar / Seeker" +"impulse 9" "Rocket Launcher / Fireball" +"impulse 14" "Port-O-Launch / Hook" +"" "" +"" "Vista" +"+zoom" "mantener zoom" +"togglezoom" "cambiar zoom" +"+showscores" "mostrar puntaje" +"screenshot" "captura de pantalla" +"" "" +"" "Communicación" +"messagemode" "chat público" +"messagemode2" "chat de equipo" +"+con_chat_maximize" "mostrar historial del chat" +"vyes" "votar SI" +"vno" "votar NO" +"ready" "preparado" +"" "" +"" "Cliente" +"+show_info" "información del servidor" +"toggleconsole" "entrar en la consola" +"disconnect" "desconectar" +"quit" "salir" +"" "" +"" "Juego en equipo" +"messagemode2" "chat de equipo" +"team_auto" "unirse al equipo automáticamente" +"menu_showteamselect" "menu de equipo" +"spec" "entrar al modo espectador" +"dropweapon" "soltar arma" +"+use" "soltar llave / soltar bandera" +"" "" +"" "Definido por el usuario" +"+userbind 1" "$userbind1" +"+userbind 2" "$userbind2" +"+userbind 3" "$userbind3" +"+userbind 4" "$userbind4" +"+userbind 5" "$userbind5" +"+userbind 6" "$userbind6" +"+userbind 7" "$userbind7" +"+userbind 8" "$userbind8" +"+userbind 9" "$userbind9" +"+userbind 10" "$userbind10" +"+userbind 11" "$userbind11" +"+userbind 12" "$userbind12" +"+userbind 13" "$userbind13" +"+userbind 14" "$userbind14" +"+userbind 15" "$userbind15" +"+userbind 16" "$userbind16" +"+userbind 17" "$userbind17" +"+userbind 18" "$userbind18" +"+userbind 19" "$userbind19" +"+userbind 20" "$userbind20" +"+userbind 21" "$userbind21" +"+userbind 22" "$userbind22" +"+userbind 23" "$userbind23" +"+userbind 24" "$userbind24" +"+userbind 25" "$userbind25" +"+userbind 26" "$userbind26" +"+userbind 27" "$userbind27" +"+userbind 28" "$userbind28" +"+userbind 29" "$userbind29" +"+userbind 30" "$userbind30" +"+userbind 31" "$userbind31" +"+userbind 32" "$userbind32" diff --git a/keybinds.txt.fr b/keybinds.txt.fr new file mode 100644 index 0000000000..c5cb242b18 --- /dev/null +++ b/keybinds.txt.fr @@ -0,0 +1,91 @@ +"" "Mouvement" +"+forward" "avancer" +"+back" "reculer" +"+moveleft" "gauche" +"+moveright" "droite" +"+jump" "sauter / nager" +"+crouch" "s'accroupir / couler" +"+hook" "grappin / jet pack" +"" "" +"" "Attaque" +"+fire" "tir primaire" +"+fire2" "tir secondaire" +"" "" +"" "Changement d'armes" +"weapprev" "arme précédente" +"weapnext" "arme suivante" +"weaplast" "dernière utilisée" +"weapbest" "meilleure arme" +"reload" "recharger" +"impulse 1" "laser" +"impulse 2" "shotgun" +"impulse 3" "machine gun / rifle" +"impulse 4" "mortar" +"impulse 5" "electro" +"impulse 6" "crylink / hlac" +"impulse 7" "nex / minstanex" +"impulse 8" "hagar" +"impulse 9" "rocket launcher / fireball" +"impulse 14" "porto / hook" +"" "" +"" "Vue" +"+zoom" "zoom clic enfoncé" +"togglezoom" "zoom 2 clics" +"+showscores" "montrer les scores (enfoncé)" +"screenshot" "capture d'écran" +"" "" +"" "Communiquer" +"messagemode" "chat public" +"messagemode2" "chat d'équipe" +"+con_chat_maximize" "historique du chat (enfoncé)" +"vyes" "voter OUI" +"vno" "voter NON" +"ready" "prêt (en mode échauffement)" +"" "" +"" "Joueur" +"+show_info" "information serveur" +"toggleconsole" "ouvrir la console" +"disconnect" "se déconnecter" +"quit" "quitter" +"" "" +"" "Équipe" +"messagemode2" "chat d'équipe" +"team_auto" "auto-joindre une équipe" +"menu_showteamselect" "séléction d'équipe" +"spec" "mode spectateur" +"dropweapon" "lâcher l'arme" +"+use" "lâcher la clé / lâcher le drapeau" +"" "" +"" "Utilisateur" +"+userbind 1" "$userbind1" +"+userbind 2" "$userbind2" +"+userbind 3" "$userbind3" +"+userbind 4" "$userbind4" +"+userbind 5" "$userbind5" +"+userbind 6" "$userbind6" +"+userbind 7" "$userbind7" +"+userbind 8" "$userbind8" +"+userbind 9" "$userbind9" +"+userbind 10" "$userbind10" +"+userbind 11" "$userbind11" +"+userbind 12" "$userbind12" +"+userbind 13" "$userbind13" +"+userbind 14" "$userbind14" +"+userbind 15" "$userbind15" +"+userbind 16" "$userbind16" +"+userbind 17" "$userbind17" +"+userbind 18" "$userbind18" +"+userbind 19" "$userbind19" +"+userbind 20" "$userbind20" +"+userbind 21" "$userbind21" +"+userbind 22" "$userbind22" +"+userbind 23" "$userbind23" +"+userbind 24" "$userbind24" +"+userbind 25" "$userbind25" +"+userbind 26" "$userbind26" +"+userbind 27" "$userbind27" +"+userbind 28" "$userbind28" +"+userbind 29" "$userbind29" +"+userbind 30" "$userbind30" +"+userbind 31" "$userbind31" +"+userbind 32" "$userbind32" diff --git a/keybinds.txt.hu b/keybinds.txt.hu new file mode 100644 index 0000000000..d20eec65d6 --- /dev/null +++ b/keybinds.txt.hu @@ -0,0 +1,91 @@ +"" "Mozgás" +"+forward" "előre" +"+back" "hátra" +"+moveleft" "balra lépés" +"+moveright" "jobbra lépés" +"+jump" "ugrás / úszás" +"+crouch" "guggolás / süllyedés" +"+hook" "kézi kampó / rakéta puttony" +"" "" +"" "Tüzelés" +"+fire" "Elsődleges" +"+fire2" "Másodlagos" +"" "" +"" "Fegyverváltás" +"weapprev" "előző" +"weapnext" "következő" +"weaplast" "előzőleg használt" +"weapbest" "legjobb" +"reload" "újratöltés" +"weapon_group_1" "Lézer" +"weapon_group_2" "Vadászpuska" +"weapon_group_3" "Géppuska" +"weapon_group_4" "Mortar / Aknavető" +"weapon_group_5" "Electro" +"weapon_group_6" "Crylink / HLAC" +"weapon_group_7" "Nex / MinstaNex / Puska" +"weapon_group_8" "Hagar / Seeker" +"weapon_group_9" "Rakétavető / Tűzlabda" +"weapon_group_0" "Port-O-Launch / Kampó" +"" "" +"" "Nézet" +"+zoom" "nagyítás tartás" +"togglezoom" "nagyítás váltás" +"+showscores" "pontszámok" +"screenshot" "kép mentés" +"" "" +"" "Kommunikáció" +"messagemode" "nyilvános beszélgetés" +"messagemode2" "csapat beszélgetés" +"+con_chat_maximize" "beszélgetés történet" +"vyes" "IGEN szavazat" +"vno" "NEM szavazat" +"ready" "kész" +"" "" +"" "Kliens" +"+show_info" "kiszolgáló info" +"toggleconsole" "konzolba lépés" +"disconnect" "lekapcsolodás" +"quit" "kilépés" +"" "" +"" "Csapatjáték" +"messagemode2" "csapat beszélgetés" +"team_auto" "automatikus csapatválasztás" +"menu_showteamselect" "csapat menü" +"spec" "belépés néző módba" +"dropweapon" "fegyver eldobás" +"+use" "kulcs / zászló eldobás" +"" "" +"" "Felhasználói hozzárendelések" +"+userbind 1" "$userbind1" +"+userbind 2" "$userbind2" +"+userbind 3" "$userbind3" +"+userbind 4" "$userbind4" +"+userbind 5" "$userbind5" +"+userbind 6" "$userbind6" +"+userbind 7" "$userbind7" +"+userbind 8" "$userbind8" +"+userbind 9" "$userbind9" +"+userbind 10" "$userbind10" +"+userbind 11" "$userbind11" +"+userbind 12" "$userbind12" +"+userbind 13" "$userbind13" +"+userbind 14" "$userbind14" +"+userbind 15" "$userbind15" +"+userbind 16" "$userbind16" +"+userbind 17" "$userbind17" +"+userbind 18" "$userbind18" +"+userbind 19" "$userbind19" +"+userbind 20" "$userbind20" +"+userbind 21" "$userbind21" +"+userbind 22" "$userbind22" +"+userbind 23" "$userbind23" +"+userbind 24" "$userbind24" +"+userbind 25" "$userbind25" +"+userbind 26" "$userbind26" +"+userbind 27" "$userbind27" +"+userbind 28" "$userbind28" +"+userbind 29" "$userbind29" +"+userbind 30" "$userbind30" +"+userbind 31" "$userbind31" +"+userbind 32" "$userbind32" diff --git a/keybinds.txt.it b/keybinds.txt.it new file mode 100644 index 0000000000..82baa6e536 --- /dev/null +++ b/keybinds.txt.it @@ -0,0 +1,91 @@ +"" "Movimento" +"+forward" "avanti" +"+back" "indietro" +"+moveleft" "a sinistra" +"+moveright" "a destra" +"+jump" "salta / nuota" +"+crouch" "accovacciarsi / abbassarsi" +"+hook" "uncino / jet pack" +"" "" +"" "Attacco" +"+fire" "fuoco primario" +"+fire2" "fuoco secondario" +"" "" +"" "Cambio d'arma" +"weapprev" "arma precedente" +"weapnext" "arma successiva" +"weaplast" "ultima arma usata" +"weapbest" "miglior arma" +"reload" "ricarica" +"impulse 1" "Laser" +"impulse 2" "Shotgun" +"impulse 3" "Machine Gun" +"impulse 4" "Mortar / Mine Layer" +"impulse 5" "Electro" +"impulse 6" "Crylink / HLAC" +"impulse 7" "Nex / MinstaNex / Fucile" +"impulse 8" "Hagar / Seeker" +"impulse 9" "Rocket Launcher / Fireball" +"impulse 14" "Port-O-Launch / Hook" +"" "" +"" "Vista" +"+zoom" "tieni zoom" +"togglezoom" "attiva/disattiva zoom" +"+showscores" "mostra punteggio" +"screenshot" "cattura schermata" +"" "" +"" "Comunicazione" +"messagemode" "chat pubblica" +"messagemode2" "chat di squadra" +"+con_chat_maximize" "mostra storia chat" +"vyes" "vota SÌ" +"vno" "vota NO" +"ready" "pronto" +"" "" +"" "Client" +"+show_info" "info del server" +"toggleconsole" "apri console" +"disconnect" "disconnetti" +"quit" "esci" +"" "" +"" "Teamplay" +"messagemode2" "chat di squadra" +"team_auto" "auto-unisciti ad una squadra" +"menu_showteamselect" "selezione della squadra" +"spec" "entra in modalità spettatore" +"dropweapon" "rilascia arma" +"+use" "rilascia chiave / rilascia bandiera" +"" "" +"" "Definiti dall'utente" +"+userbind 1" "$userbind1" +"+userbind 2" "$userbind2" +"+userbind 3" "$userbind3" +"+userbind 4" "$userbind4" +"+userbind 5" "$userbind5" +"+userbind 6" "$userbind6" +"+userbind 7" "$userbind7" +"+userbind 8" "$userbind8" +"+userbind 9" "$userbind9" +"+userbind 10" "$userbind10" +"+userbind 11" "$userbind11" +"+userbind 12" "$userbind12" +"+userbind 13" "$userbind13" +"+userbind 14" "$userbind14" +"+userbind 15" "$userbind15" +"+userbind 16" "$userbind16" +"+userbind 17" "$userbind17" +"+userbind 18" "$userbind18" +"+userbind 19" "$userbind19" +"+userbind 20" "$userbind20" +"+userbind 21" "$userbind21" +"+userbind 22" "$userbind22" +"+userbind 23" "$userbind23" +"+userbind 24" "$userbind24" +"+userbind 25" "$userbind25" +"+userbind 26" "$userbind26" +"+userbind 27" "$userbind27" +"+userbind 28" "$userbind28" +"+userbind 29" "$userbind29" +"+userbind 30" "$userbind30" +"+userbind 31" "$userbind31" +"+userbind 32" "$userbind32" diff --git a/keybinds.txt.ru b/keybinds.txt.ru new file mode 100644 index 0000000000..ed46d02f17 --- /dev/null +++ b/keybinds.txt.ru @@ -0,0 +1,91 @@ +"" "Движение" +"+forward" "вперёд" +"+back" "назад" +"+moveleft" "влево" +"+moveright" "вправо" +"+jump" "прыжок / плыть" +"+crouch" "пригнуться / погрузиться" +"+hook" "крюк / реактивный ранец" +"" "" +"" "Нападение" +"+fire" "основной огонь" +"+fire2" "дополнительный огонь" +"" "" +"" "Переключение оружия" +"weapprev" "предыдущее" +"weapnext" "следующее" +"weaplast" "ранее использованное" +"weapbest" "лучшее" +"reload" "перезарядить" +"impulse 1" "Laser" +"impulse 2" "Shotgun" +"impulse 3" "Machine Gun" +"impulse 4" "Mortar / Mine Layer" +"impulse 5" "Electro" +"impulse 6" "Crylink / HLAC" +"impulse 7" "Nex / MinstaNex / Rifle" +"impulse 8" "Hagar / Seeker" +"impulse 9" "Rocket Launcher / Fireball" +"impulse 14" "Port-O-Launch / Hook" +"" "" +"" "Вид" +"+zoom" "увеличение" +"togglezoom" "переключить увеличение" +"+showscores" "показать очки" +"screenshot" "снимок экрана" +"" "" +"" "Общение" +"messagemode" "общий чат" +"messagemode2" "чат команды" +"+con_chat_maximize" "показать историю чата" +"vyes" "голосовать ДА" +"vno" "голосовать НЕТ" +"ready" "готовность" +"" "" +"" "Клиент" +"+show_info" "сведения о сервере" +"toggleconsole" "открыть консоль" +"disconnect" "отключиться" +"quit" "выйти" +"" "" +"" "Командная игра" +"messagemode2" "чат команды" +"team_auto" "авто-выбор команды" +"menu_showteamselect" "меню команды" +"spec" "стать наблюдателем" +"dropweapon" "бросить оружие" +"+use" "бросить ключ или флаг" +"" "" +"" "Определенно пользователем" +"+userbind 1" "$userbind1" +"+userbind 2" "$userbind2" +"+userbind 3" "$userbind3" +"+userbind 4" "$userbind4" +"+userbind 5" "$userbind5" +"+userbind 6" "$userbind6" +"+userbind 7" "$userbind7" +"+userbind 8" "$userbind8" +"+userbind 9" "$userbind9" +"+userbind 10" "$userbind10" +"+userbind 11" "$userbind11" +"+userbind 12" "$userbind12" +"+userbind 13" "$userbind13" +"+userbind 14" "$userbind14" +"+userbind 15" "$userbind15" +"+userbind 16" "$userbind16" +"+userbind 17" "$userbind17" +"+userbind 18" "$userbind18" +"+userbind 19" "$userbind19" +"+userbind 20" "$userbind20" +"+userbind 21" "$userbind21" +"+userbind 22" "$userbind22" +"+userbind 23" "$userbind23" +"+userbind 24" "$userbind24" +"+userbind 25" "$userbind25" +"+userbind 26" "$userbind26" +"+userbind 27" "$userbind27" +"+userbind 28" "$userbind28" +"+userbind 29" "$userbind29" +"+userbind 30" "$userbind30" +"+userbind 31" "$userbind31" +"+userbind 32" "$userbind32" diff --git a/keybinds.txt.uk b/keybinds.txt.uk new file mode 100644 index 0000000000..2772c16bd1 --- /dev/null +++ b/keybinds.txt.uk @@ -0,0 +1,91 @@ +"" "Рух" +"+forward" "вперед" +"+back" "назад" +"+moveleft" "крок ліворуч" +"+moveright" "крок праворуч" +"+jump" "стрибок / плисти нагору" +"+crouch" "присідання / занурення" +"+hook" "гак / реактивний ранець" +"" "" +"" "Бій" +"+fire" "основний вогонь" +"+fire2" "альтернативний вогонь" +"" "" +"" "Вибір зброї" +"weapprev" "попередня" +"weapnext" "наступна" +"weaplast" "використана раніше" +"weapbest" "найкраща" +"reload" "перезарядити" +"weapon_group_1" "Лазер" +"weapon_group_2" "Рушниця" +"weapon_group_3" "Автомат" +"weapon_group_4" "Мортира / Міноукладчик" +"weapon_group_5" "Електро" +"weapon_group_6" "Крайлінк / ВЛШГ" +"weapon_group_7" "Некс / МінстаНекс / Гвинтівка" +"weapon_group_8" "Хейгар / Шукач" +"weapon_group_9" "Ракетна гармата / Метеор" +"weapon_group_0" "Портал-О-Пуск / Гак" +"" "" +"" "Вид" +"+zoom" "утримувати для зуму" +"togglezoom" "увімк / вимк зум" +"+showscores" "показати рахунок" +"screenshot" "скриншот" +"" "" +"" "Спілкування" +"messagemode" "публічний чат" +"messagemode2" "командний чат" +"+con_chat_maximize" "показувати історію чату" +"vyes" "проголосувати ТАК" +"vno" "проголосувати НІ" +"ready" "готовий" +"" "" +"" "Клієнт" +"+show_info" "відомості про сервер" +"toggleconsole" "увійти в консоль" +"disconnect" "роз'єднатися" +"quit" "вийти" +"" "" +"" "Командна гра" +"messagemode2" "командний чат" +"team_auto" "автовибір команди" +"menu_showteamselect" "командне меню" +"spec" "увійти в режим спостерігача" +"dropweapon" "викинути зброю" +"+use" "викинути ключ / прапор" +"" "" +"" "Визначені користувачем" +"+userbind 1" "$userbind1" +"+userbind 2" "$userbind2" +"+userbind 3" "$userbind3" +"+userbind 4" "$userbind4" +"+userbind 5" "$userbind5" +"+userbind 6" "$userbind6" +"+userbind 7" "$userbind7" +"+userbind 8" "$userbind8" +"+userbind 9" "$userbind9" +"+userbind 10" "$userbind10" +"+userbind 11" "$userbind11" +"+userbind 12" "$userbind12" +"+userbind 13" "$userbind13" +"+userbind 14" "$userbind14" +"+userbind 15" "$userbind15" +"+userbind 16" "$userbind16" +"+userbind 17" "$userbind17" +"+userbind 18" "$userbind18" +"+userbind 19" "$userbind19" +"+userbind 20" "$userbind20" +"+userbind 21" "$userbind21" +"+userbind 22" "$userbind22" +"+userbind 23" "$userbind23" +"+userbind 24" "$userbind24" +"+userbind 25" "$userbind25" +"+userbind 26" "$userbind26" +"+userbind 27" "$userbind27" +"+userbind 28" "$userbind28" +"+userbind 29" "$userbind29" +"+userbind 30" "$userbind30" +"+userbind 31" "$userbind31" +"+userbind 32" "$userbind32" diff --git a/languages.txt b/languages.txt new file mode 100644 index 0000000000..0551db8783 --- /dev/null +++ b/languages.txt @@ -0,0 +1,13 @@ +de German "Deutsch" +el Greek "Ελληνική" +en English "English" +es Spanish "Español" +fr French "Français" +it Italian "Italiano" +hu Hungarian "Magyar" +nl Dutch "Nederlands" +pt Portuguese "Português" +ro Romanian "Romana" +ru Russian "Русский" +fi Finnish "Suomi" +uk Ukrainian "Українська" diff --git a/menu.dat.de.po b/menu.dat.de.po new file mode 100644 index 0000000000..9951f0cab3 --- /dev/null +++ b/menu.dat.de.po @@ -0,0 +1,2983 @@ +# Xonotic CSQC +# Copyright (C) 2011 Team Xonotic +# This file is distributed under the same license as the Xonotic package. +# Rudolf Polzer , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: 0.1preview\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-12-25 22:57+0100\n" +"PO-Revision-Date: 2011-04-20 10:46+0200\n" +"Last-Translator: Rudolf Polzer \n" +"Language-Team: Rudolf Polzer \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: qcsrc/common/mapinfo.qc:1097 qcsrc/menu/xonotic/skinlist.c:163 +#, c-format +msgid "%s: %s" +msgstr "%s: %s" + +#: qcsrc/menu/gamecommand.qc:47 +#, c-format +msgid "error: status is %d\n" +msgstr "Fehler: Status ist %d\n" + +#: qcsrc/menu/gamecommand.qc:70 +msgid "Usage: menu_cmd command..., where possible commands are:\n" +msgstr "Syntax: menu_cmd Befehl..., wobei mögliche Befehle sind:\n" + +#: qcsrc/menu/gamecommand.qc:71 +msgid " sync - reloads all cvars on the current menu page\n" +msgstr " sync - lädt alle Variablen auf der aktuellen Menüseite neu\n" + +#: qcsrc/menu/gamecommand.qc:72 +msgid " directmenu ITEM - select a menu item as main item\n" +msgstr " directmenu ELEMENT - springt zu einem Menüelement" + +#: qcsrc/menu/gamecommand.qc:185 +msgid "error creating curl handle\n" +msgstr "Fehler beim Erstellen eines curl-Handles\n" + +#: qcsrc/menu/gamecommand.qc:192 +msgid "Invalid command. For a list of supported commands, try menu_cmd help.\n" +msgstr "" +"Ungültiger Befehl. Eine Liste der unterstützten Befehle wird von menu_cmd " +"help ausgegeben.\n" + +#: qcsrc/menu/item/gecko.c:49 +msgid "Browser not initialized!" +msgstr "Browser nicht initialisiert!" + +#: qcsrc/menu/item/label.c:63 +#, c-format +msgid "NOTE: label text %s too wide for label, condensed by factor %f\n" +msgstr "" +"HINWEIS: Text %s ist zu weit für das Textfeld, Text wurde um Faktor %f " +"gestaucht\n" + +#: qcsrc/menu/item/listbox.c:300 +#, c-format +msgid "Item %d" +msgstr "Eintrag %d" + +#: qcsrc/menu/item/slider.c:64 +#, c-format +msgid "%d (%s)" +msgstr "%d (%s)" + +#: qcsrc/menu/item/textslider.c:29 qcsrc/menu/item/textslider.c:31 +msgid "custom" +msgstr "benutzerdefiniert" + +#: qcsrc/menu/menu.qc:37 +#, c-format +msgid "^4MQC Build information: ^1%s\n" +msgstr "^4MQC Build-Information: ^1%s (deutsch)\n" + +#: qcsrc/menu/xonotic/campaign.c:284 +#: qcsrc/menu/xonotic/dialog_singleplayer.c:123 +msgid "???" +msgstr "???" + +#: qcsrc/menu/xonotic/campaign.c:285 +#, c-format +msgid "Level %d: %s" +msgstr "Level %d: %s" + +#: qcsrc/menu/xonotic/cvarlist.c:85 +msgid "will be saved to config.cfg" +msgstr "wird in config.cfg gespeichert" + +#: qcsrc/menu/xonotic/cvarlist.c:87 +msgid "will not be saved" +msgstr "wird nicht gespeichert" + +#: qcsrc/menu/xonotic/cvarlist.c:89 +msgid "private" +msgstr "privat" + +#: qcsrc/menu/xonotic/cvarlist.c:91 +msgid "engine setting" +msgstr "Engine-Einstellung" + +#: qcsrc/menu/xonotic/cvarlist.c:93 +msgid "read only" +msgstr "nur lesen" + +#: qcsrc/menu/xonotic/dialog_credits.c:5 +msgid "Credits" +msgstr "Entwickler" + +#: qcsrc/menu/xonotic/dialog_credits.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:277 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:35 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:57 +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:89 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:61 +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:21 +msgid "OK" +msgstr "OK" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:4 +msgid "Welcome" +msgstr "Willkommen" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:33 +msgid "" +"Welcome to Xonotic, please select your language preference and enter your " +"player name to get started. You can change these options later through the " +"menu system." +msgstr "" +"Willkommen in Xonotic! Nach Auswahl der Sprache und Eingabe des " +"Spielernamens kann es losgehen. Diese Optionen können natürlich später im " +"Menüsystem geändert werden." + +#: qcsrc/menu/xonotic/dialog_firstrun.c:38 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:35 +msgid "Text language:" +msgstr "Sprache:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:47 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:40 +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:39 +msgid "Name:" +msgstr "Name:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:69 +msgid "Save settings" +msgstr "Einstellungen speichern" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:4 +msgid "Ammo Panel" +msgstr "Munitons-Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:22 +msgid "Ammunition display:" +msgstr "Munitionsanzeige:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:25 +msgid "Show only current ammo type" +msgstr "Nur aktuellen Munitionstyp anzeigen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:28 +msgid "Align icon:" +msgstr "Icon ausrichten:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:29 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:36 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:40 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:40 +msgid "Left" +msgstr "Links" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:38 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:41 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:41 +msgid "Right" +msgstr "Rechts" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:4 +msgid "Centerprint" +msgstr "Nachrichten" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:23 +msgid "Message duration:" +msgstr "Anzeigedauer:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:27 +msgid "Fade time:" +msgstr "Ausblenden nach:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:31 +msgid "Flip messages order" +msgstr "Reihenfolge vertauschen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:33 +msgid "Text alignment:" +msgstr "Textausrichtung:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:37 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:50 +msgid "Center" +msgstr "Mittig" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:41 +msgid "Font scale:" +msgstr "Schriftgröße:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:4 +msgid "Chat Panel" +msgstr "Chat-Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:22 +msgid "Chat entries:" +msgstr "Chat-Zeilen:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:25 +msgid "Chat size:" +msgstr "Chat-Größe:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:29 +msgid "Chat lifetime:" +msgstr "Chat-Sichtbarkeit:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:33 +msgid "Chat beep sound" +msgstr "Chat-Piepton:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:4 +msgid "Engine Info Panel" +msgstr "Engine-Info-Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:22 +msgid "Engine info:" +msgstr "Engine-Info:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:25 +msgid "Use an averaging algorithm for fps" +msgstr "Zeige einen Durchschnittswert für fps" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:4 +msgid "Health/Armor Panel" +msgstr "Health/Armor-Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:22 +msgid "Enable status bar" +msgstr "Statusleiste anzeigen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:24 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:24 +msgid "Status bar alignment:" +msgstr "Statusleistenausrichtung" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:42 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:42 +msgid "Inward" +msgstr "Innen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:43 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:43 +msgid "Outward" +msgstr "Außen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:37 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:37 +msgid "Icon alignment:" +msgstr "Iconausrichtung:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:45 +msgid "Flip health and armor positions" +msgstr "Health und Armor tauschen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:4 +msgid "Info Messages Panel" +msgstr "Informations-Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:22 +msgid "Info messages:" +msgstr "Informationen:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:25 +msgid "Flip align" +msgstr "Ausrichtung tauschen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_modicons.c:4 +msgid "Mod Icons Panel" +msgstr "Mod-Symbole-Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:4 +msgid "Notification Panel" +msgstr "Anzeige-Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:22 +msgid "Notifications:" +msgstr "Anzeige:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:25 +msgid "Also print notifications to the console" +msgstr "auch auf der Konsole ausgeben" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:28 +msgid "Flip notify order" +msgstr "Scrollrichtung vertauschen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:31 +msgid "Entry lifetime:" +msgstr "Eintrags-Sichtbarkeit:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:35 +msgid "Entry fadetime:" +msgstr "Eintrags-Ausblendung:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:4 +msgid "Physics Panel" +msgstr "Physik-Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:21 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:21 +msgid "Panel disabled" +msgstr "Panel nicht anzeigen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:23 +msgid "Panel enabled" +msgstr "Panel anzeigen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:24 +msgid "Panel enabled even observing" +msgstr "Panel auch beim Zuschauen anzeigen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:25 +msgid "Panel enabled only in Race/CTS" +msgstr "Panel nur in Race und CTS anzeigen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:31 +msgid "Status bar" +msgstr "Statusleiste" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:48 +msgid "Left align" +msgstr "Links" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:34 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:52 +msgid "Right align" +msgstr "Rechts" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:35 +msgid "Inward align" +msgstr "Innen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:36 +msgid "Outward align" +msgstr "Außen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:40 +msgid "Flip speed/acceleration positions" +msgstr "Geschwindigkeit/Beschleunigung tauschen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:44 +msgid "Speed:" +msgstr "Geschwindigkeit:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:45 +msgid "Include vertical speed" +msgstr "Mit vertikaler Geschwindigkeit" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:56 +msgid "Speed unit:" +msgstr "Geschwindigkeitseinheit:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:58 +msgid "qu/s" +msgstr "qu/s" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:59 +msgid "m/s" +msgstr "m/s" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:60 +msgid "km/h" +msgstr "km/h" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:61 +msgid "mph" +msgstr "mph" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:62 +msgid "knots" +msgstr "Knoten" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:64 +msgid "Show" +msgstr "Anzeigen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:67 +msgid "Top speed" +msgstr "Geschwindigkeitsrekord:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:73 +msgid "Acceleration:" +msgstr "Beschleunigung:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:74 +msgid "Include vertical acceleration" +msgstr "Mit vertikaler Beschleunigung" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:4 +msgid "Powerups Panel" +msgstr "Bonus-Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:45 +msgid "Flip strength and shield positions" +msgstr "Strength und Shield vertauschen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:4 +msgid "Pressed Keys Panel" +msgstr "Gedrückte-Tasten-Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:22 +msgid "Panel enabled when spectating" +msgstr "Panel beim Zuschauen anzeigen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:23 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:23 +msgid "Panel always enabled" +msgstr "Panel immer anzeigen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:30 +msgid "Forced aspect:" +msgstr "Aspektverhältnis:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_racetimer.c:4 +msgid "Race Timer Panel" +msgstr "Rundenzeit-Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:4 +msgid "Radar Panel" +msgstr "Radar-Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:22 +msgid "Panel enabled in teamgames" +msgstr "Panel in Team-Spieltypen aktivieren" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:29 +msgid "Radar:" +msgstr "Radar:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:32 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:43 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:156 +#: qcsrc/menu/xonotic/util.qc:623 +msgid "Alpha:" +msgstr "Alpha:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:36 +msgid "Rotation:" +msgstr "Drehung:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:38 +msgid "Forward" +msgstr "Vorwärts" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:39 +msgid "West" +msgstr "West" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:40 +msgid "South" +msgstr "Süd" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:41 +msgid "East" +msgstr "Ost" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:42 +msgid "North" +msgstr "Nord" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:46 +msgid "Scale:" +msgstr "Skalierung:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:50 +msgid "Zoom mode:" +msgstr "Zoom-Modus:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:52 +msgid "Zoomed in" +msgstr "vergrößert" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:53 +msgid "Zoomed out" +msgstr "verkleinert" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:54 +msgid "Always zoomed" +msgstr "immer vergrößert" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:55 +msgid "Never zoomed" +msgstr "nie vergrößert" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:4 +msgid "Score Panel" +msgstr "Punkte-Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:22 +msgid "Score:" +msgstr "Punkte:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:25 +msgid "Rankings:" +msgstr "Platzierungen:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:26 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:60 +msgid "Off" +msgstr "Aus" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:27 +msgid "And me" +msgstr "Auch für mich" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:28 +msgid "Pure" +msgstr "Rein" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:4 +msgid "Timer Panel" +msgstr "Zeit-Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:22 +msgid "Timer:" +msgstr "Zeit:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:25 +msgid "Show elapsed time" +msgstr "Vergangene Zeit anzeigen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:4 +msgid "Vote Panel" +msgstr "Abstimmungs-Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:22 +msgid "Alpha after voting:" +msgstr "Alpha nach Abstimmung:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:4 +msgid "Weapons Panel" +msgstr "Waffen-Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:24 +msgid "Fade out after:" +msgstr "Ausblenden nach:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:26 +msgid "Never" +msgstr "Nie" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:28 +#, c-format +msgid "%ds" +msgstr "%ds" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:32 +msgid "Fade effect:" +msgstr "Ausblendeeffekt:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:35 +msgid "EF^None" +msgstr "keiner" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:36 +msgid "Slide" +msgstr "Schieben" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:37 +msgid "Alpha" +msgstr "Alpha" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:38 +msgid "EF^Both" +msgstr "beide" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:42 +msgid "Weapon icons:" +msgstr "Waffensymbole:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:45 +msgid "Show only owned weapons" +msgstr "Nur vorhandene Waffen zeigen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:48 +msgid "Show weapon ID as:" +msgstr "Waffen-ID zeigen als:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:49 +msgid "SHOWAS^None" +msgstr "nichts" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:50 +msgid "Number" +msgstr "Zahl" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:51 +msgid "Bind" +msgstr "Taste" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:54 +msgid "Show Accuracy" +msgstr "Trefferquote zeigen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:55 +msgid "Show Ammo" +msgstr "Munition zeigen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:58 +msgid "Ammo bar color:" +msgstr "Muntionsleistenfarbe:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:64 +msgid "Ammo bar alpha:" +msgstr "Munitionsleistenalpha:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:4 +msgid "Panel HUD Setup" +msgstr "HUD-Konfiguration" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:21 +msgid "Panel background defaults:" +msgstr "Panel-Standardhintergrund:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:23 qcsrc/menu/xonotic/util.qc:598 +msgid "Background:" +msgstr "Hintergrund:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:25 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:37 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:52 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:91 qcsrc/menu/xonotic/util.qc:601 +#: qcsrc/menu/xonotic/util.qc:617 qcsrc/menu/xonotic/util.qc:634 +msgid "Disable" +msgstr "Aus" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:30 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:77 qcsrc/menu/xonotic/util.qc:606 +msgid "Color:" +msgstr "Farbe:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:35 qcsrc/menu/xonotic/util.qc:614 +msgid "Border size:" +msgstr "Rahmengröße:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:50 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:89 +msgid "Team color:" +msgstr "Teamfarbe:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:58 qcsrc/menu/xonotic/util.qc:640 +msgid "Test team color in configure mode" +msgstr "Teamfarbe bei Konfiguration testen" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:61 qcsrc/menu/xonotic/util.qc:643 +msgid "Padding:" +msgstr "Abstand:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:68 +msgid "HUD Dock:" +msgstr "HUD-Dock:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:70 +msgid "DOCK^Disabled" +msgstr "Aus" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:71 +msgid "DOCK^Small" +msgstr "Klein" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:72 +msgid "DOCK^Medium" +msgstr "Mittel" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:73 +msgid "DOCK^Large" +msgstr "Groß" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:96 +msgid "Grid settings:" +msgstr "Gitter:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:99 +msgid "Snap panels to grid" +msgstr "Panels am Gitter ausrichten" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:102 +msgid "Grid size:" +msgstr "Gitterweite:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:103 +msgid "X:" +msgstr "X:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:109 +msgid "Y:" +msgstr "Y:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:117 +msgid "Exit setup" +msgstr "Verlassen" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:4 +msgid "Multiplayer" +msgstr "Mehrspieler" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:18 +msgid "Servers" +msgstr "Server" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:19 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:5 +msgid "Create" +msgstr "Starten" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:20 +msgid "Demos" +msgstr "Demos" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:5 +msgid "Player Setup" +msgstr "Spieler-Einstellungen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:34 +msgid "Game type:" +msgstr "Spieltyp" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:46 +msgid "Match settings:" +msgstr "Spieleinstellungen:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:49 +msgid "Time limit:" +msgstr "Zeitlimit:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:53 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:61 +msgid "Use map specified default" +msgstr "Standardwert der Map verwenden" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:56 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:155 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:156 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:157 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:161 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:162 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:163 +msgid "Point limit:" +msgstr "Punktelimit" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:64 +msgid "Player slots:" +msgstr "Spielerplätze:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:67 +msgid "Number of bots:" +msgstr "Anzahl Bots:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:71 +msgid "Bot skill:" +msgstr "Spielstärke:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:74 +msgid "Botlike" +msgstr "Bots halt" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:75 +msgid "Beginner" +msgstr "Anfänger" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:76 +msgid "You will win" +msgstr "Gewinnst schon" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:77 +msgid "You can win" +msgstr "Kannst gewinnen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:78 +msgid "You might win" +msgstr "Könntest gewinnen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:79 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:62 +msgid "Advanced" +msgstr "Fortgeschritten" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:80 +msgid "Expert" +msgstr "Experte" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:81 +msgid "Pro" +msgstr "Profi" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:82 +msgid "Assassin" +msgstr "Mörder" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:83 +msgid "Unhuman" +msgstr "Übermenschlich" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:84 +msgid "Godlike" +msgstr "Gottgleich" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:88 +msgid "Mutators..." +msgstr "Mutators..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:97 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:68 +msgid "Advanced settings..." +msgstr "Erweiterte Einstellungen..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:104 +msgid "Map list:" +msgstr "Mapliste:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:110 +msgid "Select all" +msgstr "Alle auswählen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:113 +msgid "Select none" +msgstr "Keine auswählen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:119 +msgid "Start Multiplayer!" +msgstr "Starten!" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:154 +msgid "Capture limit:" +msgstr "Capture-Limit:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:158 +msgid "Lives:" +msgstr "Leben:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:159 +msgid "Laps:" +msgstr "Runden:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:160 +msgid "Goals:" +msgstr "Tore:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:164 +msgid "Frag limit:" +msgstr "Punktelimit:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:6 +msgid "Advanced server settings" +msgstr "Erweiterte Servereinstellungen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:25 +msgid "Game settings:" +msgstr "Spieleinstellungen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:28 +msgid "Allow spectating" +msgstr "Zuschauer erlauben" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:31 +msgid "Spawn shield:" +msgstr "Startschutz:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:36 +msgid "Game speed:" +msgstr "Spieltempo:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:40 +msgid "Teamplay settings:" +msgstr "Teamplay-Einstellungen:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:43 +msgid "Friendly fire scale:" +msgstr "Eigenbeschuss-Faktor:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:47 +msgid "Virtual friendly fire (effect only)" +msgstr "Virtueller Eigenbeschuss (nur Effekt)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:50 +msgid "Friendly fire penalty:" +msgstr "Strafe für Eigenbeschuss:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:54 +msgid "Virtual penalty (effect only)" +msgstr "Virtuelle Strafe (nur Effekt)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:57 +msgid "Teams:" +msgstr "Teams:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:66 +msgid "Map voting:" +msgstr "Map-Abstimmung:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:68 +msgid "No voting" +msgstr "Keine Abstimmung" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:69 +msgid "2 choices" +msgstr "2 Optionen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:70 +msgid "3 choices" +msgstr "3 Optionen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:71 +msgid "4 choices" +msgstr "4 Optionen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:72 +msgid "5 choices" +msgstr "5 Optionen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:73 +msgid "6 choices" +msgstr "6 Optionen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:74 +msgid "7 choices" +msgstr "7 Optionen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:75 +msgid "8 choices" +msgstr "8 Optionen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:76 +msgid "9 choices" +msgstr "9 Optionen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:79 +msgid "Simple majority wins vcall" +msgstr "Einfache Mehrheit gewinnt vcall" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:5 +msgid "Map Information" +msgstr "Map-Information" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "Full item placement" +msgstr "mit Waffen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "MinstaGib only" +msgstr "nur MinstaGib" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:78 +msgid "Title:" +msgstr "Titel:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:84 +msgid "Author:" +msgstr "Autor:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:90 +msgid "Features:" +msgstr "Features:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:95 +msgid "Game types:" +msgstr "Spieltyp:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:118 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:317 +msgid "Close" +msgstr "Schließen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:121 +msgid "MAP^Play" +msgstr "Start" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:7 +msgid "Mutators" +msgstr "Mutators" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:33 +msgid "All Weapons Arena" +msgstr "Alle-Waffen-Arena" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:35 +msgid "Most Weapons Arena" +msgstr "Viele-Waffen-Arena" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:56 +#, c-format +msgid "%s Arena" +msgstr "%s-Arena" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:68 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:173 +msgid "Dodging" +msgstr "Ausweichen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:70 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:258 +msgid "MinstaGib" +msgstr "MinstaGib" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:261 +msgid "NIX" +msgstr "NIX" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:74 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:213 +msgid "Rocket Flying" +msgstr "Raketen-Fliegen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:76 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:210 +msgid "Invincible Projectiles" +msgstr "Unzerstörbare Schüsse" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:80 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:272 +msgid "No start weapons" +msgstr "Ohne Waffen starten" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:195 +msgid "Low gravity" +msgstr "Wenig Schwerkraft" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:84 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:176 +msgid "Cloaked" +msgstr "Tarnung" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:86 +msgid "Hook" +msgstr "Enterhaken" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:88 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:179 +msgid "Midair" +msgstr "in der Luft" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:90 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:182 +msgid "Vampire" +msgstr "Vampir" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:92 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:216 +msgid "Piñata" +msgstr "Piñata" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:94 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:219 +msgid "Weapons stay" +msgstr "Waffen bleiben" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:96 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:186 +msgid "Blood loss" +msgstr "Blutverlust" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:98 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:207 +msgid "Jet pack" +msgstr "Jetpack" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:100 +msgid "No powerups" +msgstr "Keine Boni" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:102 +msgid "Powerups" +msgstr "Boni" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:104 +msgid "MUT^None" +msgstr "keiner" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:170 +msgid "Gameplay mutators:" +msgstr "Spielmechanik-Mutators:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:201 +msgid "Weapon & item mutators:" +msgstr "Waffen/Gegenstände-Mutators:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:204 +msgid "Grappling hook" +msgstr "Enterhaken" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:223 +msgid "Weapon arenas:" +msgstr "Waffen-Arenen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:226 +msgid "Regular (no arena)" +msgstr "Normal (keine Arena)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:247 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:264 +msgid "with laser" +msgstr "mit Laser" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:255 +msgid "Special arenas:" +msgstr "Spezielle Arenen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:268 +msgid "Most weapons" +msgstr "Viele Waffen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:4 +msgid "Demo" +msgstr "Demo" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:28 +msgid "Record demos while playing" +msgstr "Demo beim Spielen aufnehmen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:32 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:28 +msgid "Filter:" +msgstr "Filter:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:29 +#: qcsrc/menu/xonotic/dialog_settings_input.c:41 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:24 +msgid "Clear" +msgstr "Löschen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:43 +msgid "Timedemo" +msgstr "Timedemo" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:46 +msgid "DEMO^Play" +msgstr "Abspielen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:4 +msgid "Join" +msgstr "Verbinden" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:36 +msgid "SRVS^Empty" +msgstr "leer" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:40 +msgid "SRVS^Full" +msgstr "voll" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:44 +msgid "Pause" +msgstr "Pause" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:56 +msgid "Address:" +msgstr "Adresse:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:67 +msgid "Info..." +msgstr "Info..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:320 +msgid "Join!" +msgstr "Verbinden!" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:5 +msgid "Server Information" +msgstr "Server-Information" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:115 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:116 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:186 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:192 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:202 +msgid "N/A" +msgstr "-" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:161 +#, c-format +msgid "%d/%d, %d free player slots" +msgstr "%d/%d, %d freie Slots" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:175 +#, c-format +msgid "%d modified settings" +msgstr "%d veränderte Einstellungen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:175 +msgid "Official settings" +msgstr "Offizielle Einstellungen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:200 +msgid "N/A (can't connect)" +msgstr "- (nicht kompatibel)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:208 +msgid "not supported (can't connect)" +msgstr "nicht unterstützt (nicht kompatibel)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:210 +msgid "not supported (won't encrypt)" +msgstr "nicht untersützt (nicht aktiv)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:214 +msgid "supported (will encrypt)" +msgstr "unterstützt (aktiv)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:216 +msgid "supported (won't encrypt)" +msgstr "unterstützt (nicht aktiv)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:220 +msgid "requested (will encrypt)" +msgstr "erwünscht (aktiv)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:222 +msgid "requested (won't encrypt)" +msgstr "erwünscht (nicht aktiv)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:226 +msgid "required (can't connect)" +msgstr "notwendig (nicht kompatibel)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:228 +msgid "required (will encrypt)" +msgstr "notwendig (aktiv)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:249 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:272 +msgid "Players:" +msgstr "Spieler:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:257 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:38 +msgid "Type:" +msgstr "Typ:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:262 +msgid "Map:" +msgstr "Map:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:267 +msgid "Gameplay:" +msgstr "Spielregeln:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:277 +msgid "Bots:" +msgstr "Bots:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:282 +msgid "Mod:" +msgstr "Mod:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:287 +msgid "Version:" +msgstr "Version:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:292 +msgid "Ping:" +msgstr "Ping:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:298 +msgid "CA:" +msgstr "CA:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:304 +msgid "Key:" +msgstr "Schlüssel:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:310 +msgid "Encryption:" +msgstr "Krypto:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:63 +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:19 +msgid "Model:" +msgstr "Modell:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:87 +msgid "Force player models to mine" +msgstr "Alle Spieler als mein Modell zeigen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:90 +msgid "Field of view:" +msgstr "Sichtfeld:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:94 +msgid "View bobbing:" +msgstr "Sicht-Wackeln:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:98 +msgid "Zoom factor:" +msgstr "Vergrößerungsfaktor:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:102 +msgid "Zoom speed:" +msgstr "Vergrößerungsgeschwindigkeit:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:105 +msgid "Weapon settings..." +msgstr "Waffeneinstellungen..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:112 +msgid "Crosshair:" +msgstr "Fadenkreuz:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:113 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:141 +msgid "Per weapon" +msgstr "pro Waffe" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:132 +msgid "Crosshair size:" +msgstr "Größe:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:136 +msgid "Crosshair alpha:" +msgstr "Alpha:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:140 +msgid "Crosshair color:" +msgstr "Farbe:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:142 +msgid "By health" +msgstr "je nach Health" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:145 +msgid "Custom" +msgstr "benutzerdefiniert" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:150 +msgid "Enable center dot" +msgstr "Punkt in der Mitte aktivieren" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:153 +msgid "Size:" +msgstr "Größe:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:160 +msgid "Hit test:" +msgstr "Treffer-Test:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:161 +msgid "HTST^None" +msgstr "Aus" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:162 +msgid "TrueAim" +msgstr "TrueAim" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:163 +msgid "Enemies" +msgstr "Gegner" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:166 +msgid "Waypoints setup..." +msgstr "Wegpunkt-Einstellungen..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:171 +msgid "Enter HUD editor" +msgstr "HUD-Editor starten" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:176 +msgid "Force models:" +msgstr "Modell erzwingen:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:177 +msgid "MDL^None" +msgstr "keine" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:178 +msgid "MDL^Custom" +msgstr "inoffizielle" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:179 +msgid "MDL^All" +msgstr "alle" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:182 +msgid "Disable gore effects" +msgstr "Gewalteffekte deaktivieren" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:184 +msgid "Gibs:" +msgstr "Fleischteile:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:186 +msgid "GIBS^None" +msgstr "Aus" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:187 +msgid "GIBS^Few" +msgstr "Wenige" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:188 +msgid "GIBS^Many" +msgstr "Einige" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:189 +msgid "GIBS^Lots" +msgstr "Viele" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:193 +msgid "Damage splash:" +msgstr "Schadenseffekt:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:197 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:175 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:195 +#: qcsrc/menu/xonotic/dialog_settings_input.c:74 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:30 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:41 +#: qcsrc/menu/xonotic/dialog_settings_video.c:105 +msgid "Apply immediately" +msgstr "Sofort anwenden" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:5 +msgid "Waypoints" +msgstr "Wegpunkte" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:23 +msgid "Show base waypoints" +msgstr "Basis-Wegpunkte anzeigen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:25 +msgid "Waypoint scale:" +msgstr "Wegpunkt-Skalierung:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:29 +msgid "Waypoint alpha:" +msgstr "Wegpunkt-Alpha:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:33 +msgid "Show names above players" +msgstr "Namen über Spielern anzeigen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:6 +msgid "Weapon settings" +msgstr "Waffeneinstellungen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:29 +msgid "Weapon priority list:" +msgstr "Waffenreihenfolge" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:34 +msgid "Up" +msgstr "Hoch" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:37 +msgid "Down" +msgstr "Runter" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:41 +msgid "Use priority list for weapon cycling" +msgstr "Waffenreihenfolge für Mausrad verwenden" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:43 +msgid "Auto switch weapons on pickup" +msgstr "Automatisch auf beste Waffe wechseln" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:45 +msgid "Draw 1st person weapon model" +msgstr "Waffe in 3D anzeigen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:55 +msgid "Flip view horizontally" +msgstr "3D-Ansicht spiegeln" + +#: qcsrc/menu/xonotic/dialog_news.c:4 +msgid "News" +msgstr "Nachrichten" + +#: qcsrc/menu/xonotic/dialog_news.c:18 +msgid "http://www.xonotic.org/team/blog/" +msgstr "http://www.xonotic.org/team/blog/" + +#: qcsrc/menu/xonotic/dialog_quit.c:4 +msgid "Quit" +msgstr "Beenden" + +#: qcsrc/menu/xonotic/dialog_quit.c:17 +msgid "Are you sure you want to quit?" +msgstr "Willst du das Spiel wirklich beenden?" + +#: qcsrc/menu/xonotic/dialog_quit.c:20 +msgid "Yes" +msgstr "Ja" + +#: qcsrc/menu/xonotic/dialog_quit.c:21 +msgid "No" +msgstr "Nein" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:4 +msgid "Sandbox Tools" +msgstr "Sandbox-Tools" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:24 +msgid "Spawn" +msgstr "Neu" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:25 +msgid "Remove *" +msgstr "Entfernen *" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:27 +msgid "Copy *" +msgstr "Kopieren *" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:28 +msgid "Paste" +msgstr "Einfügen" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:30 +msgid "Bone:" +msgstr "Knochen:" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:35 +msgid "Set * as child" +msgstr "* als Kind festlegen" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:36 +msgid "Attach to *" +msgstr "An * anhängen" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:38 +msgid "Detach from *" +msgstr "Von * abhängen" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:41 +msgid "Visual object properties for *:" +msgstr "Visuelle Eigenschaften von *:" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:43 +msgid "Set skin:" +msgstr "Skin:" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:45 +msgid "Set alpha:" +msgstr "Alpha:" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:48 +msgid "Set color main:" +msgstr "Hauptfarbe:" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:50 +msgid "Set color glow:" +msgstr "Leuchtfarbe:" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:54 +msgid "Set frame:" +msgstr "Frame:" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:58 +msgid "Physical object properties for *:" +msgstr "Physikalische Eigenschaften von *:" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:60 +msgid "Set material:" +msgstr "Material:" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:66 +msgid "Set solidity:" +msgstr "Festigkeit:" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:67 +msgid "Non-solid" +msgstr "Gasförmig" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:68 +msgid "Solid" +msgstr "Fest" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:69 +msgid "Set physics:" +msgstr "Physik:" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:70 +msgid "Static" +msgstr "Statisch" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:71 +msgid "Movable" +msgstr "Beweglich" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:72 +msgid "Physical" +msgstr "Physik-Eigenschaften" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:74 +msgid "Set scale:" +msgstr "Größe:" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:76 +msgid "Set force:" +msgstr "Kraft:" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:80 +msgid "Claim *" +msgstr "* nehmen" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:82 +msgid "* object info" +msgstr "* Objekteigeschaften" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:83 +msgid "* mesh info" +msgstr "* Modelleigenschaften" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:84 +msgid "* attachment info" +msgstr "* Anhängerkupplung" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:85 +msgid "Show help" +msgstr "Hilfe anzeigen" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:86 +msgid "* is the object you are facing" +msgstr "* ist das Objekt vor deiner Nase" + +#: qcsrc/menu/xonotic/dialog_settings.c:4 +msgid "Settings" +msgstr "Einstellungen" + +#: qcsrc/menu/xonotic/dialog_settings.c:18 +#: qcsrc/menu/xonotic/dialog_settings_input.c:4 +msgid "Input" +msgstr "Eingabe" + +#: qcsrc/menu/xonotic/dialog_settings.c:19 +#: qcsrc/menu/xonotic/dialog_settings_video.c:4 +msgid "Video" +msgstr "Grafik" + +#: qcsrc/menu/xonotic/dialog_settings.c:20 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:4 +msgid "Effects" +msgstr "Effekte" + +#: qcsrc/menu/xonotic/dialog_settings.c:21 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:4 +msgid "Audio" +msgstr "Ton" + +#: qcsrc/menu/xonotic/dialog_settings.c:22 +#: qcsrc/menu/xonotic/dialog_settings_network.c:4 +msgid "Network" +msgstr "Netzwerk" + +#: qcsrc/menu/xonotic/dialog_settings.c:23 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:4 +msgid "Misc" +msgstr "Sonstiges" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:27 +msgid "Master:" +msgstr "Master:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:33 +msgid "Music:" +msgstr "Musik:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:41 +msgid "VOL^Ambient:" +msgstr "Umgebung:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:48 +msgid "Info:" +msgstr "Info:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:55 +msgid "Items:" +msgstr "Gegenstände:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:62 +msgid "Pain:" +msgstr "Schmerz:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:69 +msgid "Player:" +msgstr "Spieler:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:76 +msgid "Shots:" +msgstr "Schüsse:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:83 +msgid "Voice:" +msgstr "Stimme:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:91 +msgid "Weapons:" +msgstr "Waffen:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:98 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:158 +msgid "Frequency:" +msgstr "Frequenz:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:100 +msgid "8 kHz" +msgstr "8 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:101 +msgid "11.025 kHz" +msgstr "11,025 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:102 +msgid "16 kHz" +msgstr "16 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:103 +msgid "22.05 kHz" +msgstr "22,05 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:104 +msgid "24 kHz" +msgstr "24 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:105 +msgid "32 kHz" +msgstr "32 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:106 +msgid "44.1 kHz" +msgstr "44,1 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:107 +msgid "48 kHz" +msgstr "48 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:110 +msgid "Channels:" +msgstr "Kanäle" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:112 +msgid "Mono" +msgstr "Mono" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:113 +msgid "Stereo" +msgstr "Stereo" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:114 +msgid "2.1" +msgstr "2.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:115 +msgid "4" +msgstr "4" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:116 +msgid "5" +msgstr "5" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:117 +msgid "5.1" +msgstr "5.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:118 +msgid "6.1" +msgstr "6.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:119 +msgid "7.1" +msgstr "7.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:123 +msgid "Swap Stereo" +msgstr "Stereokanäle tauschen" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:127 +msgid "Headphone friendly mode" +msgstr "Kopfhörer-Modus" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:131 +msgid "New style sound attenuation" +msgstr "Neue Sound-Distanzformel" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:133 +msgid "Spatial voices:" +msgstr "Räumliche Sprachnachrichten:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:134 +msgid "VOCS^None" +msgstr "keine" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:135 +msgid "VOCS^Taunts" +msgstr "nur Spott" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:136 +msgid "VOCS^All" +msgstr "alle" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:139 +msgid "Taunt range:" +msgstr "Spott-Radius:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:142 +msgid "RNG^Very short" +msgstr "Sehr klein" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:143 +msgid "RNG^Short" +msgstr "Klein" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:144 +msgid "RNG^Normal" +msgstr "Normal" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:145 +msgid "RNG^Long" +msgstr "Groß" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:146 +msgid "RNG^Full" +msgstr "Sehr groß" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:153 +msgid "Automatic taunts" +msgstr "Automatischer Spott" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:162 +msgid "Time warning:" +msgstr "Zeitwarnung:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:164 +msgid "WRN^None" +msgstr "keine" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:165 +msgid "1 minute" +msgstr "1 Minute" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:166 +msgid "5 minutes" +msgstr "5 Minuten" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:167 +msgid "WRN^Both" +msgstr "beide" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:170 +msgid "Hit indicator" +msgstr "Treffer-Indikator" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:172 +msgid "Menu sounds" +msgstr "Menü-Sounds" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:38 +msgid "Quality preset:" +msgstr "Qualitäts-Vorgabe:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:41 +msgid "PRE^OMG!" +msgstr "OMG!" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:42 +msgid "PRE^Low" +msgstr "Niedrig" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:43 +msgid "PRE^Medium" +msgstr "Mittel" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:44 +msgid "PRE^Normal" +msgstr "Normal" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:45 +msgid "PRE^High" +msgstr "Hoch" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:46 +msgid "PRE^Ultra" +msgstr "Ultra" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:48 +msgid "PRE^Ultimate" +msgstr "Ultimativ" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:52 +msgid "Geometry detail:" +msgstr "Geometrie-Detail:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:54 +msgid "DET^Lowest" +msgstr "Sehr niedrig" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:55 +msgid "DET^Low" +msgstr "Niedrig" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:56 +msgid "DET^Normal" +msgstr "Normal" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:57 +msgid "DET^Good" +msgstr "Gut" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:58 +msgid "DET^Best" +msgstr "Sehr gut" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:59 +msgid "DET^Insane" +msgstr "Wahnsinnig" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:62 +msgid "Antialiasing:" +msgstr "Kantenglättung:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:64 +msgid "AA^Disabled" +msgstr "Aus" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:65 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:106 +msgid "2x" +msgstr "2x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:66 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:107 +msgid "4x" +msgstr "4x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:70 +msgid "High-quality frame buffer" +msgstr "Genauerer Framebuffer" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:73 +msgid "Texture resolution:" +msgstr "Texturauflösung:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:76 +msgid "RES^Leet" +msgstr "Leet" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:77 +msgid "RES^Lowest" +msgstr "Sehr niedrig" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:78 +msgid "RES^Low" +msgstr "Niedrig" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:79 +msgid "RES^Normal" +msgstr "Normal" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:80 +msgid "RES^Good" +msgstr "Gut" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:81 +msgid "RES^Best" +msgstr "Sehr gut" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:94 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:97 +msgid "Avoid lossy texture compression" +msgstr "Texturkompression vermeiden" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:103 +msgid "Anisotropy:" +msgstr "Anisotropie:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:105 +msgid "ANISO^Disabled" +msgstr "Aus" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:108 +msgid "8x" +msgstr "8x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:109 +msgid "16x" +msgstr "16x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:113 +msgid "Particle quality:" +msgstr "Partikelqualität:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:116 +msgid "Particle distance:" +msgstr "Partikeldistanz:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:120 +msgid "Decals" +msgstr "Einschusslöcher" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:121 +msgid "Decals on models" +msgstr "auch auf Objekten" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:125 +msgid "Distance:" +msgstr "Distanz:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:131 +msgid "Time:" +msgstr "Zeit:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:137 +msgid "Use lightmaps" +msgstr "Lightmaps verwenden" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:138 +msgid "Deluxe mapping" +msgstr "Deluxemapping" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:140 +msgid "Gloss" +msgstr "Glanz" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:143 +msgid "Offset mapping" +msgstr "Offsetmapping" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:145 +msgid "Relief mapping" +msgstr "Reliefmapping" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:148 +msgid "Reflections:" +msgstr "Reflexionen:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:151 +msgid "Blurred" +msgstr "Schwammig" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:152 +msgid "REFL^Good" +msgstr "Gut" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:153 +msgid "Sharp" +msgstr "Scharf" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:158 +msgid "Show surfaces" +msgstr "Oberflächen anzeigen" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:160 +msgid "No dynamic lighting" +msgstr "Kein dynamisches Licht" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:162 +msgid "Flash blend approximation" +msgstr "Flash-Blend-Näherung" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:164 +msgid "Realtime dynamic lighting" +msgstr "Dynamisches Licht in Echtzeit" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:165 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:169 +msgid "Shadows" +msgstr "Schatten" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:168 +msgid "Realtime world lighting" +msgstr "Map-Licht in Echtzeit" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:173 +msgid "Use normal maps" +msgstr "Normalmaps verwenden" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:175 +msgid "Soft shadows" +msgstr "Weiche Schatten" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:178 +msgid "Coronas" +msgstr "Koronas" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:179 +msgid "Use Occlusion Queries" +msgstr "Occlusion Queries verwenden" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:181 +msgid "High Dynamic Range (HDR)" +msgstr "Lichtdynamik (HDR)" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:185 +msgid "Motion blur:" +msgstr "Bewegungsunschärfe:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:190 +msgid "Blur and sharpen postprocessing" +msgstr "Schärfeeffekte" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:26 +msgid "Key bindings:" +msgstr "Tastenbelegung:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:31 +msgid "Change key..." +msgstr "Taste ändern..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:35 +msgid "Edit..." +msgstr "Bearbeiten..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:46 +msgid "Sensitivity:" +msgstr "Empfindlichkeit:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:51 +msgid "UI mouse speed:" +msgstr "Mausgeschwindigkeit:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:55 +msgid "Mouse filter" +msgstr "Mausfilterung" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:57 +msgid "Invert mouse" +msgstr "Höhe invertieren" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:60 +#: qcsrc/menu/xonotic/dialog_settings_input.c:62 +msgid "Use joystick input" +msgstr "Joystick verwenden" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:65 +#: qcsrc/menu/xonotic/dialog_settings_input.c:67 +msgid "Turn off OS mouse acceleration" +msgstr "Mausbeschleunigung deaktivieren" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:69 +msgid "\"enter console\" also closes" +msgstr "\"Konsole öffnen\" schließt auch" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:72 +msgid "Holding jump key keeps jumping" +msgstr "Festhalten der Springen-Taste springt weiter" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:5 +msgid "User defined key bind" +msgstr "Benutzerdefinierte Tastenbelegung" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:42 +msgid "Command when pressed:" +msgstr "Befehl beim Drücken:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:45 +msgid "Command when released:" +msgstr "Befehl beim Loslassen:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:48 +msgid "Save" +msgstr "Speichern" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:51 +msgid "Cancel" +msgstr "Abbrechen" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:26 +msgid "Menu skins:" +msgstr "Menü-Skins:" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:47 +msgid "Show current time" +msgstr "Uhrzeit anzeigen" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:49 +msgid "Show current date" +msgstr "Datum anzeigen" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:51 +msgid "Show frames per second" +msgstr "Frames pro Sekunde anzeigen" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:53 +msgid "Minimize input latency" +msgstr "Eingabelatenz minimieren" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:59 +msgid "Menu Tooltips:" +msgstr "Menü-Tooltips:" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:61 +msgid "Standard" +msgstr "Standard" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:5 +msgid "Advanced settings" +msgstr "Erweiterte Einstellungen" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:23 +msgid "Cvar filter:" +msgstr "Cvar-Filter:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:34 +msgid "Setting:" +msgstr "Einstellung:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:42 +msgid "Value:" +msgstr "Wert:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:56 +msgid "Description:" +msgstr "Beschreibung:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:26 +msgid "Client-side movement prediction" +msgstr "Client-seitige Bewegungssimulation" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:30 +msgid "Show netgraph" +msgstr "Netgraph anzeigen" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:33 +msgid "Network speed:" +msgstr "Netzwerkgeschwindigkeit:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:35 +msgid "56k" +msgstr "Modem" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:36 +msgid "ISDN" +msgstr "ISDN" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:37 +msgid "Slow ADSL" +msgstr "ADSL (langsam)" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:38 +msgid "Fast ADSL" +msgstr "ADSL (schnell)" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:39 +msgid "Broadband" +msgstr "Breitband" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:42 +msgid "Input packets/s:" +msgstr "Eingabe-Pakete/s:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:46 +msgid "HTTP downloads:" +msgstr "HTTP-Downloads:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:49 +msgid "Downloads:" +msgstr "Downloads:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:53 +msgid "Speed (kB/s):" +msgstr "Geschwindigkeit (kB/s):" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:57 +msgid "Client UDP port:" +msgstr "Client-UDP-Port:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:26 +msgid "Resolution:" +msgstr "Auflösung:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:29 +msgid "Font/UI size:" +msgstr "Schriftgröße:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:31 +msgid "SZ^Unreadable" +msgstr "Unleserlich" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:32 +msgid "SZ^Tiny" +msgstr "Winzig" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:33 +msgid "SZ^Little" +msgstr "Klein" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:34 +msgid "SZ^Small" +msgstr "Klein" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:35 +msgid "SZ^Medium" +msgstr "Mittel" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:36 +msgid "SZ^Large" +msgstr "Groß" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:37 +msgid "SZ^Huge" +msgstr "Riesig" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:38 +msgid "SZ^Gigantic" +msgstr "Gigantisch" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:39 +msgid "SZ^Colossal" +msgstr "Kolossal" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:42 +msgid "Color depth:" +msgstr "Farbtiefe:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:45 +msgid "Full screen" +msgstr "Vollbild" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:46 +msgid "Vertical Synchronization" +msgstr "Vertikale Synchronisation" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:48 +msgid "Use OpenGL 2.0 shaders (GLSL)" +msgstr "OpenGL 2.0 Shaders verwenden (GLSL)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:51 +msgid "Use GLSL to handle color control" +msgstr "GLSL für Farbregelung verwenden" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:55 +msgid "Vertex Buffer Objects (VBOs)" +msgstr "Vertex Buffer Objects (VBOs)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:58 +msgid "VBO^Off" +msgstr "Aus" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:59 +msgid "Vertices, some Tris (compatible)" +msgstr "Ecken, einige Dreiecke (kompatibel)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:62 +msgid "Vertices" +msgstr "Ecken" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:63 +msgid "Vertices and Triangles" +msgstr "Ecken und Dreiecke" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:66 +msgid "Depth first:" +msgstr "Tiefe zuerst rendern:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:68 +msgid "DF^Disabled" +msgstr "Aus" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:69 +msgid "DF^World" +msgstr "nur Map" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:70 +msgid "DF^All" +msgstr "Immer" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:73 +msgid "Wait for GPU to finish each frame" +msgstr "Bei jedem Frame auf die Grafikkarte warten" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:76 +msgid "Brightness:" +msgstr "Helligkeit:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:79 +msgid "Contrast:" +msgstr "Kontrast:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:82 +msgid "Gamma:" +msgstr "Gamma:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:87 +msgid "Contrast boost:" +msgstr "Kontrasterhöhung:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:92 +msgid "Saturation:" +msgstr "Sättigung:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:98 +msgid "LIT^Ambient:" +msgstr "Umgebungslicht:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:101 +msgid "Intensity:" +msgstr "Lichtstärke:" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:4 +msgid "Singleplayer" +msgstr "Einzelspieler" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:116 +msgid "Instant action! (random map with bots)" +msgstr "Sofortstart! (zufällige Map mit Bots)" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:137 +msgid "Start Singleplayer!" +msgstr "Spiel starten!" + +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:4 +msgid "Winner" +msgstr "Gewinner" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:5 +msgid "Team Selection" +msgstr "Teamauswahl" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:41 +msgid "join 'best' team (auto-select)" +msgstr "'bestem' Team beitreten" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:45 +msgid "red" +msgstr "rot" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:46 +msgid "blue" +msgstr "blau" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:47 +msgid "yellow" +msgstr "gelb" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:48 +msgid "pink" +msgstr "pink" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:51 +msgid "spectate" +msgstr "zuschauen" + +#: qcsrc/menu/xonotic/mainwindow.c:35 qcsrc/menu/xonotic/mainwindow.c:38 +msgid "Do not press this button again!" +msgstr "Bitte nicht nochmal diesen Knopf drücken!" + +#: qcsrc/menu/xonotic/maplist.c:278 +msgid "" +"Huh? Can't play this (m is NULL). Refiltering so this won't happen again.\n" +msgstr "" +"Hä? Kann diese Map nicht starten (m ist NULL). Mapliste wird neu gefiltert.\n" + +#: qcsrc/menu/xonotic/maplist.c:286 +#, c-format +msgid "%s's Xonotic Server" +msgstr "%ss Xonotic-Server" + +#: qcsrc/menu/xonotic/maplist.c:291 +msgid "" +"Huh? Can't play this (invalid game type). Refiltering so this won't happen " +"again.\n" +msgstr "" +"Hä? Kann diese Map nicht starten (ungültiger Spieltyp). Mapliste wird neu " +"gefiltert.\n" + +#: qcsrc/menu/xonotic/playermodel.c:174 +msgid "" +msgstr "" + +#: qcsrc/menu/xonotic/serverlist.c:185 +msgid "Remove" +msgstr "Vergessen" + +#: qcsrc/menu/xonotic/serverlist.c:187 +msgid "Bookmark" +msgstr "Speichern" + +#: qcsrc/menu/xonotic/serverlist.c:548 +msgid "Ping" +msgstr "Ping" + +#: qcsrc/menu/xonotic/serverlist.c:549 +msgid "Host name" +msgstr "Servername" + +#: qcsrc/menu/xonotic/serverlist.c:550 +msgid "Map" +msgstr "Map" + +#: qcsrc/menu/xonotic/serverlist.c:551 +msgid "Type" +msgstr "Typ" + +#: qcsrc/menu/xonotic/serverlist.c:552 +msgid "Players" +msgstr "Spieler" + +#: qcsrc/menu/xonotic/skinlist.c:105 +msgid "" +msgstr "<TITEL>" + +#: qcsrc/menu/xonotic/skinlist.c:106 +msgid "<AUTHOR>" +msgstr "<AUTOR>" + +#: qcsrc/menu/xonotic/slider_decibels.c:50 +msgid "VOL^OFF" +msgstr "AUS" + +#: qcsrc/menu/xonotic/slider_decibels.c:52 +msgid "VOL^MAX" +msgstr "MAX" + +#: qcsrc/menu/xonotic/slider_decibels.c:53 +#, c-format +msgid "%s dB" +msgstr "%s dB" + +#: qcsrc/menu/xonotic/slider_resolution.c:65 +#, c-format +msgid "%dx%d" +msgstr "%dx%d" + +#: qcsrc/menu/xonotic/util.qc:276 +#, c-format +msgid "Received HTTP request data for an invalid id %d.\n" +msgstr "HTTP-Antwort für ungültige ID %d erhalten.\n" + +#: qcsrc/menu/xonotic/util.qc:291 +#, c-format +msgid "error receiving update notification: status is %d\n" +msgstr "Fehler beim Empfang von Update-Information (Status: %d)\n" + +#: qcsrc/menu/xonotic/util.qc:296 +msgid "error: received HTML instead of an update notification\n" +msgstr "Fehler: HTML statt Update-Information erhalten\n" + +#: qcsrc/menu/xonotic/util.qc:301 +msgid "error: received carriage returns from update notification server\n" +msgstr "Fehler: Carriage-Returns in Update-Information enthalten\n" + +#: qcsrc/menu/xonotic/util.qc:322 +#, c-format +msgid "" +"Update can be downloaded at:\n" +"%s\n" +msgstr "" +"Das Update kann bei:\n" +"%s\n" +"heruntergeladen werden.\n" + +#: qcsrc/menu/xonotic/util.qc:351 +msgid "Autogenerating mapinfo for newly added maps..." +msgstr "Automatische Generierung von mapinfo-Dateien..." + +#: qcsrc/menu/xonotic/util.qc:381 +#, c-format +msgid "^1%s TEST BUILD" +msgstr "^1%s TESTVERSION" + +#: qcsrc/menu/xonotic/util.qc:439 +#, c-format +msgid "Update to %s now!" +msgstr "Jetzt auf %s updaten!" + +#: qcsrc/menu/xonotic/util.qc:524 +msgid "" +"^1ERROR: Texture compression is required but not supported.\n" +"^1Expect visual problems.\n" +msgstr "" +"^1FEHLER: Texturekompression ist notwendig aber nicht unterstützt.\n" +"^1Darstellungsprobleme sind zu erwarten.\n" + +#: qcsrc/menu/xonotic/util.qc:546 +msgid "Arena" +msgstr "Arena" + +#: qcsrc/menu/xonotic/util.qc:547 +msgid "Assault" +msgstr "Assault" + +#: qcsrc/menu/xonotic/util.qc:548 +msgid "Capture The Flag" +msgstr "Capture The Flag" + +#: qcsrc/menu/xonotic/util.qc:549 +msgid "Clan Arena" +msgstr "Clan Arena" + +#: qcsrc/menu/xonotic/util.qc:550 +msgid "Deathmatch" +msgstr "Deathmatch" + +#: qcsrc/menu/xonotic/util.qc:551 +msgid "Domination" +msgstr "Domination" + +#: qcsrc/menu/xonotic/util.qc:552 +msgid "Freeze Tag" +msgstr "Freeze Tag" + +#: qcsrc/menu/xonotic/util.qc:553 +msgid "Keepaway" +msgstr "Keepaway" + +#: qcsrc/menu/xonotic/util.qc:554 +msgid "Key Hunt" +msgstr "Key Hunt" + +#: qcsrc/menu/xonotic/util.qc:555 +msgid "Last Man Standing" +msgstr "Last Man Standing" + +#: qcsrc/menu/xonotic/util.qc:556 +msgid "Nexball" +msgstr "Nexball" + +#: qcsrc/menu/xonotic/util.qc:557 +msgid "Onslaught" +msgstr "Onslaught" + +#: qcsrc/menu/xonotic/util.qc:558 +msgid "Race" +msgstr "Race" + +#: qcsrc/menu/xonotic/util.qc:559 +msgid "Race CTS" +msgstr "Race CTS" + +#: qcsrc/menu/xonotic/util.qc:560 +msgid "Runematch" +msgstr "Runematch" + +#: qcsrc/menu/xonotic/util.qc:561 +msgid "Team Deathmatch" +msgstr "Team Deathmatch" + +#: qcsrc/menu/xonotic/util.qc:580 +#, c-format +msgid "@!#%'n Tuba Throwing" +msgstr "@!#%'n Tuba-Werfen" + +#: qcsrc/menu/xonotic/util.qc:600 qcsrc/menu/xonotic/util.qc:616 +#: qcsrc/menu/xonotic/util.qc:625 qcsrc/menu/xonotic/util.qc:633 +#: qcsrc/menu/xonotic/util.qc:645 +msgid "Default" +msgstr "Standard" + +#: qcsrc/menu/xonotic/util.qc:611 +msgid "Use default" +msgstr "Standard verwenden" + +#: qcsrc/menu/xonotic/util.qc:631 +msgid "Team Color:" +msgstr "Teamfarbe:" + +#: qcsrc/menu/xonotic/util.qh:48 +msgid "Enable panel" +msgstr "Panel aktivieren" + +#: weapons.qc.tmp:1 +msgid "Crylink" +msgstr "Crylink" + +#: weapons.qc.tmp:2 +msgid "Heavy Laser Assault Cannon" +msgstr "Heavy Laser Assault Cannon" + +#: weapons.qc.tmp:3 +msgid "MinstaNex" +msgstr "MinstaNex" + +#: weapons.qc.tmp:4 +msgid "Mortar" +msgstr "Mortar" + +#: weapons.qc.tmp:5 +msgid "Laser" +msgstr "Laser" + +#: weapons.qc.tmp:6 +msgid "Nex" +msgstr "Nex" + +#: weapons.qc.tmp:7 +msgid "Grappling Hook" +msgstr "Enterhaken" + +#: weapons.qc.tmp:8 +msgid "Rocket Launcher" +msgstr "Rocket Launcher" + +#: weapons.qc.tmp:9 +msgid "Port-O-Launch" +msgstr "Port-O-Launch" + +#: weapons.qc.tmp:10 +msgid "Electro" +msgstr "Electro" + +#: weapons.qc.tmp:11 +msgid "Hagar" +msgstr "Hagar" + +#: weapons.qc.tmp:12 +msgid "Shotgun" +msgstr "Shotgun" + +#: weapons.qc.tmp:13 +#, c-format +msgid "@!#%'n Tuba" +msgstr "@!#%'n Tuba" + +#: weapons.qc.tmp:14 +msgid "Mine Layer" +msgstr "Mine Layer" + +#: weapons.qc.tmp:15 +msgid "Rifle" +msgstr "Gewehr" + +#: weapons.qc.tmp:16 +msgid "Machine Gun" +msgstr "Machine Gun" + +#: weapons.qc.tmp:17 +msgid "Fireball" +msgstr "Fireball" + +#: weapons.qc.tmp:18 +msgid "T.A.G. Seeker" +msgstr "T.A.G. Seeker" + +#~ msgid "Powerup sharpen" +#~ msgstr "Bonus-Schärfe" + +#~ msgid "Damage & water blur" +#~ msgstr "Schadens-Unschärfe" + +#~ msgid "%s sniped themself somehow" +#~ msgstr "%s hat so scharf geschossen, dass er sich selbst getroffen hat" + +#~ msgid "%s shot themself automatically" +#~ msgstr "%s hat sich vollautomatisch selbst erschossen" + +#~ msgid "%s exploded" +#~ msgstr "%s ist explodiert" + +#~ msgid "%s hoped %s's missiles wouldn't bounce" +#~ msgstr "%s hat gehofft, dass %ss Raketen nicht von Wänden abprallen" + +#~ msgid "%s detonated" +#~ msgstr "%s verfing sich in der eigenen Detonation" + +#~ msgid "%s tried out his own grenade" +#~ msgstr "%s wollte wissen, ob seine Granate funktioniert" + +#~ msgid "Disable multithreaded OpenGL" +#~ msgstr "OpenGL-Multithreading deaktivieren" + +#~ msgid "Bloom" +#~ msgstr "Überstrahlung" + +#~ msgid "All players" +#~ msgstr "Alle Spieler" + +#~ msgid "Teammates" +#~ msgstr "Mitspieler" + +#~ msgid "Show names:" +#~ msgstr "Namen anzeigen:" + +#~ msgid "%s died of %s's great playing on the @!#%%'n Tuba" +#~ msgstr "" +#~ "%s ist an seinen Ohrenschmerzen, die von %ss großartigem Spiel auf der @!#" +#~ "%%'n Tuba stammten, gestorben" + +#~ msgid "%s hurt his own ears with the @!#%%'n Tuba" +#~ msgstr "" +#~ "%s haben die Ohren geschmerzt von seinem eigenen Spiel auf der @!#%%'n " +#~ "Tuba" + +#~ msgid "%s ate %s's rocket" +#~ msgstr "%s hat %ss Rakete in den Mund genommen" + +#~ msgid "%s almost dodged %s's rocket" +#~ msgstr "%s ist fast %ss Rakete ausgewichen" + +#~ msgid "%s got too close to %s's rocket" +#~ msgstr "%s ist %ss Rakete zu nahe getreten" + +#~ msgid "%s failed to hide from %s's rifle" +#~ msgstr "%s hat es nicht geschafft, sich vor %ss Gewehr zu verstecken" + +#~ msgid "%s felt %s doing the impossible to him" +#~ msgstr "%s hat gespürt, wie %s das Unmögliche für ihn getan hat" + +#~ msgid "%s is now thinking with portals" +#~ msgstr "%s kann jetzt mit Portalen denken" + +#~ msgid "%s stepped on %s's mine" +#~ msgstr "%s ist auf %ss Mine gelatscht" + +#~ msgid "%s almost dodged %s's mine" +#~ msgstr "%s ist fast %ss Mine ausgewichen" + +#~ msgid "%s got too close to %s's mine" +#~ msgstr "%s ist %ss Mine zu nahe getreten" + +#~ msgid "%s was lasered to death by %s" +#~ msgstr "^1%s^1 wurde von %s^1 zu Tode gelasert" + +#~ msgid "%s was cut in half by %s's gauntlet" +#~ msgstr "%s ist von %ss Gauntlet halbiert worden" + +#~ msgid "%s lasered themself to hell" +#~ msgstr "%s hat sich in die Hölle gelasert" + +#~ msgid "%s did the impossible" +#~ msgstr "%s hat das Unmögliche geschafft" + +#~ msgid "%s ate %s's grenade" +#~ msgstr "%s nahm %ss Granate in den Mund" + +#~ msgid "%s almost dodged %s's grenade" +#~ msgstr "%s ist fast %ss Granate ausgewichen" + +#~ msgid "%s didn't see %s's grenade" +#~ msgstr "%s hat %ss Granate nicht gesehen" + +#~ msgid "%s tasted %s's fireball" +#~ msgstr "%s hat von %ss Feuerball probiert" + +#~ msgid "%s got too close to %s's fireball" +#~ msgstr "%s ist %ss Feuerball zu nahe getreten" + +#~ msgid "%s saw the pretty lights of %s's fireball" +#~ msgstr "%s hat die hübschen Lichter von %ss Feuerball gesehen" + +#~ msgid "%s could not hide from %s's fireball" +#~ msgstr "%s konnte sich nicht vor %ss Feuerball verstecken" + +#~ msgid "%s fatefully ignored %s's firemine" +#~ msgstr "%s hat tragischerweise %ss Feuermine ignoriert" + +#~ msgid "%s tried to catch %s's firemine" +#~ msgstr "%s hat versucht %ss Feuermine zu fangen" + +#~ msgid "%s should have used a smaller gun" +#~ msgstr "%s hätte eine kleinere Waffe nehmen sollen" + +#~ msgid "%s forgot about some firemine" +#~ msgstr "%s hat den Platz einer Feuermine vergessen" + +#~ msgid "%s took a close look at %s's Crylink" +#~ msgstr "%s schaute sich %ss Crylink sehr genau an" + +#~ msgid "%s was too close to %s's Crylink" +#~ msgstr "%s trat %ss Crylink zu nahe" + +#~ msgid "%s could not hide from %s's Crylink" +#~ msgstr "%s konnte sich nicht vor %ss Crylink verstecken" + +#~ msgid "%s succeeded at self-destructing themself with the Crylink" +#~ msgstr "%s zerstörte sich selbst erfolgreich mit der Crylink" + +#~ msgid "%s was riddled full of holes by %s's machine gun" +#~ msgstr "%s ist von %s durchlöchert worden wie ein Schweizer Käse" + +#~ msgid "%s was sniped by %s's machine gun" +#~ msgstr "%s wurde von %ss Maschinengewehr erledigt" + +#~ msgid "%s died of %s's great playing on the @!#%%'n Accordeon" +#~ msgstr "" +#~ "%s ist an seinen Ohrenschmerzen, die von %ss großartigem Spiel auf dem @!#" +#~ "%%'n Akkordeon stammten, gestorben" + +#~ msgid "%s hurt his own ears with the @!#%%'n Accordeon" +#~ msgstr "" +#~ "%s haben die Ohren geschmerzt von seinem eigenen Spiel auf dem @!#%%'n " +#~ "Akkordeon" + +#~ msgid "%s was gunned down with a shotgun by %s" +#~ msgstr "%s wurde von %s erschossen" + +#~ msgid "%2$s slapped %1$s around a bit with a large shotgun" +#~ msgstr "%2$s hat %1$s ein wenig mit einer großen Schrotflinte geschlagen" + +#~ msgid "%s was pummeled with seeker rockets by %s" +#~ msgstr "%s wurde von %s erwischt" + +#~ msgid "%s was tagged with a seeker by %s" +#~ msgstr "%s wurde von %s getagged" + +#~ msgid "%s played with tiny seeker rockets" +#~ msgstr "%s hat mit kleinen Raketen gespielt" + +#~ msgid "%s was sniped with a rifle by %s" +#~ msgstr "%s wurde von %s fachmännisch erledigt" + +#~ msgid "%s got shot in the head with a rifle by %s" +#~ msgstr "%s hat ein Loch im Kopf bekommen; schuld war %s" + +#~ msgid "%s died in %s's rifle bullet hail" +#~ msgstr "%s ist in %ss Kugelhagel gefallen" + +#~ msgid "%s failed to hide from %s's rifle bullet hail" +#~ msgstr "%s hat es nicht geschafft, sich vor %ss Kugelhagel zu verstecken" + +#~ msgid "%s has been vaporized by %s's nex" +#~ msgstr "%s^1 wurde von %ss Nex vernichtet" + +#~ msgid "%s has been vaporized by %s's minstanex" +#~ msgstr "%s^1 wurde von %ss MinstaNex vernichtet" + +#~ msgid "%s forgot about their mine" +#~ msgstr "%s hat den Platz einer Mine vergessen" + +#~ msgid "%s was caught in %s's hook gravity bomb" +#~ msgstr "%s ist in %ss Gravitationsbombe reingelaufen" + +#~ msgid "%s was cut down with a HLAC by %s" +#~ msgstr "%s wurde von %ss HLAC niedergehauen" + +#~ msgid "%s was pummeled with hagar rockets by %s" +#~ msgstr "%s wurde von %ss Hagar-Raketen erwischt" + +#~ msgid "%s was pummeled with a burst of hagar rockets by %s" +#~ msgstr "%s ist von %s durchlöchert worden wie ein Schweizer Käse" + +#~ msgid "%s played with tiny hagar rockets" +#~ msgstr "%s hat mit kleinen Raketen gespielt" + +#~ msgid "%s didn't see their own grenade" +#~ msgstr "%s hat die eigene Granate übersehen" + +#~ msgid "%s was blasted by %s's blue electro bolt" +#~ msgstr "%s wurde von %ss blauen Strahl erwischt" + +#~ msgid "%s got too close to %s's blue electro bolt" +#~ msgstr "%s kam zu nah an %ss blauen Strahl" + +#~ msgid "%s felt the electrifying air of %s's electro combo" +#~ msgstr "%s hat gespürt, wie %ss Combo die Luft elektrisierte" + +#~ msgid "%s got in touch with %s's electro plasma" +#~ msgstr "%s kam mit %ss Plasma in Kontakt" + +#~ msgid "%s just noticed %s's electro plasma" +#~ msgstr "%s hat gerade %ss Plasma bemerkt" + +#~ msgid "%s played with electro plasma" +#~ msgstr "%s spielte mit Plasma" + +#~ msgid "%s could not remember where they put their electro plasma" +#~ msgstr "%s vergaß, wo er das Plasma hingetan hatte" diff --git a/menu.dat.el.po b/menu.dat.el.po new file mode 100644 index 0000000000..ad574ed9fc --- /dev/null +++ b/menu.dat.el.po @@ -0,0 +1,2957 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# Γιάννης Α. <yannanth@gmail.com>, 2011. +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-09-12 12:24+0200\n" +"PO-Revision-Date: 2011-12-05 22:27-0000\n" +"Last-Translator: Γιάννης Α. <yannanth@gmail.com>\n" +"Language-Team: Γ.Α.\n" +"Language: el\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Virtaal 0.7.0\n" + +#: qcsrc/menu/menu.qc:29 +#, c-format +msgid "^4MQC Build information: ^1%s\n" +msgstr "^4MQC Πληροφορίες εκδοχής: ^1%s\n" + +#: qcsrc/menu/item/slider.c:64 +#, c-format +msgid "%d (%s)" +msgstr "%d (%s)" + +#: qcsrc/menu/item/label.c:63 +#, c-format +msgid "NOTE: label text %s too wide for label, condensed by factor %f\n" +msgstr "" + +#: qcsrc/menu/item/textslider.c:29 +#: qcsrc/menu/item/textslider.c:31 +msgid "custom" +msgstr "προσαρμογή" + +#: qcsrc/menu/item/gecko.c:49 +msgid "Browser not initialized!" +msgstr "Ο περιηγητής δεν έχει αρχίσει!" + +#: qcsrc/menu/item/listbox.c:300 +#, c-format +msgid "Item %d" +msgstr "Αντικείμενο %d" + +#: qcsrc/menu/gamecommand.qc:47 +#, c-format +msgid "error: status is %d\n" +msgstr "" + +#: qcsrc/menu/gamecommand.qc:65 +msgid "Usage: menu_cmd command..., where possible commands are:\n" +msgstr "" + +#: qcsrc/menu/gamecommand.qc:66 +msgid " sync - reloads all cvars on the current menu page\n" +msgstr "" + +#: qcsrc/menu/gamecommand.qc:67 +msgid " directmenu ITEM - select a menu item as main item\n" +msgstr "" + +#: qcsrc/menu/gamecommand.qc:193 +msgid "error creating curl handle\n" +msgstr "" + +#: qcsrc/menu/gamecommand.qc:239 +msgid "Invalid command. For a list of supported commands, try menu_cmd help.\n" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:4 +#: qcsrc/menu/xonotic/dialog_settings.c:19 +msgid "Video" +msgstr "Βίντεο" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:26 +msgid "Resolution:" +msgstr "Ανάλυση:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:29 +#, fuzzy +msgid "Font/UI size:" +msgstr "Μέγεθος γραμματοσειράς/UI:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:31 +msgid "SZ^Unreadable" +msgstr "SZ^Αδιάβαστο" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:32 +msgid "SZ^Tiny" +msgstr "SZ^Μικροσκοπικό" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:33 +msgid "SZ^Little" +msgstr "SZ^Μικρούτσικο" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:34 +msgid "SZ^Small" +msgstr "SZ^Μικρό" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:35 +msgid "SZ^Medium" +msgstr "SZ^Μεσαίο" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:36 +msgid "SZ^Large" +msgstr "SZ^Μεγάλο" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:37 +msgid "SZ^Huge" +msgstr "SZ^Τεράστιο" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:38 +msgid "SZ^Gigantic" +msgstr "SZ^Γιγάντιο" + +# Maybe τιτανικό (titanic) would be better, this may be associated with the Colosseum in Rome... +#: qcsrc/menu/xonotic/dialog_settings_video.c:39 +#, fuzzy +msgid "SZ^Colossal" +msgstr "SZ^Κολοσσαίο" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:42 +msgid "Color depth:" +msgstr "Βάθος χρώματος:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:45 +msgid "Full screen" +msgstr "Πλήρης οθόνη" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:46 +msgid "Vertical Synchronization" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:49 +msgid "Use OpenGL 2.0 shaders (GLSL)" +msgstr "Χρήση σκιών (shaders) OpenGL 2.0 (GLSL)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:52 +msgid "Use GLSL to handle color control" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:56 +msgid "Vertex Buffer Objects (VBOs)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:59 +msgid "VBO^Off" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:60 +msgid "Vertices, some Tris (compatible)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:63 +msgid "Vertices" +msgstr "Κορυφές" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:64 +msgid "Vertices and Triangles" +msgstr "Κορυφές και Τρίγωνα" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:67 +msgid "Depth first:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:69 +msgid "DF^Disabled" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:70 +msgid "DF^World" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:71 +msgid "DF^All" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:75 +msgid "Disable multithreaded OpenGL" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:77 +msgid "Wait for GPU to finish each frame" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:80 +msgid "Brightness:" +msgstr "Φωτεινότητα:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:83 +msgid "Contrast:" +msgstr "Αντίθεση:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:86 +msgid "Gamma:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:91 +msgid "Contrast boost:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:96 +msgid "Saturation:" +msgstr "Κορεσμός:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:102 +msgid "LIT^Ambient:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:105 +msgid "Intensity:" +msgstr "Ένταση:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:109 +#: qcsrc/menu/xonotic/dialog_settings_input.c:74 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:30 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:41 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:195 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:194 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:173 +msgid "Apply immediately" +msgstr "Άμεση εφαρμογή" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:4 +msgid "Panel HUD Setup" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:21 +msgid "Panel background defaults:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:23 +#: qcsrc/menu/xonotic/util.qc:587 +msgid "Background:" +msgstr "Φόντο:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:25 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:37 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:52 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:91 +#: qcsrc/menu/xonotic/util.qc:590 +#: qcsrc/menu/xonotic/util.qc:606 +#: qcsrc/menu/xonotic/util.qc:623 +msgid "Disable" +msgstr "Απενεργοποίηση" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:30 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:77 +#: qcsrc/menu/xonotic/util.qc:595 +msgid "Color:" +msgstr "Χρώμα:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:35 +#: qcsrc/menu/xonotic/util.qc:603 +msgid "Border size:" +msgstr "Μέγεθος περιθωρίου:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:43 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:82 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:32 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:154 +#: qcsrc/menu/xonotic/util.qc:612 +msgid "Alpha:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:50 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:89 +msgid "Team color:" +msgstr "Χρώμα ομάδας:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:58 +#: qcsrc/menu/xonotic/util.qc:629 +msgid "Test team color in configure mode" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:61 +#: qcsrc/menu/xonotic/util.qc:632 +msgid "Padding:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:68 +msgid "HUD Dock:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:70 +msgid "DOCK^Disabled" +msgstr "DOCK^Απενεργοποιημένο" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:71 +msgid "DOCK^Small" +msgstr "DOCK^Μικρό" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:72 +msgid "DOCK^Medium" +msgstr "DOCK^Μεσαίο" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:73 +msgid "DOCK^Large" +msgstr "DOCK^Μεγάλο" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:96 +msgid "Grid settings:" +msgstr "Ρυθμίσεις πλέγματος:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:99 +msgid "Snap panels to grid" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:102 +msgid "Grid size:" +msgstr "Μέγεθος πλέγματος:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:103 +msgid "X:" +msgstr "Χ:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:109 +msgid "Y:" +msgstr "Ψ:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:117 +msgid "Exit setup" +msgstr "Έξοδος ρύθμισης" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:4 +msgid "Vote Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:22 +msgid "Alpha after voting:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_modicons.c:4 +msgid "Mod Icons Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:4 +#, fuzzy +msgid "Info Messages Panel" +msgstr "Πίνακας Πληροφοριών" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:22 +#, fuzzy +msgid "Info messages:" +msgstr "Πληροφοριακά μηνύματα:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:25 +msgid "Flip align" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:5 +msgid "Waypoints" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:23 +msgid "Show base waypoints" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:25 +msgid "Waypoint scale:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:29 +msgid "Waypoint alpha:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:34 +msgid "Show names:" +msgstr "Εμφάνιση ονομάτων:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:36 +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:26 +msgid "Never" +msgstr "Ποτέ" + +# Might just mean other people playing with you, literally (official definition) "co-players" +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:37 +#, fuzzy +msgid "Teammates" +msgstr "Συμπαίκτες" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:38 +msgid "All players" +msgstr "Όλοι οι παίκτες" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:41 +#: qcsrc/menu/xonotic/dialog_credits.c:21 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:61 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:269 +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:57 +msgid "OK" +msgstr "ΟΚ" + +#: qcsrc/menu/xonotic/dialog_credits.c:5 +msgid "Credits" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:5 +msgid "Advanced settings" +msgstr "Προχωρημένες ρυθμίσεις:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:23 +msgid "Cvar filter:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:24 +#: qcsrc/menu/xonotic/dialog_settings_input.c:41 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:29 +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:33 +msgid "Clear" +msgstr "Εκκαθάριση" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:34 +msgid "Setting:" +msgstr "Ρύθμιση:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:38 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:254 +msgid "Type:" +msgstr "Τύπος:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:42 +#, fuzzy +msgid "Value:" +msgstr "Τιμή:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:56 +msgid "Description:" +msgstr "Περιγραφή:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:4 +msgid "Pressed Keys Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:21 +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:21 +msgid "Panel disabled" +msgstr "Πίνακας απενεργοποιημένος" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:22 +msgid "Panel enabled when spectating" +msgstr "Πίνακας ενεργοποιημένος στην θέαση" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:23 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:23 +msgid "Panel always enabled" +msgstr "Πίνακας πάντα ενεργοποιημένος" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:30 +msgid "Forced aspect:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:5 +msgid "Team Selection" +msgstr "Επιλογή Ομαδάς" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:41 +msgid "join 'best' team (auto-select)" +msgstr "μπες στην «καλύτερη» ομάδα (αυτόματη επιλογή)" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:45 +msgid "red" +msgstr "κόκκινο" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:46 +msgid "blue" +msgstr "μπλε" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:47 +msgid "yellow" +msgstr "κίτρινο" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:48 +msgid "pink" +msgstr "ροζ" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:51 +msgid "spectate" +msgstr "θέαση" + +#: qcsrc/menu/xonotic/slider_resolution.c:65 +#, c-format +msgid "%dx%d" +msgstr "%dx%d" + +#: qcsrc/menu/xonotic/dialog_settings.c:4 +msgid "Settings" +msgstr "Ρυθμίσεις" + +#: qcsrc/menu/xonotic/dialog_settings.c:18 +#: qcsrc/menu/xonotic/dialog_settings_input.c:4 +msgid "Input" +msgstr "Εισαγωγή" + +#: qcsrc/menu/xonotic/dialog_settings.c:20 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:4 +msgid "Effects" +msgstr "Εφέ" + +#: qcsrc/menu/xonotic/dialog_settings.c:21 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:4 +msgid "Audio" +msgstr "Ήχος" + +#: qcsrc/menu/xonotic/dialog_settings.c:22 +#: qcsrc/menu/xonotic/dialog_settings_network.c:4 +msgid "Network" +msgstr "Δίκτυο" + +#: qcsrc/menu/xonotic/dialog_settings.c:23 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:4 +msgid "Misc" +msgstr "Λοιπά" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:4 +msgid "Welcome" +msgstr "Καλώσορίσατε" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:33 +msgid "Welcome to Xonotic, please select your language preference and enter your player name to get started. You can change these options later through the menu system." +msgstr "Καλώσορίσατε στο Xonotic, πάρακαλούμε επιλέξτε της γλώσσα προτίμησης σας και είσαγετε το όνομά σας. Μπορείτε να αλλάξετε αυτές τις επιλογές αργότερα μέσω του μενού." + +#: qcsrc/menu/xonotic/dialog_firstrun.c:38 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:35 +msgid "Text language:" +msgstr "Γλώσσα κειμένου:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:47 +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:39 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:40 +msgid "Name:" +msgstr "Όνομα:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:69 +msgid "Save settings" +msgstr "Αποθήκευση ρυθμίσεων" + +#: qcsrc/menu/xonotic/campaign.c:284 +#: qcsrc/menu/xonotic/dialog_singleplayer.c:123 +msgid "???" +msgstr ";;;" + +#: qcsrc/menu/xonotic/campaign.c:285 +#, c-format +msgid "Level %d: %s" +msgstr "Επίπεδο %d:%s" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:26 +msgid "Key bindings:" +msgstr "Διαμόρφωση πλήκτρων:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:31 +msgid "Change key..." +msgstr "Αλλαγή πλήκτρου..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:35 +msgid "Edit..." +msgstr "Επεξεργασία..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:46 +msgid "Sensitivity:" +msgstr "Ταχύτητα δείκτη:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:51 +msgid "UI mouse speed:" +msgstr "Ταχύτητα δείκτη στην διεπαφή:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:55 +msgid "Mouse filter" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:57 +#, fuzzy +msgid "Invert mouse" +msgstr "Ανάτρεψη ποντικιού" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:60 +#: qcsrc/menu/xonotic/dialog_settings_input.c:62 +msgid "Use joystick input" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:65 +#: qcsrc/menu/xonotic/dialog_settings_input.c:67 +msgid "Turn off OS mouse acceleration" +msgstr "Απενεργοποίηση επιτάχυνσης δείκτη από λειτουργικό σύστημα" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:69 +msgid "\"enter console\" also closes" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:72 +msgid "Holding jump key keeps jumping" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:4 +msgid "Weapons Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:24 +msgid "Fade out after:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:28 +#, c-format +msgid "%ds" +msgstr "%ds" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:32 +msgid "Fade effect:" +msgstr "Εφέ ξεθωριάσματος" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:35 +msgid "EF^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:36 +msgid "Slide" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:37 +msgid "Alpha" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:38 +msgid "EF^Both" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:42 +msgid "Weapon icons:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:45 +msgid "Show only owned weapons" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:48 +msgid "Show weapon ID as:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:49 +msgid "SHOWAS^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:50 +msgid "Number" +msgstr "Αριθμός" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:51 +msgid "Bind" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:54 +msgid "Show Accuracy" +msgstr "Εμφάνιση Ακρίβειας" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:55 +#, fuzzy +msgid "Show Ammo" +msgstr "Εμφάνιση Πυρομαχικών" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:58 +msgid "Ammo bar color:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:64 +msgid "Ammo bar alpha:" +msgstr "" + +#: qcsrc/menu/xonotic/mainwindow.c:35 +#: qcsrc/menu/xonotic/mainwindow.c:38 +msgid "Do not press this button again!" +msgstr "Μην ξαναπατήσεις αυτό το κουμπί!" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:4 +msgid "Engine Info Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:22 +msgid "Engine info:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:25 +msgid "Use an averaging algorithm for fps" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:4 +msgid "Physics Panel" +msgstr "Πίνακας Φυσικής" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:23 +msgid "Panel enabled" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:24 +msgid "Panel enabled even observing" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:25 +msgid "Panel enabled only in Race/CTS" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:31 +msgid "Status bar" +msgstr "Γραμμή κατάστασης" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:48 +#, fuzzy +msgid "Left align" +msgstr "Ευθυγράμμιση στα αριστερά" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:34 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:52 +#, fuzzy +msgid "Right align" +msgstr "Ευθυγράμμιση στα δεξιά" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:35 +#, fuzzy +msgid "Inward align" +msgstr "Ευθυγράμμιση προς τα μέσα" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:36 +#, fuzzy +msgid "Outward align" +msgstr "Ευθυγράμμιση προς τα έξω" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:40 +msgid "Flip speed/acceleration positions" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:44 +msgid "Speed:" +msgstr "Ταχύτητα" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:45 +msgid "Include vertical speed" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:56 +msgid "Speed unit:" +msgstr "Μονάδα ταχύτητας:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:58 +msgid "qu/s" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:59 +msgid "m/s" +msgstr "μέτρα/δευτερόλεπτο" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:60 +msgid "km/h" +msgstr "χλμ/ώρα" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:61 +msgid "mph" +msgstr "μίλια/ώρα" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:62 +msgid "knots" +msgstr "κόμβοι" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:64 +msgid "Show" +msgstr "Εμφάνιση" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:67 +msgid "Top speed" +msgstr "Μέγιστη ταχύτητα" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:73 +msgid "Acceleration:" +msgstr "Επιτάχυνση:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:74 +msgid "Include vertical acceleration" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_quit.c:4 +msgid "Quit" +msgstr "Έξοδος" + +#: qcsrc/menu/xonotic/dialog_quit.c:17 +#, fuzzy +msgid "Are you sure you want to quit?" +msgstr "Είσαι σίγουρος-η ότι θες να βγεις από το παιχνίδι;" + +#: qcsrc/menu/xonotic/dialog_quit.c:20 +msgid "Yes" +msgstr "Ναι" + +#: qcsrc/menu/xonotic/dialog_quit.c:21 +msgid "No" +msgstr "Όχι" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:4 +msgid "Join" +msgstr "Σύνδεση" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:28 +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:32 +msgid "Filter:" +msgstr "Φίλτρο:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:36 +msgid "SRVS^Empty" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:40 +msgid "SRVS^Full" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:44 +msgid "Pause" +msgstr "Παύση" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:56 +msgid "Address:" +msgstr "Διεύθυνση" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:67 +msgid "Info..." +msgstr "Πληροφορίες..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:317 +msgid "Join!" +msgstr "Σύνδεση!" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:4 +msgid "Notification Panel" +msgstr "Πίνακας Ανακοινώσεων" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:22 +msgid "Notifications:" +msgstr "Ανακοινώσεις:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:25 +msgid "Also print notifications to the console" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:28 +msgid "Flip notify order" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:31 +msgid "Entry lifetime:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:35 +msgid "Entry fadetime:" +msgstr "" + +#: qcsrc/menu/xonotic/util.qh:47 +msgid "Enable panel" +msgstr "Ενεργοποίηση πίνακα" + +# It's good, but is it good enough? +#: qcsrc/menu/xonotic/dialog_settings_misc.c:26 +#, fuzzy +msgid "Menu skins:" +msgstr "Σχέδια μενού:" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:47 +msgid "Show current time" +msgstr "Εμφάνιση τρέχων ώρας" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:49 +msgid "Show current date" +msgstr "Εμφάνιση τρέχων ημερομηνίας" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:51 +msgid "Show frames per second" +msgstr "Εμφάνιση καρέ ανα δευτερόλεπτο" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:53 +msgid "Minimize input latency" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:57 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:97 +msgid "Advanced settings..." +msgstr "Προχωρημένες ρυθμίσεις..." + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:4 +#, fuzzy +msgid "Singleplayer" +msgstr "Μονό" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:116 +msgid "Instant action! (random map with bots)" +msgstr "Άμεση δράση! (τυχαίος χάρτης με ρομπότ)" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:137 +#, fuzzy +msgid "Start Singleplayer!" +msgstr "Έναρξη παιχνίδι ενός παίκτη!" + +#: qcsrc/menu/xonotic/skinlist.c:105 +msgid "<TITLE>" +msgstr "" + +#: qcsrc/menu/xonotic/skinlist.c:106 +msgid "<AUTHOR>" +msgstr "" + +#: qcsrc/menu/xonotic/skinlist.c:163 +#: qcsrc/common/mapinfo.qc:1092 +#, c-format +msgid "%s: %s" +msgstr "%s: %s" + +#: qcsrc/menu/xonotic/dialog_news.c:4 +msgid "News" +msgstr "Νέα" + +#: qcsrc/menu/xonotic/dialog_news.c:18 +msgid "http://www.xonotic.org/team/blog/" +msgstr "http://www.xonotic.org/team/blog/" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:5 +msgid "Server Information" +msgstr "Πληροφορίες Διακομιστή" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:115 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:116 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:183 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:189 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:199 +msgid "N/A" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:158 +#, c-format +msgid "%d/%d, %d free player slots" +msgstr "" + +# I would seriously prefer "Default settings" for this... official makes it sound as if they will work for certain. +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +#, fuzzy +msgid "Official settings" +msgstr "Επίσημες ρυθμίσεις" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +#, c-format +msgid "%d modified settings" +msgstr "%d τροποποιημένες ρυθμίσεις" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:197 +msgid "N/A (can't connect)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:205 +msgid "not supported (can't connect)" +msgstr "δεν υποστηρίζεται (δεν συνδέεται)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:207 +msgid "not supported (won't encrypt)" +msgstr "δεν υποστηρίζεται (δεν κρυπτογραφείζεται)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:211 +msgid "supported (will encrypt)" +msgstr "υποστηρίζεται (θα κρυπτογραφειθεί)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:213 +msgid "supported (won't encrypt)" +msgstr "υποστηρίζεται (δεν κρυπτογραφίζεται)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:217 +msgid "requested (will encrypt)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:219 +msgid "requested (won't encrypt)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:223 +msgid "required (can't connect)" +msgstr "απαιτήται (δεν συνδέεται)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:225 +msgid "required (will encrypt)" +msgstr "απαιτήται (θα κρυπτογραφειθεί)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:246 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:269 +msgid "Players:" +msgstr "Παίκτες:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:259 +msgid "Map:" +msgstr "Χάρτης:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:264 +msgid "Gameplay:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:274 +msgid "Bots:" +msgstr "Ρομπότ:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:279 +msgid "Mod:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:284 +msgid "Version:" +msgstr "Έκδοση:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:289 +msgid "Ping:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:295 +msgid "CA:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:301 +msgid "Key:" +msgstr "Κωδικός:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:307 +msgid "Encryption:" +msgstr "Κρυπτογράφηση:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:314 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:118 +msgid "Close" +msgstr "Κλείσιμο" + +#: qcsrc/menu/xonotic/slider_decibels.c:50 +#, fuzzy +msgid "VOL^OFF" +msgstr "VOL^Σίγαση" + +#: qcsrc/menu/xonotic/slider_decibels.c:52 +#, fuzzy +msgid "VOL^MAX" +msgstr "VOL^Τέρμα" + +#: qcsrc/menu/xonotic/slider_decibels.c:53 +#, c-format +msgid "%s dB" +msgstr "%s dB" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:7 +msgid "Mutators" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:33 +msgid "All Weapons Arena" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:35 +msgid "Most Weapons Arena" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:56 +#, c-format +msgid "%s Arena" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:68 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:167 +msgid "Dodging" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:70 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:250 +msgid "MinstaGib" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:253 +msgid "NIX" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:74 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:205 +msgid "Rocket Flying" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:78 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:264 +msgid "No start weapons" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:80 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:189 +msgid "Low gravity" +msgstr "Χαμηλή βαρύτητα" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:170 +msgid "Cloaked" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:84 +#, fuzzy +msgid "Hook" +msgstr "Γάντζος" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:86 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:173 +msgid "Midair" +msgstr "Στον αέρα" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:88 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:176 +msgid "Vampire" +msgstr "Βρυκόλακας" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:90 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:208 +msgid "Piñata" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:92 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:211 +msgid "Weapons stay" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:94 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:180 +msgid "Blood loss" +msgstr "Αιμορραγία" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:96 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:202 +msgid "Jet pack" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:98 +msgid "MUT^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:164 +msgid "Gameplay mutators:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:196 +msgid "Weapon & item mutators:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:199 +msgid "Grappling hook" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:215 +msgid "Weapon arenas:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:218 +msgid "Regular (no arena)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:239 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:256 +msgid "with laser" +msgstr "με λέιζερ" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:247 +msgid "Special arenas:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:260 +msgid "Most weapons" +msgstr "Περισσότερα όπλα" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:4 +msgid "Radar Panel" +msgstr "Πίνακας Ραντάρ" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:22 +msgid "Panel enabled in teamgames" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:29 +msgid "Radar:" +msgstr "Ραντάρ:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:36 +msgid "Rotation:" +msgstr "Περιστροφή:" + +# Don't know the context of this. +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:38 +#, fuzzy +msgid "Forward" +msgstr "Εμπρός" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:39 +msgid "West" +msgstr "Δυτικά" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:40 +msgid "South" +msgstr "Νότια" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:41 +msgid "East" +msgstr "Ανατολικά" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:42 +msgid "North" +msgstr "Βόρεια" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:46 +msgid "Scale:" +msgstr "Κλίμακα:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:50 +msgid "Zoom mode:" +msgstr "Ρύθμιση μεγέθυνσης:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:52 +msgid "Zoomed in" +msgstr "Μεγεθυμένο" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:53 +msgid "Zoomed out" +msgstr "Σμικρυσμένο" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:54 +msgid "Always zoomed" +msgstr "Πάντα μεγεθυμένο" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:55 +msgid "Never zoomed" +msgstr "Ποτέ μεγεθυμένο" + +#: qcsrc/menu/xonotic/dialog_hudpanel_racetimer.c:4 +msgid "Race Timer Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:4 +msgid "Chat Panel" +msgstr "Πίνακας Ομιλίας" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:22 +msgid "Chat entries:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:25 +msgid "Chat size:" +msgstr "Μέγεθος ομιλίας:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:29 +msgid "Chat lifetime:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:33 +msgid "Chat beep sound" +msgstr "Ήχος ομιλίας" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:5 +#: qcsrc/menu/xonotic/dialog_multiplayer.c:19 +msgid "Create" +msgstr "Δημιουργία" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:34 +msgid "Game type:" +msgstr "Τύπος παιχνιδιού:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:46 +msgid "Match settings:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:49 +msgid "Time limit:" +msgstr "Χρονικό όριο:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:53 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:61 +msgid "Use map specified default" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:56 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:155 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:156 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:157 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:161 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:162 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:163 +#, fuzzy +msgid "Point limit:" +msgstr "Όριο βαθμολογίας:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:64 +msgid "Player slots:" +msgstr "Θέσεις παικτών:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:67 +msgid "Number of bots:" +msgstr "Αριθμός ρομπότ:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:71 +msgid "Bot skill:" +msgstr "Ικανότητα bot:" + +# Ρομποτικό; +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:74 +msgid "Botlike" +msgstr "Χαζό ρομπότ" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:75 +msgid "Beginner" +msgstr "Αρχάριο" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:76 +msgid "You will win" +msgstr "Θα νικήσεις" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:77 +msgid "You can win" +msgstr "Μπορείς να νικήσεις" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:78 +msgid "You might win" +msgstr "Θα μπορούσες να νικήσεις" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:79 +msgid "Advanced" +msgstr "Προχωρημένο" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:80 +msgid "Expert" +msgstr "Ειδικό" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:81 +msgid "Pro" +msgstr "Εππαγγελματικό" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:82 +msgid "Assassin" +msgstr "Δολοφονικό" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:83 +msgid "Unhuman" +msgstr "Απάνθρωπο" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:84 +msgid "Godlike" +msgstr "Θεικό" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:88 +msgid "Mutators..." +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:104 +msgid "Map list:" +msgstr "Λίστα χάρτων" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:110 +msgid "Select all" +msgstr "Επιλογή όλων" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:113 +#, fuzzy +msgid "Select none" +msgstr "Επιλογή κανενός" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:119 +#, fuzzy +msgid "Start Multiplayer!" +msgstr "Εναρξή παιχνίδι πολλαπλών παικτών!" + +# Bit posh... :/ +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:154 +#, fuzzy +msgid "Capture limit:" +msgstr "Όριο καταλύψεων:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:158 +msgid "Lives:" +msgstr "Ζωές" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:159 +msgid "Laps:" +msgstr "Γύροι:" + +# Unsure of where this goes, but I think this is about right +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:160 +msgid "Goals:" +msgstr "Στόχοι:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:164 +msgid "Frag limit:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:4 +msgid "Winner" +msgstr "Νικητής" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:5 +msgid "User defined key bind" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:42 +msgid "Command when pressed:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:45 +msgid "Command when released:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:48 +msgid "Save" +msgstr "Αποθήκευση" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:51 +msgid "Cancel" +msgstr "Ακύρωση" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:5 +#: qcsrc/menu/xonotic/dialog_multiplayer.c:21 +msgid "Player Setup" +msgstr "Ρύθμισεις Παίκτη" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:63 +msgid "Model:" +msgstr "Μοντέλο:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:88 +msgid "Field of view:" +msgstr "Οπτικό πεδίο:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:92 +msgid "View bobbing:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:96 +msgid "Zoom factor:" +msgstr "Συντελεστής μεγέθυνσης" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:100 +msgid "Zoom speed:" +msgstr "Ταχύτητα ζουμ:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:103 +msgid "Weapon settings..." +msgstr "Ρυθμίσεις όπλων..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:110 +msgid "Crosshair:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:111 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:139 +msgid "Per weapon" +msgstr "Ανά όπλο" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:130 +msgid "Crosshair size:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:134 +msgid "Crosshair alpha:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:138 +msgid "Crosshair color:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:140 +msgid "By health" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:143 +msgid "Custom" +msgstr "Προσαρμογή" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:148 +msgid "Enable center dot" +msgstr "Ενεργοποίηση κεντρικής κουκκίδας" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:151 +msgid "Size:" +msgstr "Μέγεθος:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:158 +msgid "Hit test:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:159 +msgid "HTST^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:160 +msgid "TrueAim" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:161 +msgid "Enemies" +msgstr "Εχθροί" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:164 +msgid "Waypoints setup..." +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:169 +msgid "Enter HUD editor" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:174 +msgid "Force models:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:175 +msgid "MDL^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:176 +msgid "MDL^Custom" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:177 +msgid "MDL^All" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:180 +msgid "Disable gore effects" +msgstr "Απενεργοποίηση αιματηρών εφέ" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:182 +msgid "Gibs:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:184 +msgid "GIBS^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:185 +msgid "GIBS^Few" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:186 +msgid "GIBS^Many" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:187 +msgid "GIBS^Lots" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:191 +msgid "Damage splash:" +msgstr "" + +#: qcsrc/menu/xonotic/cvarlist.c:85 +msgid "will be saved to config.cfg" +msgstr "" + +#: qcsrc/menu/xonotic/cvarlist.c:87 +msgid "will not be saved" +msgstr "" + +#: qcsrc/menu/xonotic/cvarlist.c:89 +msgid "private" +msgstr "προσωπικές" + +#: qcsrc/menu/xonotic/cvarlist.c:91 +msgid "engine setting" +msgstr "" + +#: qcsrc/menu/xonotic/cvarlist.c:93 +msgid "read only" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:4 +msgid "Centerprint" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:23 +msgid "Message duration:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:27 +msgid "Fade time:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:31 +msgid "Flip messages order" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:33 +msgid "Text alignment:" +msgstr "Ευθυγράμμιση κειμένου" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:36 +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:29 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:40 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:40 +msgid "Left" +msgstr "Αριστερά" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:37 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:50 +msgid "Center" +msgstr "Στο κέντρο" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:38 +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:41 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:41 +msgid "Right" +msgstr "Δεξιά" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:41 +msgid "Font scale:" +msgstr "Μέγεθος γραμματοσειράς:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:4 +msgid "Score Panel" +msgstr "Πίνακας Βαθμολογίας" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:22 +msgid "Score:" +msgstr "Βαθμολογία:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:25 +msgid "Rankings:" +msgstr "Κατατάξεις:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:26 +msgid "Off" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:27 +msgid "And me" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:28 +msgid "Pure" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:4 +msgid "Timer Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:22 +msgid "Timer:" +msgstr "Χρονόμετρο:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:25 +msgid "Show elapsed time" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:5 +msgid "Map Information" +msgstr "Πληροφορίες Χάρτη" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "Full item placement" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "MinstaGib only" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:78 +msgid "Title:" +msgstr "Τίτλος" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:84 +msgid "Author:" +msgstr "Δημιουργός:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:90 +msgid "Features:" +msgstr "Χαρακτηριστικά:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:95 +msgid "Game types:" +msgstr "Τύποι παιχνιδιού:" + +# Just doesn't sound right... would prefer a noun rather than a verb +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:121 +#, fuzzy +msgid "MAP^Play" +msgstr "MAP^Παίξε" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:6 +msgid "Advanced server settings" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:25 +msgid "Game settings:" +msgstr "Ρυθμίσεις παιχνιδιού:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:28 +msgid "Allow spectating" +msgstr "Επιτρέπεται η θέαση" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:31 +msgid "Spawn shield:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:36 +msgid "Game speed:" +msgstr "Ταχύτητα παιχνιδιού" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:40 +msgid "Teamplay settings:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:43 +msgid "Friendly fire scale:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:47 +msgid "Virtual friendly fire (effect only)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:50 +msgid "Friendly fire penalty:" +msgstr "Ποινή φιλικής πυράς:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:54 +msgid "Virtual penalty (effect only)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:57 +msgid "Teams:" +msgstr "Ομάδες:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:66 +msgid "Map voting:" +msgstr "Ψηφοφορία για χάρτη:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:68 +msgid "No voting" +msgstr "Χωρίς ψήφοφορία" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:69 +msgid "2 choices" +msgstr "2 επιλογές" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:70 +msgid "3 choices" +msgstr "3 επιλογές" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:71 +msgid "4 choices" +msgstr "4 επιλογές" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:72 +msgid "5 choices" +msgstr "5 επιλογές" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:73 +msgid "6 choices" +msgstr "6 επιλογές" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:74 +msgid "7 choices" +msgstr "7 επιλογές" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:75 +msgid "8 choices" +msgstr "8 επιλογές" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:76 +msgid "9 choices" +msgstr "9 επιλογές" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:79 +msgid "Simple majority wins vcall" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:271 +#, c-format +msgid "Received HTTP request data for an invalid id %d.\n" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:286 +#, c-format +msgid "error receiving update notification: status is %d\n" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:291 +msgid "error: received HTML instead of an update notification\n" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:296 +msgid "error: received carriage returns from update notification server\n" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:317 +#, c-format +msgid "" +"Update can be downloaded at:\n" +"%s\n" +msgstr "" +"Μπορεί να γίνει λήψη της αναβάθμισης στις:\n" +"%s\n" + +#: qcsrc/menu/xonotic/util.qc:340 +msgid "Autogenerating mapinfo for newly added maps..." +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:370 +#, c-format +msgid "^1%s TEST BUILD" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:428 +#, c-format +msgid "Update to %s now!" +msgstr "Αναβαθμίστε στην έκδοση %s τώρα!" + +#: qcsrc/menu/xonotic/util.qc:513 +msgid "" +"^1ERROR: Texture compression is required but not supported.\n" +"^1Expect visual problems.\n" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:535 +msgid "Arena" +msgstr "Αρένα" + +#: qcsrc/menu/xonotic/util.qc:536 +msgid "Assault" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:537 +msgid "Capture The Flag" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:538 +msgid "Clan Arena" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:539 +msgid "Deathmatch" +msgstr "" + +# About as cool as I could make it sound +#: qcsrc/menu/xonotic/util.qc:540 +msgid "Domination" +msgstr "Κυριαρχία" + +#: qcsrc/menu/xonotic/util.qc:541 +msgid "Freeze Tag" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:542 +msgid "Keepaway" +msgstr "" + +# Could be improved +#: qcsrc/menu/xonotic/util.qc:543 +msgid "Key Hunt" +msgstr "Κυνήγι για κλειδιά" + +#: qcsrc/menu/xonotic/util.qc:544 +msgid "Last Man Standing" +msgstr "" + +# See comments on "Nex" +#: qcsrc/menu/xonotic/util.qc:545 +msgid "Nexball" +msgstr "Θανατόμπαλα" + +#: qcsrc/menu/xonotic/util.qc:546 +msgid "Onslaught" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:547 +msgid "Race" +msgstr "Αγώνας" + +#: qcsrc/menu/xonotic/util.qc:548 +msgid "Race CTS" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:549 +msgid "Runematch" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:550 +msgid "Team Deathmatch" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:569 +#, c-format +msgid "@!#%'n Tuba Throwing" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:589 +#: qcsrc/menu/xonotic/util.qc:605 +#: qcsrc/menu/xonotic/util.qc:614 +#: qcsrc/menu/xonotic/util.qc:622 +#: qcsrc/menu/xonotic/util.qc:634 +msgid "Default" +msgstr "Προεπιλογή" + +#: qcsrc/menu/xonotic/util.qc:600 +msgid "Use default" +msgstr "Χρήση προεπιλογής" + +#: qcsrc/menu/xonotic/util.qc:620 +msgid "Team Color:" +msgstr "Χρώμα Ομαδάς:" + +# Functional, but could be improved as far as including no models at all goes in the meaning of the sentence +#: qcsrc/menu/xonotic/playermodel.c:174 +msgid "<no model found>" +msgstr "<μοντέλο δεν βρέθηκε>" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:4 +msgid "Ammo Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:22 +msgid "Ammunition display:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:25 +msgid "Show only current ammo type" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:28 +msgid "Align icon:" +msgstr "Ευθυγράμμιση εικονιδίου:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:6 +msgid "Weapon settings" +msgstr "Ρυθμίσεις όπλων" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:29 +msgid "Weapon priority list:" +msgstr "" + +# Would prefer υψηλότερη/χαμηλότερη (higher/lower) but may be too long +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:34 +msgid "Up" +msgstr "Πάνω" + +# Would prefer υψηλότερη/χαμηλότερη (higher/lower) but may be too long +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:37 +msgid "Down" +msgstr "Κάτω" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:41 +msgid "Use priority list for weapon cycling" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:43 +msgid "Auto switch weapons on pickup" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:45 +msgid "Draw 1st person weapon model" +msgstr "Εμφάνιση όπλου σε πρώτο πρόσωπο" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:55 +msgid "Flip view horizontally" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:38 +msgid "Quality preset:" +msgstr "Προκαθορισμένη ποιότητα:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:41 +msgid "PRE^OMG!" +msgstr "PRE^Όπα!" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:42 +msgid "PRE^Low" +msgstr "PRE^Χαμηλή" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:43 +msgid "PRE^Medium" +msgstr "PRE^Μεσαία" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:44 +msgid "PRE^Normal" +msgstr "PRE^Κανονική" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:45 +msgid "PRE^High" +msgstr "PRE^Υψηλή" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:46 +msgid "PRE^Ultra" +msgstr "PRE^Ακραία" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:48 +msgid "PRE^Ultimate" +msgstr "PRE^Μέγιστη" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:52 +msgid "Geometry detail:" +msgstr "Γεομετρική λεπτομέρεια:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:54 +#, fuzzy +msgid "DET^Lowest" +msgstr "DET^Χαμηλότατη" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:55 +msgid "DET^Low" +msgstr "DET^Χαμηλή" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:56 +msgid "DET^Normal" +msgstr "DET^" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:57 +msgid "DET^Good" +msgstr "DET^Καλή" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:58 +msgid "DET^Best" +msgstr "DET^Καλύτερη" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:59 +msgid "DET^Insane" +msgstr "DET^Τρομερή" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:62 +msgid "Antialiasing:" +msgstr "Εξομάλυνση:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:64 +msgid "AA^Disabled" +msgstr "AA^Απενεργοποιημένη" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:65 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:103 +msgid "2x" +msgstr "2x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:66 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:104 +msgid "4x" +msgstr "4x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:70 +msgid "Texture resolution:" +msgstr "Ανάλυση υφής:" + +# Taking the piss a bit... +#: qcsrc/menu/xonotic/dialog_settings_effects.c:73 +msgid "RES^Leet" +msgstr "RES^Ακραίος χαμηλή" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:74 +msgid "RES^Lowest" +msgstr "RES^Χαμηλότερή" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:75 +msgid "RES^Low" +msgstr "RES^Χαμηλή" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:76 +msgid "RES^Normal" +msgstr "RES^Κανονική" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:77 +msgid "RES^Good" +msgstr "RES^Καλή" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:78 +msgid "RES^Best" +msgstr "RES^Καλύτερη" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:91 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:94 +msgid "Avoid lossy texture compression" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:100 +msgid "Anisotropy:" +msgstr "Ανισοτροπία:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:102 +msgid "ANISO^Disabled" +msgstr "ANISO^Απενεργοποίηση" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:105 +msgid "8x" +msgstr "8x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:106 +msgid "16x" +msgstr "16x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:110 +msgid "Particle quality:" +msgstr "Ποιότητα σωματιδίων:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:113 +msgid "Particle distance:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:117 +msgid "Decals" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:118 +msgid "Decals on models" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:122 +msgid "Distance:" +msgstr "Απόσταση:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:128 +msgid "Time:" +msgstr "Χρόνος:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:134 +msgid "Use lightmaps" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:135 +msgid "Deluxe mapping" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:137 +msgid "Gloss" +msgstr "Γυαλάδα" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:140 +msgid "Offset mapping" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:142 +msgid "Relief mapping" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:145 +msgid "Reflections:" +msgstr "Αντανακλάσεις:" + +# Masculine/feminine? +#: qcsrc/menu/xonotic/dialog_settings_effects.c:148 +msgid "Blurred" +msgstr "Θολομένο" + +# Masculine/feminine? +#: qcsrc/menu/xonotic/dialog_settings_effects.c:149 +msgid "REFL^Good" +msgstr "REFL^Καλό" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:150 +#, fuzzy +msgid "Sharp" +msgstr "Οξύτητα" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:155 +msgid "Show surfaces" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:157 +msgid "No dynamic lighting" +msgstr "Χωρίς δυναμικό φωτισμό" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:159 +msgid "Flash blend approximation" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:161 +msgid "Realtime dynamic lighting" +msgstr "Δυναμικός φώτισμος σε πραγματικό χρόνο" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:162 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:166 +msgid "Shadows" +msgstr "Σκιές" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:165 +msgid "Realtime world lighting" +msgstr "Φωτισμός κόσμου σε πραγματικό χρόνο" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:170 +msgid "Use normal maps" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:172 +#, fuzzy +msgid "Soft shadows" +msgstr "Μαλακές σκιές" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:175 +msgid "Coronas" +msgstr "Στέμματα" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:176 +msgid "Use Occlusion Queries" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:178 +msgid "Bloom" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:180 +msgid "High Dynamic Range (HDR)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:184 +msgid "Motion blur:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:189 +msgid "Blur and sharpen postprocessing" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:26 +msgid "Client-side movement prediction" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:30 +msgid "Show netgraph" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:33 +msgid "Network speed:" +msgstr "Τάχυτητα δικτύου:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:35 +msgid "56k" +msgstr "56k" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:36 +msgid "ISDN" +msgstr "ISDN" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:37 +msgid "Slow ADSL" +msgstr "Αργό ADSL" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:38 +msgid "Fast ADSL" +msgstr "Γρήγορο ADSL" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:39 +msgid "Broadband" +msgstr "Ευρής ζώνης" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:42 +msgid "Input packets/s:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:46 +msgid "HTTP downloads:" +msgstr "Λήψεις HTTP:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:49 +msgid "Downloads:" +msgstr "Λήψεις:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:53 +msgid "Speed (kB/s):" +msgstr "Ταχύτητα (kB/s):" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:57 +msgid "Client UDP port:" +msgstr "" + +#: qcsrc/menu/xonotic/serverlist.c:185 +msgid "Remove" +msgstr "Αφαίρεση" + +# I don't know the context of this. +#: qcsrc/menu/xonotic/serverlist.c:187 +#, fuzzy +msgid "Bookmark" +msgstr "Προσθήκη στους σελιδοδείκτες" + +#: qcsrc/menu/xonotic/serverlist.c:527 +msgid "Ping" +msgstr "" + +#: qcsrc/menu/xonotic/serverlist.c:528 +msgid "Host name" +msgstr "Όνομα διακομιστή" + +#: qcsrc/menu/xonotic/serverlist.c:529 +msgid "Map" +msgstr "Χάρτης" + +#: qcsrc/menu/xonotic/serverlist.c:530 +msgid "Type" +msgstr "Τύπος" + +#: qcsrc/menu/xonotic/serverlist.c:531 +msgid "Players" +msgstr "Παίκτες" + +#: qcsrc/menu/xonotic/maplist.c:278 +msgid "Huh? Can't play this (m is NULL). Refiltering so this won't happen again.\n" +msgstr "" + +#: qcsrc/menu/xonotic/maplist.c:286 +#, c-format +msgid "%s's Xonotic Server" +msgstr "Διακομιστής Xonotic του %s" + +#: qcsrc/menu/xonotic/maplist.c:291 +msgid "Huh? Can't play this (invalid game type). Refiltering so this won't happen again.\n" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:4 +msgid "Demo" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:28 +msgid "Record demos while playing" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:43 +msgid "Timedemo" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:46 +msgid "DEMO^Play" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:4 +msgid "Powerups Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:22 +msgid "Enable status bar" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:24 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:24 +msgid "Status bar alignment:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:42 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:42 +msgid "Inward" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:43 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:43 +msgid "Outward" +msgstr "" + +# Στοίχιση; +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:37 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:37 +msgid "Icon alignment:" +msgstr "Ευθυγράμμιση εικονιδίων:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:45 +msgid "Flip strength and shield positions" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:27 +msgid "Master:" +msgstr "Κύρια ένταση ήχου:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:33 +msgid "Music:" +msgstr "Μουσική" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:41 +msgid "VOL^Ambient:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:48 +msgid "Info:" +msgstr "Πληροφορίες:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:55 +msgid "Items:" +msgstr "Αντικείμενα:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:62 +msgid "Pain:" +msgstr "Πόνος:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:69 +msgid "Player:" +msgstr "Παίκτης:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:76 +msgid "Shots:" +msgstr "Πυροβολισμοί:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:83 +msgid "Voice:" +msgstr "Φωνή:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:91 +msgid "Weapons:" +msgstr "Όπλα:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:98 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:156 +msgid "Frequency:" +msgstr "Συχνότητα:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:100 +msgid "8 kHz" +msgstr "8 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:101 +msgid "11.025 kHz" +msgstr "11.025 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:102 +msgid "16 kHz" +msgstr "16 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:103 +msgid "22.05 kHz" +msgstr "22.05 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:104 +msgid "24 kHz" +msgstr "24 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:105 +msgid "32 kHz" +msgstr "32 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:106 +msgid "44.1 kHz" +msgstr "44.1 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:107 +msgid "48 kHz" +msgstr "48 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:110 +msgid "Channels:" +msgstr "Κανάλια:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:112 +msgid "Mono" +msgstr "Μονοφωνικό" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:113 +msgid "Stereo" +msgstr "Στερεφωνικό" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:114 +msgid "2.1" +msgstr "2.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:115 +msgid "4" +msgstr "4" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:116 +msgid "5" +msgstr "5" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:117 +msgid "5.1" +msgstr "5.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:118 +msgid "6.1" +msgstr "6.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:119 +msgid "7.1" +msgstr "7.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:123 +msgid "Swap Stereo" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:127 +#, fuzzy +msgid "Headphone friendly mode" +msgstr "Φιλικά με ακουστικά" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:131 +msgid "Spatial voices:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:132 +msgid "VOCS^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:133 +msgid "VOCS^Taunts" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:134 +msgid "VOCS^All" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:137 +msgid "Taunt range:" +msgstr "Εμβέλεια κοροϊδίας" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:140 +msgid "RNG^Very short" +msgstr "RNG^Πολύ μικρή" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:141 +msgid "RNG^Short" +msgstr "RNG^Μικρή" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:142 +msgid "RNG^Normal" +msgstr "RNG^Μεσαία" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:143 +msgid "RNG^Long" +msgstr "RNG^Μακριά" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:144 +msgid "RNG^Full" +msgstr "RNG^Πλήρη" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:151 +msgid "Automatic taunts" +msgstr "Αυτόματες κοροϊδίες" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:160 +msgid "Time warning:" +msgstr "Προειδοποίηση χρόνου:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:162 +msgid "WRN^None" +msgstr "WRN^Καμιά" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:163 +msgid "1 minute" +msgstr "1 λεπτό" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:164 +msgid "5 minutes" +msgstr "5 λεπτά" + +# ??? +#: qcsrc/menu/xonotic/dialog_settings_audio.c:165 +#, fuzzy +msgid "WRN^Both" +msgstr "WRN^Και οι δυο" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:168 +msgid "Hit indicator" +msgstr "Ένδειξη χτυπήματος" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:170 +msgid "Menu sounds" +msgstr "Ήχοι μενού" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:4 +msgid "Multiplayer" +msgstr "Πολλαπλοί παίκτες" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:18 +msgid "Servers" +msgstr "Διακομιστές" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:20 +msgid "Demos" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:4 +msgid "Health/Armor Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:45 +msgid "Flip health and armor positions" +msgstr "" + +#: qcsrc/server/w_fireball.qc:2 +#, fuzzy +msgid "Fireball" +msgstr "Φλογοβολίδα" + +#: qcsrc/server/w_fireball.qc:417 +#, c-format +msgid "%s forgot about some firemine" +msgstr "" + +#: qcsrc/server/w_fireball.qc:419 +#: qcsrc/server/w_hlac.qc:240 +#, c-format +msgid "%s should have used a smaller gun" +msgstr "%s θα έπρεπε να χρησιμοποιούσε μικρότερο όπλο" + +#: qcsrc/server/w_fireball.qc:426 +#, c-format +msgid "%s tried to catch %s's firemine" +msgstr "" + +#: qcsrc/server/w_fireball.qc:428 +#, c-format +msgid "%s fatefully ignored %s's firemine" +msgstr "" + +#: qcsrc/server/w_fireball.qc:435 +#, c-format +msgid "%s could not hide from %s's fireball" +msgstr "ο %s δεν μπορούσε να κρυφτεί από την φλογοβολίδα του %s" + +#: qcsrc/server/w_fireball.qc:437 +#, c-format +msgid "%s saw the pretty lights of %s's fireball" +msgstr "ο %s θαύμασε την ομορφιά της φλογοβολίδας του %s" + +#: qcsrc/server/w_fireball.qc:440 +#, c-format +msgid "%s got too close to %s's fireball" +msgstr "ο %s πλησίασε τη φλογοβολίδα του %s πάρα πολύ" + +#: qcsrc/server/w_fireball.qc:442 +#, c-format +msgid "%s tasted %s's fireball" +msgstr "ο %s γεύστηκε τη φλόγα του %s " + +# Presumably "Nex" comes from the Latin word which means violent death +#: qcsrc/server/w_nex.qc:2 +msgid "Nex" +msgstr "Θάνατος" + +#: qcsrc/server/w_nex.qc:253 +#: qcsrc/server/w_shotgun.qc:215 +#: qcsrc/server/w_uzi.qc:317 +#: qcsrc/server/w_minstanex.qc:293 +#, c-format +msgid "%s is now thinking with portals" +msgstr "" + +#: qcsrc/server/w_nex.qc:255 +#: qcsrc/server/w_minstanex.qc:295 +#, c-format +msgid "%s has been vaporized by %s" +msgstr "ο %s αεροποιήθηκε από τον %s" + +#: qcsrc/server/w_laser.qc:2 +msgid "Laser" +msgstr "Λέιζερ" + +#: qcsrc/server/w_laser.qc:311 +#, c-format +msgid "%s lasered themself to hell" +msgstr "" + +#: qcsrc/server/w_laser.qc:315 +#, c-format +msgid "%s was cut in half by %s's gauntlet" +msgstr "" + +#: qcsrc/server/w_laser.qc:317 +#, c-format +msgid "%s was lasered to death by %s" +msgstr "" + +#: qcsrc/server/w_shotgun.qc:2 +msgid "Shotgun" +msgstr "Καραμπίνα" + +#: qcsrc/server/w_shotgun.qc:219 +#, c-format +msgid "%2$s ^7slapped %1$s ^7around a bit with a large ^2shotgun" +msgstr "" + +#: qcsrc/server/w_shotgun.qc:221 +#, c-format +msgid "%s was gunned by %s" +msgstr "" + +#: qcsrc/server/w_uzi.qc:2 +msgid "Machine Gun" +msgstr "Πολυβόλο" + +#: qcsrc/server/w_uzi.qc:321 +#: qcsrc/server/w_rifle.qc:258 +#, c-format +msgid "%s was sniped by %s" +msgstr "" + +#: qcsrc/server/w_uzi.qc:323 +#, c-format +msgid "%s was riddled full of holes by %s" +msgstr "" + +#: qcsrc/server/w_minstanex.qc:2 +msgid "MinstaNex" +msgstr "" + +#: qcsrc/server/w_electro.qc:2 +msgid "Electro" +msgstr "" + +#: qcsrc/server/w_electro.qc:574 +#, c-format +msgid "%s could not remember where they put plasma" +msgstr "" + +#: qcsrc/server/w_electro.qc:576 +#, c-format +msgid "%s played with plasma" +msgstr "ο %s έπαιξε με πλάσμα" + +#: qcsrc/server/w_electro.qc:583 +#, c-format +msgid "%s just noticed %s's blue ball" +msgstr "ο %s μόλις πρόσεξε τη μπλε μπάλα του %s" + +#: qcsrc/server/w_electro.qc:585 +#, c-format +msgid "%s got in touch with %s's blue ball" +msgstr "" + +#: qcsrc/server/w_electro.qc:590 +#, c-format +msgid "%s felt the electrifying air of %s's combo" +msgstr "" + +#: qcsrc/server/w_electro.qc:592 +#, c-format +msgid "%s got too close to %s's blue beam" +msgstr "ο %s πλησίασε τη μπλε ακτίνα του %s πάρα πολύ" + +#: qcsrc/server/w_electro.qc:594 +#, c-format +msgid "%s was blasted by %s's blue beam" +msgstr "" + +#: qcsrc/server/w_tuba.qc:2 +#, c-format +msgid "@!#%'n Tuba" +msgstr "" + +#: qcsrc/server/w_tuba.qc:252 +#, c-format +msgid "%s hurt his own ears with the @!#%%'n Tuba" +msgstr "" + +#: qcsrc/server/w_tuba.qc:256 +#, c-format +msgid "%s died of %s's great playing on the @!#%%'n Tuba" +msgstr "" + +#: qcsrc/server/w_porto.qc:2 +msgid "Port-O-Launch" +msgstr "" + +#: qcsrc/server/w_porto.qc:296 +#: qcsrc/server/w_hook.qc:266 +#, c-format +msgid "%s did the impossible" +msgstr "ο %s έκανε το απίθανο" + +#: qcsrc/server/w_porto.qc:298 +#, c-format +msgid "%s felt %s doing the impossible to him" +msgstr "ο %s ένιωσε τον %s να κάνει το απίθανο σ'αυτόν" + +#: qcsrc/server/w_hagar.qc:2 +msgid "Hagar" +msgstr "" + +#: qcsrc/server/w_hagar.qc:395 +#: qcsrc/server/w_seeker.qc:655 +#, c-format +msgid "%s played with tiny rockets" +msgstr "ο %s έπαιξε με μικρές ρουκέτες" + +# Too long. +#: qcsrc/server/w_hagar.qc:399 +#, fuzzy, c-format +msgid "%s hoped %s's missiles wouldn't bounce" +msgstr "ο %s έλπιζε ότι οι πύραυλοι του %s δεν θα αναπηδούσε" + +#: qcsrc/server/w_hagar.qc:401 +#: qcsrc/server/w_seeker.qc:661 +#, c-format +msgid "%s was pummeled by %s" +msgstr "" + +#: qcsrc/server/w_crylink.qc:2 +msgid "Crylink" +msgstr "" + +#: qcsrc/server/w_crylink.qc:666 +#, c-format +msgid "%s succeeded at self-destructing themself with the Crylink" +msgstr "" + +#: qcsrc/server/w_crylink.qc:671 +#, c-format +msgid "%s could not hide from %s's Crylink" +msgstr "" + +#: qcsrc/server/w_crylink.qc:673 +#, c-format +msgid "%s was too close to %s's Crylink" +msgstr "" + +#: qcsrc/server/w_crylink.qc:675 +#, c-format +msgid "%s took a close look at %s's Crylink" +msgstr "" + +#: qcsrc/server/w_rocketlauncher.qc:2 +msgid "Rocket Launcher" +msgstr "Ρουκετοεκτοξευτήρας" + +#: qcsrc/server/w_rocketlauncher.qc:501 +#: qcsrc/server/w_minelayer.qc:523 +#, c-format +msgid "%s exploded" +msgstr "ο %s εκκράγη" + +#: qcsrc/server/w_rocketlauncher.qc:505 +#, c-format +msgid "%s got too close to %s's rocket" +msgstr "ο %s πλησίασε τη ρουκέτα του %s ίσως πολύ" + +#: qcsrc/server/w_rocketlauncher.qc:507 +#, c-format +msgid "%s almost dodged %s's rocket" +msgstr "ο %s σχεδόν απέφυγε τη ρουκέτα του %s" + +#: qcsrc/server/w_rocketlauncher.qc:509 +#, c-format +msgid "%s ate %s's rocket" +msgstr "ο %s έφαγε τη ρουκέτα του %s" + +# Probably the best possible translation +#: qcsrc/server/w_hook.qc:2 +#, fuzzy +msgid "Grappling Hook" +msgstr "Δαγκάνα" + +#: qcsrc/server/w_hook.qc:268 +#, c-format +msgid "%s has run into %s's gravity bomb" +msgstr "" + +#: qcsrc/server/w_minelayer.qc:2 +msgid "Mine Layer" +msgstr "Ναρκοθέτης" + +#: qcsrc/server/w_minelayer.qc:527 +#, c-format +msgid "%s got too close to %s's mine" +msgstr "" + +#: qcsrc/server/w_minelayer.qc:529 +#, c-format +msgid "%s almost dodged %s's mine" +msgstr "ο %s σχεδόν απέφυγε τη νάρκη του %s" + +#: qcsrc/server/w_minelayer.qc:531 +#, c-format +msgid "%s stepped on %s's mine" +msgstr "ο %s πάτησε τη νάρκη του %s" + +#: qcsrc/server/w_rifle.qc:2 +msgid "Rifle" +msgstr "Τουφέκι" + +#: qcsrc/server/w_rifle.qc:233 +#, c-format +msgid "%s shot themself automatically" +msgstr "" + +#: qcsrc/server/w_rifle.qc:235 +#, c-format +msgid "%s sniped themself somehow" +msgstr "" + +#: qcsrc/server/w_rifle.qc:242 +#, c-format +msgid "%s failed to hide from %s's bullet hail" +msgstr "" + +#: qcsrc/server/w_rifle.qc:244 +#, fuzzy, c-format +msgid "%s died in %s's bullet hail" +msgstr "ο %s πέθανε στο χάλαζι σφερών του %s" + +#: qcsrc/server/w_rifle.qc:251 +#, c-format +msgid "%s failed to hide from %s's rifle" +msgstr "" + +#: qcsrc/server/w_rifle.qc:256 +#, c-format +msgid "%s got hit in the head by %s" +msgstr "" + +#: qcsrc/server/w_seeker.qc:2 +msgid "T.A.G. Seeker" +msgstr "" + +#: qcsrc/server/w_seeker.qc:659 +#, c-format +msgid "%s was tagged by %s" +msgstr "" + +# Somewhat archaic in my opinion, not cool enough for Xonotic (it starts with an X for God's sake!) +#: qcsrc/server/w_grenadelauncher.qc:2 +#, fuzzy +msgid "Mortar" +msgstr "Ολμοβόλο" + +#: qcsrc/server/w_grenadelauncher.qc:383 +#, c-format +msgid "%s tried out his own grenade" +msgstr "ο %s δοκίμασε την ίδια του τη χειροβομβίδα" + +#: qcsrc/server/w_grenadelauncher.qc:385 +#, c-format +msgid "%s detonated" +msgstr "ο %s ανατινάχθηκε" + +#: qcsrc/server/w_grenadelauncher.qc:391 +#, c-format +msgid "%s didn't see %s's grenade" +msgstr "ο %s δεν είδε τη χειροβομβίδα του %s" + +#: qcsrc/server/w_grenadelauncher.qc:393 +#, c-format +msgid "%s almost dodged %s's grenade" +msgstr "ο %s σχεδόν απέφυγε τη χειροβομβίδα του %s" + +#: qcsrc/server/w_grenadelauncher.qc:395 +#, c-format +msgid "%s ate %s's grenade" +msgstr "ο %s έφαγε τη χειροβομβίδα του %s" + +# Tried to make it sound as bad-ass as I could... +#: qcsrc/server/w_hlac.qc:2 +msgid "Heavy Laser Assault Cannon" +msgstr "Εξειδικευμένο Βαρύ Πυροβόλο Λείζερ" + +#: qcsrc/server/w_hlac.qc:242 +#, c-format +msgid "%s was cut down by %s" +msgstr "" + diff --git a/menu.dat.es.po b/menu.dat.es.po new file mode 100644 index 0000000000..65636cfccf --- /dev/null +++ b/menu.dat.es.po @@ -0,0 +1,2886 @@ +# Xonotic Menu +# Copyright (C) 2011 Team Xonotic +# This file is distributed under the same license as the Xonotic package. +# Rodrigo Mouton Laudin <ratogenesis@gmail.com>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: Xonotic 0.1preview\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-09-02 07:51+0200\n" +"Author: Rodrigo Mouton Laudin <ratogenesis@gmail.com>\n" +"Last-Translator: mand1nga <mand1nga@xonotic.org>\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"PO-Revisión-Date: 2011-03-24 19:40+0100\n" + +#: qcsrc/common/mapinfo.qc:1092 qcsrc/menu/xonotic/skinlist.c:163 +#, c-format +msgid "%s: %s" +msgstr "%s: %s" + +#: qcsrc/menu/gamecommand.qc:47 +#, c-format +msgid "error: status is %d\n" +msgstr "error: estado es %d\n" + +#: qcsrc/menu/gamecommand.qc:65 +msgid "Usage: menu_cmd command..., where possible commands are:\n" +msgstr "Uso: menu_cmd commando..., donde los posibles comandos son:\n" + +#: qcsrc/menu/gamecommand.qc:66 +msgid " sync - reloads all cvars on the current menu page\n" +msgstr " sync - recarga todas las cvar en el menu actual\n" + +#: qcsrc/menu/gamecommand.qc:67 +msgid " directmenu ITEM - select a menu item as main item\n" +msgstr " directmenu ITEM - selecciona un item del menu como principal\n" + +#: qcsrc/menu/gamecommand.qc:193 +msgid "error creating curl handle\n" +msgstr "error creando el manejador curl\n" + +#: qcsrc/menu/gamecommand.qc:239 +msgid "Invalid command. For a list of supported commands, try menu_cmd help.\n" +msgstr "" +"Comando no válido. Para una lista de comandos soportados, escriba menu_cmd " +"help\n" + +#: qcsrc/menu/item/gecko.c:49 +msgid "Browser not initialized!" +msgstr "¡Navegador no inicializado!" + +#: qcsrc/menu/item/label.c:63 +#, c-format +msgid "NOTE: label text %s too wide for label, condensed by factor %f\n" +msgstr "" +"NOTA: texto %s demasiado largo para la etiqueta, condensada por factor %f\n" + +#: qcsrc/menu/item/listbox.c:300 +#, c-format +msgid "Item %d" +msgstr "Item %d" + +#: qcsrc/menu/item/slider.c:64 +#, c-format +msgid "%d (%s)" +msgstr "%d (%s)" + +#: qcsrc/menu/item/textslider.c:29 qcsrc/menu/item/textslider.c:31 +msgid "custom" +msgstr "Personalizado" + +#: qcsrc/menu/menu.qc:29 +#, c-format +msgid "^4MQC Build information: ^1%s\n" +msgstr "^4MQC Información de compilación/build %s\n" + +#: qcsrc/menu/xonotic/campaign.c:284 +#: qcsrc/menu/xonotic/dialog_singleplayer.c:134 +msgid "???" +msgstr "???" + +#: qcsrc/menu/xonotic/campaign.c:285 +#, c-format +msgid "Level %d: %s" +msgstr "Nivel %d: %s" + +#: qcsrc/menu/xonotic/cvarlist.c:85 +msgid "will be saved to config.cfg" +msgstr "será guardado en config.cfg" + +#: qcsrc/menu/xonotic/cvarlist.c:87 +msgid "will not be saved" +msgstr "no será guardado" + +#: qcsrc/menu/xonotic/cvarlist.c:89 +msgid "private" +msgstr "privado" + +#: qcsrc/menu/xonotic/cvarlist.c:91 +msgid "engine setting" +msgstr "configuración del motor" + +#: qcsrc/menu/xonotic/cvarlist.c:93 +msgid "read only" +msgstr "sólo lectura" + +#: qcsrc/menu/xonotic/dialog_credits.c:5 +msgid "Credits" +msgstr "Créditos" + +#: qcsrc/menu/xonotic/dialog_credits.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:269 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:41 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:57 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:61 +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:21 +msgid "OK" +msgstr "OK" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:4 +msgid "Welcome" +msgstr "Bienvenido" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:33 +msgid "" +"Welcome to Xonotic, please select your language preference and enter your " +"player name to get started. You can change these options later through the " +"menu system." +msgstr "" +"Bienvenido a Xonotic, por favor seleccióne su lenguaje preferido y luego " +"ingrese su nombre de jugador. Estas opciones pueden ser modificadas luego " +"utilizando el menú de configuración" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:38 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:35 +msgid "Text language:" +msgstr "Lenguaje:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:47 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:40 +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:39 +msgid "Name:" +msgstr "Nombre:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:69 +msgid "Save settings" +msgstr "Guardar configuración" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:4 +msgid "Ammo Panel" +msgstr "Panel de munición" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:22 +msgid "Ammunition display:" +msgstr "Pantalla de munición:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:25 +msgid "Show only current ammo type" +msgstr "Mostrar sólo la munición actual" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:28 +msgid "Align icon:" +msgstr "Alinear ícono" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:29 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:36 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:40 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:40 +msgid "Left" +msgstr "Izquierda" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:38 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:41 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:41 +msgid "Right" +msgstr "Derecha" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:4 +msgid "Centerprint" +msgstr "Mensaje centrado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:23 +msgid "Message duration:" +msgstr "Duración del mensaje:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:27 +msgid "Fade time:" +msgstr "Tiempo hasta desaparecer:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:31 +msgid "Flip messages order" +msgstr "Intercambiar orden de mensajes" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:33 +msgid "Text alignment:" +msgstr "Alineado de texto" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:37 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:50 +msgid "Center" +msgstr "Centro" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:41 +msgid "Font scale:" +msgstr "Escala de fuente:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:4 +msgid "Chat Panel" +msgstr "Panel de chat" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:22 +msgid "Chat entries:" +msgstr "Entradas de chat:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:25 +msgid "Chat size:" +msgstr "Tamaño del chat:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:29 +msgid "Chat lifetime:" +msgstr "Tiempo de vida del chat:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:33 +msgid "Chat beep sound" +msgstr "Alarma de chat" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:4 +msgid "Engine Info Panel" +msgstr "Panel de Información del Motor" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:22 +msgid "Engine info:" +msgstr "Información del Motor:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:25 +msgid "Use an averaging algorithm for fps" +msgstr "Usar un algoritmo de promediado de fps" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:4 +msgid "Health/Armor Panel" +msgstr "Panel de Vida/Armadura" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:22 +msgid "Enable status bar" +msgstr "Activar barra de estado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:24 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:24 +msgid "Status bar alignment:" +msgstr "Alineado de barra de estado:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:42 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:42 +msgid "Inward" +msgstr "Dentro" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:43 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:43 +msgid "Outward" +msgstr "Fuera" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:37 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:37 +msgid "Icon alignment:" +msgstr "Alineado de íconos" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:45 +msgid "Flip health and armor positions" +msgstr "Intercambiar la posición de vida y armadura" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:4 +msgid "Info Messages Panel" +msgstr "Panel de Información de Mensajes" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:22 +msgid "Info messages:" +msgstr "Información de mensajes:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:25 +msgid "Flip align" +msgstr "Intercambiar alineamiento" + +#: qcsrc/menu/xonotic/dialog_hudpanel_modicons.c:4 +msgid "Mod Icons Panel" +msgstr "Panel de íconos modificado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:4 +msgid "Notification Panel" +msgstr "Panel de notificaciónes" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:22 +msgid "Notifications:" +msgstr "Notificaciones:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:25 +msgid "Also print notifications to the console" +msgstr "Imprimir tambien notificaciónes en la consola" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:28 +msgid "Flip notify order" +msgstr "Intercambiar orden de notificaciónes" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:31 +msgid "Entry lifetime:" +msgstr "Tiempo de vida de la entrada:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:35 +msgid "Entry fadetime:" +msgstr "Desaparecimento de la entrada:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:4 +msgid "Physics Panel" +msgstr "Panel de Física" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:21 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:21 +msgid "Panel disabled" +msgstr "Panel desactivado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:23 +msgid "Panel enabled" +msgstr "Panel habilitado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:24 +msgid "Panel enabled even observing" +msgstr "Panel activado aún como espectador" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:25 +msgid "Panel enabled only in Race/CTS" +msgstr "Panel activo en modo Race/CTS" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:31 +msgid "Status bar" +msgstr "Barra de estado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:48 +msgid "Left align" +msgstr "Alinear a la izquierda" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:34 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:52 +msgid "Right align" +msgstr "Alinear a la derecha" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:35 +msgid "Inward align" +msgstr "Alineado interior" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:36 +msgid "Outward align" +msgstr "Alineado exterior" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:40 +msgid "Flip speed/acceleration positions" +msgstr "Intercambiar la posición de velocidad/aceleración" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:44 +msgid "Speed:" +msgstr "Velocidad:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:45 +msgid "Include vertical speed" +msgstr "Incluir velocidad vertical" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:56 +msgid "Speed unit:" +msgstr "Unidad de velocidad" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:58 +msgid "qu/s" +msgstr "qu/s" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:59 +msgid "m/s" +msgstr "m/s" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:60 +msgid "km/h" +msgstr "km/h" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:61 +msgid "mph" +msgstr "mph" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:62 +msgid "knots" +msgstr "nudos" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:64 +msgid "Show" +msgstr "Mostrar" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:67 +msgid "Top speed" +msgstr "Máxima velocidad:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:73 +msgid "Acceleration:" +msgstr "Aceleración:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:74 +msgid "Include vertical acceleration" +msgstr "Incluir aceleración vertical" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:4 +msgid "Powerups Panel" +msgstr "Panel de Poderes" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:45 +msgid "Flip strength and shield positions" +msgstr "Intercambiar posición de escudo y fuerza" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:4 +msgid "Pressed Keys Panel" +msgstr "Panel de teclas presionadas" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:22 +msgid "Panel enabled when spectating" +msgstr "Panel activado cuando este espectador" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:23 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:23 +msgid "Panel always enabled" +msgstr "Panel sempre activado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:30 +msgid "Forced aspect:" +msgstr "Forzar aspecto:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_racetimer.c:4 +msgid "Race Timer Panel" +msgstr "Panel de Cronómetro de Carrera" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:4 +msgid "Radar Panel" +msgstr "Panel de Radar" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:22 +msgid "Panel enabled in teamgames" +msgstr "Panel activo en juegos de equipo" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:29 +msgid "Radar:" +msgstr "Radar:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:32 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:43 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:154 +#: qcsrc/menu/xonotic/util.qc:600 +msgid "Alpha:" +msgstr "Transparencia:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:36 +msgid "Rotation:" +msgstr "Rotación:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:38 +msgid "Forward" +msgstr "Al frente" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:39 +msgid "West" +msgstr "Oeste" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:40 +msgid "South" +msgstr "Sul" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:41 +msgid "East" +msgstr "Este" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:42 +msgid "North" +msgstr "Norte" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:46 +msgid "Scale:" +msgstr "Escala:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:50 +msgid "Zoom mode:" +msgstr "Modo de zoom:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:52 +msgid "Zoomed in" +msgstr "Ampliado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:53 +msgid "Zoomed out" +msgstr "Reducido" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:54 +msgid "Always zoomed" +msgstr "Siempre ampliado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:55 +msgid "Never zoomed" +msgstr "Nunca ampliado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:4 +msgid "Score Panel" +msgstr "Panel de Puntos" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:22 +msgid "Score:" +msgstr "Puntaje" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:25 +msgid "Rankings:" +msgstr "Posiciones:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:26 +msgid "Off" +msgstr "Desactivado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:27 +msgid "And me" +msgstr "Y yo" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:28 +msgid "Pure" +msgstr "Puro" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:4 +msgid "Timer Panel" +msgstr "Panel del Temporizador" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:22 +msgid "Timer:" +msgstr "Temporizador:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:25 +msgid "Show elapsed time" +msgstr "Mostrar tiempo pasado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:4 +msgid "Vote Panel" +msgstr "Panel de votos" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:22 +msgid "Alpha after voting:" +msgstr "Transparencia despues del voto:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:4 +msgid "Weapons Panel" +msgstr "Panel de armas" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:24 +msgid "Fade out after:" +msgstr "Desaparecer despues:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:26 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:36 +msgid "Never" +msgstr "Nunca" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:28 +#, c-format +msgid "%ds" +msgstr "%ds" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:32 +msgid "Fade effect:" +msgstr "Efecto de desvanecimento" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:35 +msgid "EF^None" +msgstr "Ninguno" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:36 +msgid "Slide" +msgstr "Corte" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:37 +msgid "Alpha" +msgstr "Transparencia" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:38 +msgid "EF^Both" +msgstr "Ambos" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:42 +msgid "Weapon icons:" +msgstr "íconos de armas" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:45 +msgid "Show weapon ID as:" +msgstr "Mostra ID de arma como:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:46 +msgid "SHOWAS^None" +msgstr "Ninguno" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:47 +msgid "Number" +msgstr "Número" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:48 +msgid "Bind" +msgstr "Lazo" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:51 +msgid "Show Accuracy" +msgstr "Mostrar precision" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:52 +msgid "Show Ammo" +msgstr "Mostrar munición" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:55 +msgid "Ammo bar color:" +msgstr "Color de la barra de munición:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:61 +msgid "Ammo bar alpha:" +msgstr "Transparencia de la barra de munición:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:4 +msgid "Panel HUD Setup" +msgstr "configuración del panel HUD" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:21 +msgid "Panel background defaults:" +msgstr "Panel de fondo por defecto:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:23 qcsrc/menu/xonotic/util.qc:575 +msgid "Background:" +msgstr "Fondo:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:25 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:37 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:52 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:91 qcsrc/menu/xonotic/util.qc:578 +#: qcsrc/menu/xonotic/util.qc:594 qcsrc/menu/xonotic/util.qc:611 +msgid "Disable" +msgstr "Desactivar" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:30 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:77 qcsrc/menu/xonotic/util.qc:583 +msgid "Color:" +msgstr "Color:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:35 qcsrc/menu/xonotic/util.qc:591 +msgid "Border size:" +msgstr "Tamaño de limite:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:50 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:89 +msgid "Team color:" +msgstr "Color del equipo:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:58 qcsrc/menu/xonotic/util.qc:617 +msgid "Test team color in configure mode" +msgstr "Probar color del equipo en modo configuración" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:61 qcsrc/menu/xonotic/util.qc:620 +msgid "Padding:" +msgstr "Relleno:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:68 +msgid "HUD Dock:" +msgstr "Muelle de HUD:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:70 +msgid "DOCK^Disabled" +msgstr "Desactivado" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:71 +msgid "DOCK^Small" +msgstr "Chico" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:72 +msgid "DOCK^Medium" +msgstr "Medio" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:73 +msgid "DOCK^Large" +msgstr "Grande" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:96 +msgid "Grid settings:" +msgstr "Configuración de grilla:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:99 +msgid "Snap panels to grid" +msgstr "Ajustar paneles a la grilla" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:102 +msgid "Grid size:" +msgstr "Tamaño de grilla:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:103 +msgid "X:" +msgstr "X:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:109 +msgid "Y:" +msgstr "Y:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:117 +msgid "Exit setup" +msgstr "Salir de la configuración" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:4 +msgid "Multiplayer" +msgstr "Multijugador" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:18 +msgid "Servers" +msgstr "Servidores" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:19 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:5 +msgid "Create" +msgstr "Crear" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:20 +msgid "Demos" +msgstr "Demos" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:5 +msgid "Player Setup" +msgstr "Jugador" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:34 +msgid "Game type:" +msgstr "Tipo de juego:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:46 +msgid "Match settings:" +msgstr "Configuración del encuentro:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:49 +msgid "Time limit:" +msgstr "Limite de tiempo:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:53 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:61 +msgid "Use map specified default" +msgstr "Usar definicion especifica del mapa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:56 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:155 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:156 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:157 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:161 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:162 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:163 +msgid "Point limit:" +msgstr "Limite de puntos:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:64 +msgid "Player slots:" +msgstr "Slots de Jugadores:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:67 +msgid "Number of bots:" +msgstr "Número de bots:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:71 +msgid "Bot skill:" +msgstr "Dificultad del bot:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:74 +msgid "Botlike" +msgstr "Bot" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:75 +msgid "Beginner" +msgstr "Iniciado" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:76 +msgid "You will win" +msgstr "Ganaras" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:77 +msgid "You can win" +msgstr "Puedes ganar" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:78 +msgid "You might win" +msgstr "Podrias ganar ganar" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:79 +msgid "Advanced" +msgstr "Avanzado" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:80 +msgid "Expert" +msgstr "Experto" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:81 +msgid "Pro" +msgstr "Profesional" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:82 +msgid "Assassin" +msgstr "Asesino" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:83 +msgid "Unhuman" +msgstr "No humano" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:84 +msgid "Godlike" +msgstr "Semi-dios" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:88 +msgid "Mutators..." +msgstr "Mutators..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:97 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:57 +msgid "Advanced settings..." +msgstr "Configuración avanzada..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:104 +msgid "Map list:" +msgstr "Lista de mapas:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:110 +msgid "Select all" +msgstr "Seleccionar todos" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:113 +msgid "Select none" +msgstr "Seleccionar ninguno" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:119 +msgid "Start Multiplayer!" +msgstr "¡Comenzar Multijugador!" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:154 +msgid "Capture limit:" +msgstr "Limite de capturas:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:158 +msgid "Lives:" +msgstr "Vidas:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:159 +msgid "Laps:" +msgstr "Vueltas:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:160 +msgid "Goals:" +msgstr "Metas:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:164 +msgid "Frag limit:" +msgstr "Limite de Frags:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:6 +msgid "Advanced server settings" +msgstr "configuración avanzada del servidor" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:25 +msgid "Game settings:" +msgstr "Configuración del juego:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:28 +msgid "Allow spectating" +msgstr "Permitir espectadores" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:31 +msgid "Spawn shield:" +msgstr "Tiempo de protección al resucitar:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:36 +msgid "Game speed:" +msgstr "Velocidad del juego:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:40 +msgid "Teamplay settings:" +msgstr "Configuración del juego en equipo:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:43 +msgid "Friendly fire scale:" +msgstr "Escala de daño a aliados:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:47 +msgid "Virtual friendly fire (effect only)" +msgstr "Daño virtual a aliados (apenas afecta)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:50 +msgid "Friendly fire penalty:" +msgstr "Penalizacion de daño a aliados:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:54 +msgid "Virtual penalty (effect only)" +msgstr "Penalizacion virtual (apenas afecta)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:57 +msgid "Teams:" +msgstr "Equipos:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:66 +msgid "Map voting:" +msgstr "Votacion de mapa:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:68 +msgid "No voting" +msgstr "No votar" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:69 +msgid "2 choices" +msgstr "2 opciones" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:70 +msgid "3 choices" +msgstr "3 opciones" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:71 +msgid "4 choices" +msgstr "4 opciones" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:72 +msgid "5 choices" +msgstr "5 opciones" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:73 +msgid "6 choices" +msgstr "6 opciones" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:74 +msgid "7 choices" +msgstr "7 opciones" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:75 +msgid "8 choices" +msgstr "8 opciones" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:76 +msgid "9 choices" +msgstr "9 opciones" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:79 +msgid "Simple majority wins vcall" +msgstr "La mayoría simple gana" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:5 +msgid "Map Information" +msgstr "Información del mapa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "Full item placement" +msgstr "Colocado total del item" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "MinstaGib only" +msgstr "Sólo MinstaGib" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:78 +msgid "Title:" +msgstr "Título:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:84 +msgid "Author:" +msgstr "Autor:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:90 +msgid "Features:" +msgstr "Características:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:95 +msgid "Game types:" +msgstr "Modos de juego:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:118 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:314 +msgid "Close" +msgstr "Cerrar" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:121 +msgid "MAP^Play" +msgstr "Jugar" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:7 +msgid "Mutators" +msgstr "Mutators" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:33 +msgid "All Weapons Arena" +msgstr "Arena con todas las armas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:35 +msgid "Most Weapons Arena" +msgstr "Arena con la mayoría de las Armas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:56 +#, c-format +msgid "%s Arena" +msgstr "%s Arena" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:68 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:167 +msgid "Dodging" +msgstr "Agacharse" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:70 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:250 +msgid "MinstaGib" +msgstr "MinstaGib" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:253 +msgid "NIX" +msgstr "NIX" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:74 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:205 +msgid "Rocket Flying" +msgstr "Volar con Cohetes" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:78 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:264 +msgid "No start weapons" +msgstr "Empezar sin armas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:80 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:189 +msgid "Low gravity" +msgstr "Poca gravedad" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:170 +msgid "Cloaked" +msgstr "Escondido" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:84 +msgid "Hook" +msgstr "Gancho" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:86 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:173 +msgid "Midair" +msgstr "No saltes" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:88 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:176 +msgid "Vampire" +msgstr "Vampiro" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:90 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:208 +msgid "Piñata" +msgstr "Piñata" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:92 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:211 +msgid "Weapons stay" +msgstr "Las armas permanecen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:94 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:180 +msgid "Blood loss" +msgstr "Pérdida de sangre" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:96 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:202 +msgid "Jet pack" +msgstr "Jetpack" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:98 +msgid "MUT^None" +msgstr "Ninguno" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:164 +msgid "Gameplay mutators:" +msgstr "Mutators del juego" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:196 +msgid "Weapon & item mutators:" +msgstr "Mutators de armas e items" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:199 +msgid "Grappling hook" +msgstr "Gancho de trepar" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:215 +msgid "Weapon arenas:" +msgstr "Arenas de armas:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:218 +msgid "Regular (no arena)" +msgstr "Regular (no arena)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:239 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:256 +msgid "with laser" +msgstr "con laser" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:247 +msgid "Special arenas:" +msgstr "Arenas especiales:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:260 +msgid "Most weapons" +msgstr "Mayoría de las Armas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:4 +msgid "Demo" +msgstr "Demo" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:28 +msgid "Record demos while playing" +msgstr "Grabar demos mientras se juega" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:32 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:28 +msgid "Filter:" +msgstr "Filtrar:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:29 +#: qcsrc/menu/xonotic/dialog_settings_input.c:41 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:24 +msgid "Clear" +msgstr "Limpiar" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:43 +msgid "Timedemo" +msgstr "Demo temporizado" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:46 +#, fuzzy +msgid "DEMO^Play" +msgstr "Jugar" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:4 +msgid "Join" +msgstr "Ingresar" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:36 +msgid "SRVS^Empty" +msgstr "Vacío" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:40 +msgid "SRVS^Full" +msgstr "Completo" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:44 +msgid "Pause" +msgstr "Pausar" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:56 +msgid "Address:" +msgstr "Direccion:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:67 +msgid "Info..." +msgstr "Información..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:317 +msgid "Join!" +msgstr "¡Ingresar!" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:5 +msgid "Server Information" +msgstr "Información del servidor" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:115 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:116 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:183 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:189 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:199 +msgid "N/A" +msgstr "N/A" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:158 +#, c-format +msgid "%d/%d, %d free player slots" +msgstr "%d/%d, %d lugares para jugar disponibles" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +#, c-format +msgid "%d modified settings" +msgstr "%d configuración modificada" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +msgid "Official settings" +msgstr "configuración oficial" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:197 +msgid "N/A (can't connect)" +msgstr "N/A (no se puede conectar)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:205 +msgid "not supported (can't connect)" +msgstr "no soportado (no se puede conectar)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:207 +msgid "not supported (won't encrypt)" +msgstr "no soportado (sin cifrado)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:211 +msgid "supported (will encrypt)" +msgstr "soportado (cifrado)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:213 +msgid "supported (won't encrypt)" +msgstr "suportado (no cifrado)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:217 +msgid "requested (will encrypt)" +msgstr "pedido (cifrado)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:219 +msgid "requested (won't encrypt)" +msgstr "pedido (sin cifrado)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:223 +msgid "required (can't connect)" +msgstr "requerido (no se puede conectarr)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:225 +msgid "required (will encrypt)" +msgstr "requerido (cifrado)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:246 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:269 +msgid "Players:" +msgstr "Jugadores:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:254 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:38 +msgid "Type:" +msgstr "Tipo:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:259 +msgid "Map:" +msgstr "Mapa:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:264 +msgid "Gameplay:" +msgstr "Jugabilidad:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:274 +msgid "Bots:" +msgstr "Bots:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:279 +msgid "Mod:" +msgstr "Mod:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:284 +msgid "Version:" +msgstr "Version:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:289 +msgid "Ping:" +msgstr "Ping:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:295 +msgid "CA:" +msgstr "CA:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:301 +msgid "Key:" +msgstr "Llave:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:307 +msgid "Encryption:" +msgstr "Encriptación:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:63 +msgid "Model:" +msgstr "Modelo:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:88 +msgid "Field of view:" +msgstr "Campo de visión:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:92 +msgid "View bobbing:" +msgstr "Vista flotante:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:96 +msgid "Zoom factor:" +msgstr "Factor de zoom:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:100 +msgid "Zoom speed:" +msgstr "Velocidad de zoom:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:103 +msgid "Weapon settings..." +msgstr "Configuración de armas..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:110 +msgid "Crosshair:" +msgstr "Mira:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:111 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:139 +msgid "Per weapon" +msgstr "Por arma" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:130 +msgid "Crosshair size:" +msgstr "Tamaño de mira:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:134 +msgid "Crosshair alpha:" +msgstr "Transparencia de mira:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:138 +msgid "Crosshair color:" +msgstr "Color de mira:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:140 +msgid "By health" +msgstr "Por salud" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:143 +msgid "Custom" +msgstr "Personalizado" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:148 +msgid "Enable center dot" +msgstr "Activar punto central" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:151 +msgid "Size:" +msgstr "Tamaño:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:158 +msgid "Hit test:" +msgstr "Test de tiro:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:159 +msgid "HTST^None" +msgstr "Ninguno" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:160 +msgid "TrueAim" +msgstr "Apuntado" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:161 +msgid "Enemies" +msgstr "Enemigos" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:164 +msgid "Waypoints setup..." +msgstr "Configurar puntos de camino..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:169 +msgid "Enter HUD editor" +msgstr "Entrar en el editor de HUD" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:174 +msgid "Force models:" +msgstr "Forzar modelos:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:175 +msgid "MDL^None" +msgstr "Ninguno" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:176 +msgid "MDL^Custom" +msgstr "Personalizado" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:177 +msgid "MDL^All" +msgstr "Todos" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:180 +msgid "Disable gore effects" +msgstr "Desactivar efectos de sangre" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:182 +msgid "Gibs:" +msgstr "Gibs:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:184 +msgid "GIBS^None" +msgstr "Ninguno" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:185 +msgid "GIBS^Few" +msgstr "Pocas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:186 +msgid "GIBS^Many" +msgstr "Muchos" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:187 +msgid "GIBS^Lots" +msgstr "Abundante" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:191 +msgid "Damage splash:" +msgstr "Daño colateral:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:195 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:173 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:194 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:30 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:41 +#: qcsrc/menu/xonotic/dialog_settings_video.c:109 +msgid "Apply immediately" +msgstr "Aplicar inmediatamente" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:5 +msgid "Waypoints" +msgstr "Puntos de camino" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:23 +msgid "Show base waypoints" +msgstr "Mostrar puntos de camino" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:25 +msgid "Waypoint scale:" +msgstr "Escala:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:29 +msgid "Waypoint alpha:" +msgstr "Transparencia:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:34 +msgid "Show names:" +msgstr "Mostrar nombres:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:37 +msgid "Teammates" +msgstr "Compañeros de equipo" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:38 +msgid "All players" +msgstr "Todos los jugadores" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:6 +msgid "Weapon settings" +msgstr "configuración de armas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:29 +msgid "Weapon priority list:" +msgstr "Lista de prioridad de armas:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:34 +msgid "Up" +msgstr "Arriba" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:37 +msgid "Down" +msgstr "Abajo" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:41 +msgid "Use priority list for weapon cycling" +msgstr "Usar lista de prioridad para ciclo de armas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:43 +msgid "Auto switch weapons on pickup" +msgstr "Cambiar de arma al recojer" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:45 +msgid "Draw 1st person weapon model" +msgstr "Dibujar modelo de arma en primera persona" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:55 +msgid "Flip view horizontally" +msgstr "Invertir vista horizontalmente" + +#: qcsrc/menu/xonotic/dialog_news.c:4 +msgid "News" +msgstr "Novedades" + +#: qcsrc/menu/xonotic/dialog_news.c:18 +msgid "http://www.xonotic.org/team/blog/" +msgstr "http://www.xonotic.org/team/blog/" + +#: qcsrc/menu/xonotic/dialog_quit.c:4 +msgid "Quit" +msgstr "Salir" + +#: qcsrc/menu/xonotic/dialog_quit.c:17 +msgid "Are you sure you want to quit?" +msgstr "Estas seguro de querer salir?" + +#: qcsrc/menu/xonotic/dialog_quit.c:20 +msgid "Yes" +msgstr "Si" + +#: qcsrc/menu/xonotic/dialog_quit.c:21 +msgid "No" +msgstr "No" + +#: qcsrc/menu/xonotic/dialog_settings.c:4 +msgid "Settings" +msgstr "Configuración" + +#: qcsrc/menu/xonotic/dialog_settings.c:18 +#: qcsrc/menu/xonotic/dialog_settings_input.c:4 +msgid "Input" +msgstr "Entrada" + +#: qcsrc/menu/xonotic/dialog_settings.c:19 +#: qcsrc/menu/xonotic/dialog_settings_video.c:4 +msgid "Video" +msgstr "Video" + +#: qcsrc/menu/xonotic/dialog_settings.c:20 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:4 +msgid "Effects" +msgstr "Efectos" + +#: qcsrc/menu/xonotic/dialog_settings.c:21 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:4 +msgid "Audio" +msgstr "Sonido" + +#: qcsrc/menu/xonotic/dialog_settings.c:22 +#: qcsrc/menu/xonotic/dialog_settings_network.c:4 +msgid "Network" +msgstr "Red" + +#: qcsrc/menu/xonotic/dialog_settings.c:23 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:4 +msgid "Misc" +msgstr "Misc" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:27 +msgid "Master:" +msgstr "Principal:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:33 +msgid "Music:" +msgstr "Musica:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:41 +msgid "VOL^Ambient:" +msgstr "Ambiente:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:48 +msgid "Info:" +msgstr "Información:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:55 +msgid "Items:" +msgstr "Items:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:62 +msgid "Pain:" +msgstr "Dolor:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:69 +msgid "Player:" +msgstr "Jugador:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:76 +msgid "Shots:" +msgstr "Disparos:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:83 +msgid "Voice:" +msgstr "Voz:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:91 +msgid "Weapons:" +msgstr "Armas:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:98 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:156 +msgid "Frequency:" +msgstr "Frecuencia:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:100 +msgid "8 kHz" +msgstr "8 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:101 +msgid "11.025 kHz" +msgstr "11.025 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:102 +msgid "16 kHz" +msgstr "16 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:103 +msgid "22.05 kHz" +msgstr "22.05 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:104 +msgid "24 kHz" +msgstr "24 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:105 +msgid "32 kHz" +msgstr "32 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:106 +msgid "44.1 kHz" +msgstr "44.1 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:107 +msgid "48 kHz" +msgstr "48 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:110 +msgid "Channels:" +msgstr "Canales:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:112 +msgid "Mono" +msgstr "Mono" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:113 +msgid "Stereo" +msgstr "Stereo" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:114 +msgid "2.1" +msgstr "2.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:115 +msgid "4" +msgstr "4" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:116 +msgid "5" +msgstr "5" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:117 +msgid "5.1" +msgstr "5.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:118 +msgid "6.1" +msgstr "6.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:119 +msgid "7.1" +msgstr "7.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:123 +msgid "Swap Stereo" +msgstr "Intercambiar Stereo" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:127 +msgid "Headphone friendly mode" +msgstr "Modo para auricular" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:131 +msgid "Spatial voices:" +msgstr "Voces espaciales:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:132 +msgid "VOCS^None" +msgstr "Ninguno" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:133 +msgid "VOCS^Taunts" +msgstr "Provocaciones" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:134 +msgid "VOCS^All" +msgstr "Todos" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:137 +msgid "Taunt range:" +msgstr "Nivel de taunts:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:140 +msgid "RNG^Very short" +msgstr "Muy corto" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:141 +msgid "RNG^Short" +msgstr "Corto" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:142 +msgid "RNG^Normal" +msgstr "Normal" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:143 +msgid "RNG^Long" +msgstr "Alto" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:144 +msgid "RNG^Full" +msgstr "Total" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:151 +msgid "Automatic taunts" +msgstr "Taunts Automatico" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:160 +msgid "Time warning:" +msgstr "Aviso de tiempo:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:162 +msgid "WRN^None" +msgstr "Ninguno" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:163 +msgid "1 minute" +msgstr "1 minuto" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:164 +msgid "5 minutes" +msgstr "5 minutos" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:165 +msgid "WRN^Both" +msgstr "Ambos" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:168 +msgid "Hit indicator" +msgstr "Indicador de tiro acertado" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:170 +msgid "Menu sounds" +msgstr "Sonidos del menú" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:38 +msgid "Quality preset:" +msgstr "Predefinición de calidad:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:41 +msgid "PRE^OMG!" +msgstr "OMG!" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:42 +msgid "PRE^Low" +msgstr "Bajo" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:43 +msgid "PRE^Medium" +msgstr "Media" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:44 +msgid "PRE^Normal" +msgstr "Normal" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:45 +msgid "PRE^High" +msgstr "Alta" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:46 +msgid "PRE^Ultra" +msgstr "Ultra" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:48 +msgid "PRE^Ultimate" +msgstr "Máxima" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:52 +msgid "Geometry detail:" +msgstr "Detalles geométricos:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:54 +msgid "DET^Lowest" +msgstr "Mínimo" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:55 +msgid "DET^Low" +msgstr "Bajo" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:56 +msgid "DET^Normal" +msgstr "Normal" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:57 +msgid "DET^Good" +msgstr "Bueno" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:58 +msgid "DET^Best" +msgstr "Mejor" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:59 +msgid "DET^Insane" +msgstr "Insano" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:62 +msgid "Antialiasing:" +msgstr "Antialiasing:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:64 +msgid "AA^Disabled" +msgstr "Deshabilitado" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:65 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:103 +msgid "2x" +msgstr "2x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:66 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:104 +msgid "4x" +msgstr "4x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:70 +msgid "Texture resolution:" +msgstr "Resolución de textura:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:73 +msgid "RES^Leet" +msgstr "Leet" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:74 +msgid "RES^Lowest" +msgstr "Mínimo" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:75 +msgid "RES^Low" +msgstr "Bajo" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:76 +msgid "RES^Normal" +msgstr "Normal" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:77 +msgid "RES^Good" +msgstr "Bueno" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:78 +msgid "RES^Best" +msgstr "Mejor" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:91 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:94 +msgid "Avoid lossy texture compression" +msgstr "Evitar compresion de Textura con Pérdida" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:100 +msgid "Anisotropy:" +msgstr "Filtro Anisotrópico:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:102 +msgid "ANISO^Disabled" +msgstr "Deshabilitado" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:105 +msgid "8x" +msgstr "8x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:106 +msgid "16x" +msgstr "16x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:110 +msgid "Particle quality:" +msgstr "Calidad de partículas:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:113 +msgid "Particle distance:" +msgstr "Distancia de partículas:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:117 +msgid "Decals" +msgstr "Símbolos" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:118 +msgid "Decals on models" +msgstr "Marcas en los jugadores" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:122 +msgid "Distance:" +msgstr "Distancia:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:128 +msgid "Time:" +msgstr "Tiempo:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:134 +msgid "Use lightmaps" +msgstr "Usar lightmaps" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:135 +msgid "Deluxe mapping" +msgstr "Mapeado Deluxe" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:137 +msgid "Gloss" +msgstr "Brillo" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:140 +msgid "Offset mapping" +msgstr "Despl. de mapeado" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:142 +msgid "Relief mapping" +msgstr "Mapeado Relief" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:145 +msgid "Reflections:" +msgstr "Reflejos:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:148 +msgid "Blurred" +msgstr "Borroso" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:149 +msgid "REFL^Good" +msgstr "Bueno" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:150 +msgid "Sharp" +msgstr "Ajustado" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:155 +msgid "Show surfaces" +msgstr "Mostrar superficies" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:157 +msgid "No dynamic lighting" +msgstr "Sin iluminación dinámica" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:159 +msgid "Flash blend approximation" +msgstr "Aproximación de flash mezclado" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:161 +msgid "Realtime dynamic lighting" +msgstr "Iluminación dinámica en tiempo real" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:162 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:166 +msgid "Shadows" +msgstr "Sombras" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:165 +msgid "Realtime world lighting" +msgstr "Iluminación del mundo en tiempo real" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:170 +msgid "Use normal maps" +msgstr "Usar mapa de normales" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:172 +msgid "Soft shadows" +msgstr "Sombras Suaves" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:175 +msgid "Coronas" +msgstr "Coronas" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:176 +msgid "Use Occlusion Queries" +msgstr "Usar consultas de oclusion" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:178 +msgid "Bloom" +msgstr "Bloom" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:180 +msgid "High Dynamic Range (HDR)" +msgstr "High Dynamic Range (HDR)" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:184 +msgid "Motion blur:" +msgstr "Difuminado p/ movimiento:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:189 +msgid "Blur and sharpen postprocessing" +msgstr "Difuminado y postprocesamiento ajustado" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:26 +msgid "Key bindings:" +msgstr "Asignacion de Teclas" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:31 +msgid "Change key..." +msgstr "Cambiar tecla..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:35 +msgid "Edit..." +msgstr "Editar..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:46 +msgid "Sensitivity:" +msgstr "Sensibilidad:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:51 +msgid "UI mouse speed:" +msgstr "Velocidad del puntero:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:55 +msgid "Mouse filter" +msgstr "Filtro del raton" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:57 +msgid "Invert mouse" +msgstr "Invertir eje Y" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:60 +#: qcsrc/menu/xonotic/dialog_settings_input.c:62 +msgid "Use joystick input" +msgstr "Usar entrada de joystick" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:65 +#: qcsrc/menu/xonotic/dialog_settings_input.c:67 +msgid "Turn off OS mouse acceleration" +msgstr "Desactivar aceleracion del raton" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:69 +msgid "\"enter console\" also closes" +msgstr "\"entrar a la consola\" tambien cerrar" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:5 +msgid "User defined key bind" +msgstr "Usar teclas definidas" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:42 +msgid "Command when pressed:" +msgstr "Comandar cuando se presiona:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:45 +msgid "Command when released:" +msgstr "Comandar cuando se suelta:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:48 +msgid "Save" +msgstr "Guardar" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:51 +msgid "Cancel" +msgstr "Cancelar" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:26 +msgid "Menu skins:" +msgstr "Textura del menú:" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:47 +msgid "Show current time" +msgstr "Mostrar el tiempo actual" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:49 +msgid "Show current date" +msgstr "Mostrar la fecha actual" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:51 +msgid "Show frames per second" +msgstr "Mostrar cuadros por segundo" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:53 +msgid "Minimize input latency" +msgstr "Minimizar retardo de entrada" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:5 +msgid "Advanced settings" +msgstr "Configuración avanzada" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:23 +msgid "Cvar filter:" +msgstr "Filtro de Cvar" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:34 +msgid "Setting:" +msgstr "Configuración:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:42 +msgid "Value:" +msgstr "Valor:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:56 +msgid "Description:" +msgstr "Descripción:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:26 +msgid "Client-side movement prediction" +msgstr "Predicción de movimento de lado del cliente" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:30 +msgid "Show netgraph" +msgstr "Mostrar gráfico de red" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:33 +msgid "Network speed:" +msgstr "Velocidad de red:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:35 +msgid "56k" +msgstr "56k" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:36 +msgid "ISDN" +msgstr "ISDN" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:37 +msgid "Slow ADSL" +msgstr "ADSL lenta" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:38 +msgid "Fast ADSL" +msgstr "ADSL rápida" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:39 +msgid "Broadband" +msgstr "Banda ancha" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:42 +msgid "Input packets/s:" +msgstr "Paquetes de entrada /s" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:46 +msgid "HTTP downloads:" +msgstr "Descargas via HTTP:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:49 +msgid "Downloads:" +msgstr "Descargas:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:53 +msgid "Speed (kB/s):" +msgstr "Velocidad (kB/s):" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:57 +msgid "Client UDP port:" +msgstr "Puerto UDP del Cliente:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:26 +msgid "Resolution:" +msgstr "Resolución:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:29 +msgid "Font/UI size:" +msgstr "Tamaño de Font/UI:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:31 +msgid "SZ^Unreadable" +msgstr "Ilegible" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:32 +msgid "SZ^Tiny" +msgstr "Minuscula" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:33 +msgid "SZ^Little" +msgstr "Muy pequeña" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:34 +msgid "SZ^Small" +msgstr "Pequeña" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:35 +msgid "SZ^Medium" +msgstr "Media" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:36 +msgid "SZ^Large" +msgstr "Grande" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:37 +msgid "SZ^Huge" +msgstr "Enorme" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:38 +msgid "SZ^Gigantic" +msgstr "Gigante" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:39 +msgid "SZ^Colossal" +msgstr "Colossal" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:42 +msgid "Color depth:" +msgstr "Profundidad del color:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:45 +msgid "Full screen" +msgstr "Pantalla entera" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:46 +msgid "Vertical Synchronization" +msgstr "Sincronizacion vertical" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:49 +msgid "Use OpenGL 2.0 shaders (GLSL)" +msgstr "Usar shaders OpenGL2.0 (GLSL)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:52 +msgid "Use GLSL to handle color control" +msgstr "Usar GLSL como manejador de colores" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:56 +msgid "Vertex Buffer Objects (VBOs)" +msgstr "Vertex Buffer Objects (VBOs)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:59 +msgid "VBO^Off" +msgstr "Desactivado" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:60 +msgid "Vertices, some Tris (compatible)" +msgstr "Vértices, algunos triangulos (compatible)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:63 +msgid "Vertices" +msgstr "Vértices" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:64 +msgid "Vertices and Triangles" +msgstr "Vertices y triangulos" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:67 +msgid "Depth first:" +msgstr "Profundidad primero:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:69 +msgid "DF^Disabled" +msgstr "Desactivado" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:70 +msgid "DF^World" +msgstr "Mundo" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:71 +msgid "DF^All" +msgstr "Todos" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:75 +msgid "Disable multithreaded OpenGL" +msgstr "Desactivar multi-hilos OpenGL" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:77 +msgid "Wait for GPU to finish each frame" +msgstr "Esperar a la GPU para terminar cada frame" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:80 +msgid "Brightness:" +msgstr "Brillo:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:83 +msgid "Contrast:" +msgstr "Contraste:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:86 +msgid "Gamma:" +msgstr "Gamma:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:91 +msgid "Contrast boost:" +msgstr "Resaltador de contraste" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:96 +msgid "Saturation:" +msgstr "Saturacion de color:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:102 +msgid "LIT^Ambient:" +msgstr "Ambiente:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:105 +msgid "Intensity:" +msgstr "Intensidad:" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:4 +msgid "Singleplayer" +msgstr "Jugador" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:127 +msgid "Instant action! (random map with bots)" +msgstr "¡Accion instantanea! (Mapa aleatorio con bots)" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:148 +msgid "Start Singleplayer!" +msgstr "¡Comenzar!" + +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:4 +msgid "Winner" +msgstr "Vencedor" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:5 +msgid "Team Selection" +msgstr "Selección de equipo" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:41 +msgid "join 'best' team (auto-select)" +msgstr "Ingresar 'mejor' equipo (selección automática)" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:45 +msgid "red" +msgstr "rojo" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:46 +msgid "blue" +msgstr "azul" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:47 +msgid "yellow" +msgstr "amarillo" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:48 +msgid "pink" +msgstr "rosa" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:51 +msgid "spectate" +msgstr "espectador" + +#: qcsrc/menu/xonotic/mainwindow.c:35 qcsrc/menu/xonotic/mainwindow.c:38 +msgid "Do not press this button again!" +msgstr "¡No vuelva a presionar este boton!" + +#: qcsrc/menu/xonotic/maplist.c:278 +msgid "" +"Huh? Can't play this (m is NULL). Refiltering so this won't happen again.\n" +msgstr "" +"Huh? no puedes jugarlo (m es nulo). Reflitrando para que esto no vuelva a " +"ocurrir.\n" + +#: qcsrc/menu/xonotic/maplist.c:286 +#, c-format +msgid "%s's Xonotic Server" +msgstr "Servidor de Xonotic de %s" + +#: qcsrc/menu/xonotic/maplist.c:291 +msgid "" +"Huh? Can't play this (invalid game type). Refiltering so this won't happen " +"again.\n" +msgstr "" +"Huh? no puedes jugarlo (tipo de juego invalido). Reflitrado para que esto " +"no vuelva a ocurrir.\n" + +#: qcsrc/menu/xonotic/playermodel.c:174 +msgid "<no model found>" +msgstr "<ningún modelo encontrado>" + +#: qcsrc/menu/xonotic/serverlist.c:185 +msgid "Remove" +msgstr "Remover" + +#: qcsrc/menu/xonotic/serverlist.c:187 +msgid "Bookmark" +msgstr "Marcador" + +#: qcsrc/menu/xonotic/serverlist.c:527 +msgid "Ping" +msgstr "Ping" + +#: qcsrc/menu/xonotic/serverlist.c:528 +msgid "Host name" +msgstr "Nombre del Host" + +#: qcsrc/menu/xonotic/serverlist.c:529 +msgid "Map" +msgstr "Mapa" + +#: qcsrc/menu/xonotic/serverlist.c:530 +msgid "Type" +msgstr "Tipo" + +#: qcsrc/menu/xonotic/serverlist.c:531 +msgid "Players" +msgstr "Jugadores" + +#: qcsrc/menu/xonotic/skinlist.c:105 +msgid "<TITLE>" +msgstr "<Título>" + +#: qcsrc/menu/xonotic/skinlist.c:106 +msgid "<AUTHOR>" +msgstr "<AUTOR>" + +#: qcsrc/menu/xonotic/slider_decibels.c:50 +msgid "VOL^OFF" +msgstr "DESACTIVADO" + +#: qcsrc/menu/xonotic/slider_decibels.c:52 +msgid "VOL^MAX" +msgstr "MAXIMO" + +#: qcsrc/menu/xonotic/slider_decibels.c:53 +#, c-format +msgid "%s dB" +msgstr "%s dB" + +#: qcsrc/menu/xonotic/slider_resolution.c:65 +#, c-format +msgid "%dx%d" +msgstr "%dx%d" + +#: qcsrc/menu/xonotic/util.qc:270 +#, c-format +msgid "Received HTTP request data for an invalid id %d.\n" +msgstr "Se ha recibido un pedido de datos HTTP para un id inválido: %d. \n" + +#: qcsrc/menu/xonotic/util.qc:285 +#, c-format +msgid "error receiving update notification: status is %d\n" +msgstr "error recibiendo notificación de actualización: el estado es %d\n" + +#: qcsrc/menu/xonotic/util.qc:290 +msgid "error: received HTML instead of an update notification\n" +msgstr "" +"error: se ha recibido HTML en vez de una notificación de actualización\n" + +#: qcsrc/menu/xonotic/util.qc:295 +msgid "error: received carriage returns from update notification server\n" +msgstr "" +"error: se recibieron retornos de carro desde el servidor que notifica las " +"actualizaciones\n" + +#: qcsrc/menu/xonotic/util.qc:316 +#, c-format +msgid "" +"Update can be downloaded at:\n" +"%s\n" +msgstr "" +"Actualización puede ser descargada en:\n" +"%s\n" + +#: qcsrc/menu/xonotic/util.qc:337 +msgid "Autogenerating mapinfo for newly added maps..." +msgstr "Generación automática de información para mapas nuevos..." + +#: qcsrc/menu/xonotic/util.qc:367 +#, c-format +msgid "^1%s TEST BUILD" +msgstr "^1%s TEST BUILD" + +#: qcsrc/menu/xonotic/util.qc:432 +#, c-format +msgid "Update to %s now!" +msgstr "¡Actualizar para %s ahora!" + +#: qcsrc/menu/xonotic/util.qc:501 +msgid "" +"^1ERROR: Texture compression is required but not supported.\n" +"^1Expect visual problems.\n" +msgstr "" +"^1ERROR: Se requiere la compresion de texturas, pero no es soportada.\n" +"^1Pueden ocurrir posibles problemas visuales.\n" + +#: qcsrc/menu/xonotic/util.qc:523 +msgid "Arena" +msgstr "Arena" + +#: qcsrc/menu/xonotic/util.qc:524 +msgid "Assault" +msgstr "Asalto" + +#: qcsrc/menu/xonotic/util.qc:525 +msgid "Capture The Flag" +msgstr "Captura la Bandera" + +#: qcsrc/menu/xonotic/util.qc:526 +msgid "Clan Arena" +msgstr "Clan arena" + +#: qcsrc/menu/xonotic/util.qc:527 +msgid "Deathmatch" +msgstr "Combate a muerte" + +#: qcsrc/menu/xonotic/util.qc:528 +msgid "Domination" +msgstr "Dominación" + +#: qcsrc/menu/xonotic/util.qc:529 +msgid "Freeze Tag" +msgstr "Freeze Tag" + +#: qcsrc/menu/xonotic/util.qc:530 +msgid "Keepaway" +msgstr "Keepaway" + +#: qcsrc/menu/xonotic/util.qc:531 +msgid "Key Hunt" +msgstr "Caza de llave" + +#: qcsrc/menu/xonotic/util.qc:532 +msgid "Last Man Standing" +msgstr "Ultimo Sobreviviente" + +#: qcsrc/menu/xonotic/util.qc:533 +msgid "Nexball" +msgstr "Nexball" + +#: qcsrc/menu/xonotic/util.qc:534 +msgid "Onslaught" +msgstr "Embestida" + +#: qcsrc/menu/xonotic/util.qc:535 +msgid "Race" +msgstr "Carrera" + +#: qcsrc/menu/xonotic/util.qc:536 +msgid "Race CTS" +msgstr "Carrera CTS" + +#: qcsrc/menu/xonotic/util.qc:537 +msgid "Runematch" +msgstr "Runamatch" + +#: qcsrc/menu/xonotic/util.qc:538 +msgid "Team Deathmatch" +msgstr "Combate a muerte por equipos" + +#: qcsrc/menu/xonotic/util.qc:557 +#, c-format +msgid "@!#%'n Tuba Throwing" +msgstr "@!#%'n Tuba Throwing" + +#: qcsrc/menu/xonotic/util.qc:577 qcsrc/menu/xonotic/util.qc:593 +#: qcsrc/menu/xonotic/util.qc:602 qcsrc/menu/xonotic/util.qc:610 +#: qcsrc/menu/xonotic/util.qc:622 +msgid "Default" +msgstr "Por Defecto" + +#: qcsrc/menu/xonotic/util.qc:588 +msgid "Use default" +msgstr "Usar por defecto" + +#: qcsrc/menu/xonotic/util.qc:608 +msgid "Team Color:" +msgstr "Color del equipo:" + +#: qcsrc/menu/xonotic/util.qh:47 +msgid "Enable panel" +msgstr "Activar panel" + +#: qcsrc/server/w_crylink.qc:2 +msgid "Crylink" +msgstr "Crylink" + +#: qcsrc/server/w_crylink.qc:666 +#, c-format +msgid "%s succeeded at self-destructing themself with the Crylink" +msgstr "%s logró autodestruirse con el Crylink" + +#: qcsrc/server/w_crylink.qc:671 +#, c-format +msgid "%s could not hide from %s's Crylink" +msgstr "%s no se pudo esconder del Crylink de %s" + +#: qcsrc/server/w_crylink.qc:673 +#, c-format +msgid "%s was too close to %s's Crylink" +msgstr "%s estuvo demasiado cerca del Crylink de %s" + +#: qcsrc/server/w_crylink.qc:675 +#, c-format +msgid "%s took a close look at %s's Crylink" +msgstr "%s miró de cerca al Crylink de %s" + +#: qcsrc/server/w_electro.qc:2 +msgid "Electro" +msgstr "Electro" + +#: qcsrc/server/w_electro.qc:574 +#, c-format +msgid "%s could not remember where they put plasma" +msgstr "%s no pudo recordar donde dejó su plasma la última vez" + +#: qcsrc/server/w_electro.qc:576 +#, c-format +msgid "%s played with plasma" +msgstr "%s jugó con plasma" + +#: qcsrc/server/w_electro.qc:583 +#, c-format +msgid "%s just noticed %s's blue ball" +msgstr "%s acaba de percatarse de la bola azul de %s" + +#: qcsrc/server/w_electro.qc:585 +#, c-format +msgid "%s got in touch with %s's blue ball" +msgstr "%s tuvo un encuentro cercano con la bola azul de %s" + +#: qcsrc/server/w_electro.qc:590 +#, c-format +msgid "%s felt the electrifying air of %s's combo" +msgstr "%s sintió el aire electrificante del combo de %s" + +#: qcsrc/server/w_electro.qc:592 +#, c-format +msgid "%s got too close to %s's blue beam" +msgstr "%s estuvo demasiado cerca del rayo azul de %s" + +#: qcsrc/server/w_electro.qc:594 +#, c-format +msgid "%s was blasted by %s's blue beam" +msgstr "%s estuvo en estado critico por el rayo azul de %s" + +#: qcsrc/server/w_fireball.qc:2 +msgid "Fireball" +msgstr "Fireball" + +#: qcsrc/server/w_fireball.qc:417 +#, c-format +msgid "%s forgot about some firemine" +msgstr "%s se olvidó de algunas minas de fuego" + +#: qcsrc/server/w_fireball.qc:419 qcsrc/server/w_hlac.qc:240 +#, c-format +msgid "%s should have used a smaller gun" +msgstr "%s tendría que haber usado un arma más chica" + +#: qcsrc/server/w_fireball.qc:426 +#, c-format +msgid "%s tried to catch %s's firemine" +msgstr "%s intentó agarrar la mina de fuego de %s" + +#: qcsrc/server/w_fireball.qc:428 +#, c-format +msgid "%s fatefully ignored %s's firemine" +msgstr "%s fatalmente ignoró la mina de fuego de %s" + +#: qcsrc/server/w_fireball.qc:435 +#, c-format +msgid "%s could not hide from %s's fireball" +msgstr "%s no se puedo esconder del fireball de %s" + +#: qcsrc/server/w_fireball.qc:437 +#, c-format +msgid "%s saw the pretty lights of %s's fireball" +msgstr "%s vió las lindas luces del fireball de %s" + +#: qcsrc/server/w_fireball.qc:440 +#, c-format +msgid "%s got too close to %s's fireball" +msgstr "%s estuvo demasiado cerca del fireball de %s" + +#: qcsrc/server/w_fireball.qc:442 +#, c-format +msgid "%s tasted %s's fireball" +msgstr "%s probó el fireball de %s" + +#: qcsrc/server/w_grenadelauncher.qc:2 +msgid "Mortar" +msgstr "Mortero" + +#: qcsrc/server/w_grenadelauncher.qc:383 +#, c-format +msgid "%s tried out his own grenade" +msgstr "%s probó su propia granada" + +#: qcsrc/server/w_grenadelauncher.qc:385 +#, c-format +msgid "%s detonated" +msgstr "%s ha detonado" + +#: qcsrc/server/w_grenadelauncher.qc:391 +#, c-format +msgid "%s didn't see %s's grenade" +msgstr "%s no vió la granada de %s" + +#: qcsrc/server/w_grenadelauncher.qc:393 +#, c-format +msgid "%s almost dodged %s's grenade" +msgstr "%s casi esquivó la granada de %s" + +#: qcsrc/server/w_grenadelauncher.qc:395 +#, c-format +msgid "%s ate %s's grenade" +msgstr "%s se comió la granada de %s" + +#: qcsrc/server/w_hagar.qc:2 +msgid "Hagar" +msgstr "Hagar" + +#: qcsrc/server/w_hagar.qc:395 qcsrc/server/w_seeker.qc:655 +#, c-format +msgid "%s played with tiny rockets" +msgstr "%s jugó con pequeños cohetes" + +#: qcsrc/server/w_hagar.qc:399 +#, c-format +msgid "%s hoped %s's missiles wouldn't bounce" +msgstr "%s esperó que no le reboten misiles de %s" + +#: qcsrc/server/w_hagar.qc:401 qcsrc/server/w_seeker.qc:661 +#, c-format +msgid "%s was pummeled by %s" +msgstr "%s fue molido por %s" + +#: qcsrc/server/w_hlac.qc:2 +msgid "Heavy Laser Assault Cannon" +msgstr "Heavy Laser Assault Cannon" + +#: qcsrc/server/w_hlac.qc:242 +#, c-format +msgid "%s was cut down by %s" +msgstr "%s fue rebanado por %s" + +#: qcsrc/server/w_hook.qc:2 +msgid "Grappling Hook" +msgstr "Grappling Hook" + +#: qcsrc/server/w_hook.qc:266 qcsrc/server/w_porto.qc:296 +#, c-format +msgid "%s did the impossible" +msgstr "%s hizo lo imposible" + +#: qcsrc/server/w_hook.qc:268 +#, c-format +msgid "%s has run into %s's gravity bomb" +msgstr "%s entró a la bomba de gravedad de %s" + +#: qcsrc/server/w_laser.qc:2 +msgid "Laser" +msgstr "Laser" + +#: qcsrc/server/w_laser.qc:311 +#, c-format +msgid "%s lasered themself to hell" +msgstr "%s se fué al infierno montado en su laser" + +#: qcsrc/server/w_laser.qc:315 +#, c-format +msgid "%s was cut in half by %s's gauntlet" +msgstr "%s fue cortado a la mitad por el gauntlet de %s" + +#: qcsrc/server/w_laser.qc:317 +#, c-format +msgid "%s was lasered to death by %s" +msgstr "%s fue muerto por el laser de %s" + +#: qcsrc/server/w_minelayer.qc:2 +msgid "Mine Layer" +msgstr "Mine Layer" + +#: qcsrc/server/w_minelayer.qc:523 qcsrc/server/w_rocketlauncher.qc:501 +#, c-format +msgid "%s exploded" +msgstr "%s explotó" + +#: qcsrc/server/w_minelayer.qc:527 +#, c-format +msgid "%s got too close to %s's mine" +msgstr "%s estuvo cerca de la mina de %s" + +#: qcsrc/server/w_minelayer.qc:529 +#, c-format +msgid "%s almost dodged %s's mine" +msgstr "%s casi esquivo la mina de %s" + +#: qcsrc/server/w_minelayer.qc:531 +#, c-format +msgid "%s stepped on %s's mine" +msgstr "%s caminó encima de la mina de %s" + +#: qcsrc/server/w_minstanex.qc:2 +msgid "MinstaNex" +msgstr "MinstaNex" + +#: qcsrc/server/w_minstanex.qc:293 qcsrc/server/w_nex.qc:253 +#: qcsrc/server/w_shotgun.qc:215 qcsrc/server/w_uzi.qc:317 +#, c-format +msgid "%s is now thinking with portals" +msgstr "%s ahora está \"thinking with portals\"" + +#: qcsrc/server/w_minstanex.qc:295 qcsrc/server/w_nex.qc:255 +#, c-format +msgid "%s has been vaporized by %s" +msgstr "%s ha sido vaporizado por %s" + +#: qcsrc/server/w_nex.qc:2 +msgid "Nex" +msgstr "Nex" + +#: qcsrc/server/w_porto.qc:2 +msgid "Port-O-Launch" +msgstr "Port-O-Launch" + +#: qcsrc/server/w_porto.qc:298 +#, c-format +msgid "%s felt %s doing the impossible to him" +msgstr "%s sintió a %s hacer lo imposible por él/ella" + +#: qcsrc/server/w_rifle.qc:2 +msgid "Rifle" +msgstr "Rifle" + +#: qcsrc/server/w_rifle.qc:233 +#, c-format +msgid "%s shot themself automatically" +msgstr "%s se disparó a si mismo" + +#: qcsrc/server/w_rifle.qc:235 +#, c-format +msgid "%s sniped themself somehow" +msgstr "%s se disparó a si mismo" + +#: qcsrc/server/w_rifle.qc:242 +#, c-format +msgid "%s failed to hide from %s's bullet hail" +msgstr "%s no logró esconderse del granizo de balas de %s" + +#: qcsrc/server/w_rifle.qc:244 +#, c-format +msgid "%s died in %s's bullet hail" +msgstr "%s murió en el granizo de balas de %s" + +#: qcsrc/server/w_rifle.qc:251 +#, c-format +msgid "%s failed to hide from %s's rifle" +msgstr "%s no logró esconderse del rifle de %s" + +#: qcsrc/server/w_rifle.qc:256 +#, c-format +msgid "%s got hit in the head by %s" +msgstr "%s fué disparado en la cabeza por %s" + +#: qcsrc/server/w_rifle.qc:258 qcsrc/server/w_uzi.qc:321 +#, c-format +msgid "%s was sniped by %s" +msgstr "%s fué disparado con un rifle por %s" + +#: qcsrc/server/w_rocketlauncher.qc:2 +msgid "Rocket Launcher" +msgstr "Rocket Launcher" + +#: qcsrc/server/w_rocketlauncher.qc:505 +#, c-format +msgid "%s got too close to %s's rocket" +msgstr "%s estuvo demasiado cerca del cohete de %s" + +#: qcsrc/server/w_rocketlauncher.qc:507 +#, c-format +msgid "%s almost dodged %s's rocket" +msgstr "%s casi esquivó el cohete de %s" + +#: qcsrc/server/w_rocketlauncher.qc:509 +#, c-format +msgid "%s ate %s's rocket" +msgstr "%s se comió el misil de %s" + +#: qcsrc/server/w_seeker.qc:2 +msgid "T.A.G. Seeker" +msgstr "T.A.G. Seeker" + +#: qcsrc/server/w_seeker.qc:659 +#, c-format +msgid "%s was tagged by %s" +msgstr "%s fue marcado por %s" + +#: qcsrc/server/w_shotgun.qc:2 +msgid "Shotgun" +msgstr "Escopeta" + +#: qcsrc/server/w_shotgun.qc:219 +#, c-format +msgid "%2$s ^7slapped %1$s ^7around a bit with a large ^2shotgun" +msgstr "%2$s ^7abofeteó %1$s ^7con una gran ^2shotgun" + +#: qcsrc/server/w_shotgun.qc:221 +#, c-format +msgid "%s was gunned by %s" +msgstr "%s fue tiroteado por %s" + +#: qcsrc/server/w_tuba.qc:2 +#, c-format +msgid "@!#%'n Tuba" +msgstr "@!#%'n Tuba" + +#: qcsrc/server/w_tuba.qc:252 +#, c-format +msgid "%s hurt his own ears with the @!#%%'n Tuba" +msgstr "%s se lastimó sus propios oídos con la Tuba de @!#%%" + +#: qcsrc/server/w_tuba.qc:256 +#, c-format +msgid "%s died of %s's great playing on the @!#%%'n Tuba" +msgstr "%s murió por la gran interpretación de Tuba de @!#%%" + +#: qcsrc/server/w_uzi.qc:2 +msgid "Machine Gun" +msgstr "Machine Gun" + +#: qcsrc/server/w_uzi.qc:323 +#, c-format +msgid "%s was riddled full of holes by %s" +msgstr "%s fue totalmente acribillado por %s" diff --git a/menu.dat.fi.po b/menu.dat.fi.po new file mode 100644 index 0000000000..116c9bb982 --- /dev/null +++ b/menu.dat.fi.po @@ -0,0 +1,2883 @@ +# Xonotic Menu +# Copyright (C) 2011 Team Xonotic +# This file is distributed under the same license as the PACKAGE package. +# Henry 'Exitium' Sanmark <henry.sanmark@gmail.com>, 2011. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 0.1preview\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-09-02 07:51+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Henry 'Exitium' Sanmark <henry.sanmark@gmail.com>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: qcsrc/common/mapinfo.qc:1092 qcsrc/menu/xonotic/skinlist.c:163 +#, c-format +msgid "%s: %s" +msgstr "%s: %s" + +#: qcsrc/menu/gamecommand.qc:47 +#, c-format +msgid "error: status is %d\n" +msgstr "virhe: %d\n" + +#: qcsrc/menu/gamecommand.qc:65 +msgid "Usage: menu_cmd command..., where possible commands are:\n" +msgstr "Käyttö: menu_cmd_command..., missä mahdollisia komentoja ovat:\n" + +#: qcsrc/menu/gamecommand.qc:66 +msgid " sync - reloads all cvars on the current menu page\n" +msgstr " sync - uudelleenlataa kaikki cvar-muuttujat nykyiseen valikkoon" + +#: qcsrc/menu/gamecommand.qc:67 +msgid " directmenu ITEM - select a menu item as main item\n" +msgstr " directmenu ITMEM - valitse valikon kohta pääkohdaksi\n" + +#: qcsrc/menu/gamecommand.qc:193 +msgid "error creating curl handle\n" +msgstr "virhe luodessa curl handlea\n" + +#: qcsrc/menu/gamecommand.qc:239 +msgid "Invalid command. For a list of supported commands, try menu_cmd help.\n" +msgstr "" +"Komentoa ei löydy. Saadaksesi listan kaikista tuetuista komennoista, kokeile " +"menu_cmd help.\n" + +#: qcsrc/menu/item/gecko.c:49 +msgid "Browser not initialized!" +msgstr "Selainta ei ole alustettu!" + +#: qcsrc/menu/item/label.c:63 +#, c-format +msgid "NOTE: label text %s too wide for label, condensed by factor %f\n" +msgstr "HUOM: tekstikentän teksti %s on liian pitkä, joten se lyhennetään %f\n" + +#: qcsrc/menu/item/listbox.c:300 +#, c-format +msgid "Item %d" +msgstr "Esine %d" + +#: qcsrc/menu/item/slider.c:64 +#, c-format +msgid "%d (%s)" +msgstr "%d (%s)" + +#: qcsrc/menu/item/textslider.c:29 qcsrc/menu/item/textslider.c:31 +msgid "custom" +msgstr "omavalintainen" + +#: qcsrc/menu/menu.qc:29 +#, c-format +msgid "^4MQC Build information: ^1%s\n" +msgstr "^4MQC Version tiedot: ^1%s\n" + +#: qcsrc/menu/xonotic/campaign.c:284 +#: qcsrc/menu/xonotic/dialog_singleplayer.c:134 +msgid "???" +msgstr "???" + +#: qcsrc/menu/xonotic/campaign.c:285 +#, c-format +msgid "Level %d: %s" +msgstr "Taso %d: %s" + +#: qcsrc/menu/xonotic/cvarlist.c:85 +msgid "will be saved to config.cfg" +msgstr "tallennetaan config.cfg-tiedostoon" + +#: qcsrc/menu/xonotic/cvarlist.c:87 +msgid "will not be saved" +msgstr "ei tallenneta" + +#: qcsrc/menu/xonotic/cvarlist.c:89 +msgid "private" +msgstr "yksityinen" + +#: qcsrc/menu/xonotic/cvarlist.c:91 +msgid "engine setting" +msgstr "pelimoottorin asetus" + +#: qcsrc/menu/xonotic/cvarlist.c:93 +msgid "read only" +msgstr "vain luku" + +#: qcsrc/menu/xonotic/dialog_credits.c:5 +msgid "Credits" +msgstr "Tekijät" + +#: qcsrc/menu/xonotic/dialog_credits.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:269 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:41 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:57 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:61 +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:21 +msgid "OK" +msgstr "OK" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:4 +msgid "Welcome" +msgstr "Tervetuloa" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:33 +msgid "" +"Welcome to Xonotic, please select your language preference and enter your " +"player name to get started. You can change these options later through the " +"menu system." +msgstr "" +"Tervetuloa pelaamaan Xonoticcia! Valitse haluamasi kieli ja pelaajanimesi " +"aloittaaksesi. Voit vaihtaa näitä asetuksia jälkikäteen pelin asetuksista." + +#: qcsrc/menu/xonotic/dialog_firstrun.c:38 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:35 +msgid "Text language:" +msgstr "Tekstin kieli:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:47 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:40 +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:39 +msgid "Name:" +msgstr "Nimi:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:69 +msgid "Save settings" +msgstr "Tallenna asetukset" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:4 +msgid "Ammo Panel" +msgstr "Ammuspaneeli" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:22 +msgid "Ammunition display:" +msgstr "Ammuksien näyttö:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:25 +msgid "Show only current ammo type" +msgstr "Näytä vain nykyinen ammustyyppi" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:28 +msgid "Align icon:" +msgstr "Kuvakkeen kohdistus:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:29 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:36 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:40 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:40 +msgid "Left" +msgstr "Vasen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:38 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:41 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:41 +msgid "Right" +msgstr "Oikea" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:4 +msgid "Centerprint" +msgstr "Keskeiskirjoitus" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:23 +msgid "Message duration:" +msgstr "Viestien kesto:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:27 +msgid "Fade time:" +msgstr "Sisääntulon häivennyksen kesto" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:31 +msgid "Flip messages order" +msgstr "Käännä ilmoitusjärjestys" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:33 +msgid "Text alignment:" +msgstr "Tekstin kohdistus:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:37 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:50 +msgid "Center" +msgstr "Keskus" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:41 +msgid "Font scale:" +msgstr "Fontin skaala:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:4 +msgid "Chat Panel" +msgstr "Keskustelupaneeli" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:22 +msgid "Chat entries:" +msgstr "Keskustelun sisältö:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:25 +msgid "Chat size:" +msgstr "Keskustelun koko" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:29 +msgid "Chat lifetime:" +msgstr "Keskustelun kesto:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:33 +msgid "Chat beep sound" +msgstr "Keskustelun piippausääni" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:4 +msgid "Engine Info Panel" +msgstr "Pelimoottorin tietopaneeli" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:22 +msgid "Engine info:" +msgstr "Pelimoottorin tiedot:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:25 +msgid "Use an averaging algorithm for fps" +msgstr "Käytä tasoittavaa algoritmia ruudunpäivitykselle (FPS)" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:4 +msgid "Health/Armor Panel" +msgstr "Elämä/panssaripaneeli" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:22 +msgid "Enable status bar" +msgstr "Ota tilapalkki käyttöön" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:24 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:24 +msgid "Status bar alignment:" +msgstr "Tilapalkin kohdistus:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:42 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:42 +msgid "Inward" +msgstr "Sisäänpäin" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:43 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:43 +msgid "Outward" +msgstr "Ulospäin" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:37 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:37 +msgid "Icon alignment:" +msgstr "Kuvakkeen kohdistus:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:45 +msgid "Flip health and armor positions" +msgstr "Vaihda elämän ja panssarin paikkaa" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:4 +msgid "Info Messages Panel" +msgstr "Tiedotuspaneeli" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:22 +msgid "Info messages:" +msgstr "Tiedoitukset" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:25 +msgid "Flip align" +msgstr "Tasoita" + +#: qcsrc/menu/xonotic/dialog_hudpanel_modicons.c:4 +msgid "Mod Icons Panel" +msgstr "Modi-ikonit paneeli" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:4 +msgid "Notification Panel" +msgstr "Ilmoituspaneeli" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:22 +msgid "Notifications:" +msgstr "Ilmoitukset:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:25 +msgid "Also print notifications to the console" +msgstr "Laita ilmoitukset myös komentoriville" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:28 +msgid "Flip notify order" +msgstr "Käännä ilmoitusjärjestys" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:31 +msgid "Entry lifetime:" +msgstr "Sisääntulon kesto" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:35 +msgid "Entry fadetime:" +msgstr "Sisääntulon häivennyksen kesto" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:4 +msgid "Physics Panel" +msgstr "Fysiikkapaneeli" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:21 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:21 +msgid "Panel disabled" +msgstr "Paneeli pois päältä" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:23 +msgid "Panel enabled" +msgstr "Paneeli päälle" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:24 +msgid "Panel enabled even observing" +msgstr "Paneeli päällä kun katsojana" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:25 +msgid "Panel enabled only in Race/CTS" +msgstr "Paneeli käytössä vain kilpajuoksuissa" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:31 +msgid "Status bar" +msgstr "Tilapalkki" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:48 +msgid "Left align" +msgstr "Vasen tasaus" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:34 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:52 +msgid "Right align" +msgstr "Oikea tasaus" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:35 +msgid "Inward align" +msgstr "Sisäänpäin kohditus" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:36 +msgid "Outward align" +msgstr "Ulospäin kohdistus" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:40 +msgid "Flip speed/acceleration positions" +msgstr "Vaihda nopeuden/kiihtyvyyden paikkaa" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:44 +msgid "Speed:" +msgstr "Nopeus:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:45 +msgid "Include vertical speed" +msgstr "Huomioi pystysuora nopeus" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:56 +msgid "Speed unit:" +msgstr "Nopeuden mittayksikkö:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:58 +msgid "qu/s" +msgstr "qu/s" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:59 +msgid "m/s" +msgstr "m/s" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:60 +msgid "km/h" +msgstr "km/h" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:61 +msgid "mph" +msgstr "mph" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:62 +msgid "knots" +msgstr "knots" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:64 +msgid "Show" +msgstr "Näytä" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:67 +msgid "Top speed" +msgstr "Huippunopeus" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:73 +msgid "Acceleration:" +msgstr "Kiihtyvyys:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:74 +msgid "Include vertical acceleration" +msgstr "Huomioi pystysuora kiihtyvyys" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:4 +msgid "Powerups Panel" +msgstr "Tehonlisäyspaneeli" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:45 +msgid "Flip strength and shield positions" +msgstr "Käännä voimakkuuden ja suojauksen sijainnit" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:4 +msgid "Pressed Keys Panel" +msgstr "Painettujen näppäinten paneeli" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:22 +msgid "Panel enabled when spectating" +msgstr "Paneeli päällä kun katsojana" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:23 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:23 +msgid "Panel always enabled" +msgstr "Paneeli aina päällä" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:30 +msgid "Forced aspect:" +msgstr "Pakotettu näkymä:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_racetimer.c:4 +msgid "Race Timer Panel" +msgstr "Kilpajuoksun ajanoton paneeli" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:4 +msgid "Radar Panel" +msgstr "Tutkapaneeli" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:22 +msgid "Panel enabled in teamgames" +msgstr "Paneeli käytössä joukkuepeleissä" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:29 +msgid "Radar:" +msgstr "Tutka:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:32 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:43 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:154 +#: qcsrc/menu/xonotic/util.qc:600 +msgid "Alpha:" +msgstr "Alpha:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:36 +msgid "Rotation:" +msgstr "Pyöriminen:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:38 +msgid "Forward" +msgstr "Eteenpäin" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:39 +msgid "West" +msgstr "Länsi" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:40 +msgid "South" +msgstr "Etelä" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:41 +msgid "East" +msgstr "Itä" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:42 +msgid "North" +msgstr "Pohjoinen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:46 +msgid "Scale:" +msgstr "Skaala:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:50 +msgid "Zoom mode:" +msgstr "Tarkennus:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:52 +msgid "Zoomed in" +msgstr "Tarkennettu kohteeseen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:53 +msgid "Zoomed out" +msgstr "Tarkennuksen poisto" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:54 +msgid "Always zoomed" +msgstr "Aina tarkennettuna" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:55 +msgid "Never zoomed" +msgstr "Tarkennus ei ikinä päällä" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:4 +msgid "Score Panel" +msgstr "Tulospaneeli" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:22 +msgid "Score:" +msgstr "Tulos:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:25 +msgid "Rankings:" +msgstr "Tilastot:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:26 +msgid "Off" +msgstr "Pois päältä" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:27 +msgid "And me" +msgstr "Ja minä" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:28 +msgid "Pure" +msgstr "Muokkaamaton" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:4 +msgid "Timer Panel" +msgstr "Ajastinpaneeli" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:22 +msgid "Timer:" +msgstr "Ajastin:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:25 +msgid "Show elapsed time" +msgstr "Näytä kulutettu aika" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:4 +msgid "Vote Panel" +msgstr "Äänestyspaneeli" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:22 +msgid "Alpha after voting:" +msgstr "Alpha äänestyksen jälkeen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:4 +msgid "Weapons Panel" +msgstr "Asepaneeli" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:24 +msgid "Fade out after:" +msgstr "Himmennä jälkikäteen:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:26 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:36 +msgid "Never" +msgstr "Ei ikinä" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:28 +#, c-format +msgid "%ds" +msgstr "%dt" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:32 +msgid "Fade effect:" +msgstr "Himmennyseffekti:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:35 +msgid "EF^None" +msgstr "EF^Ei mikään" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:36 +msgid "Slide" +msgstr "Liukuminen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:37 +msgid "Alpha" +msgstr "Alpha" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:38 +msgid "EF^Both" +msgstr "EF^Molemmat" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:42 +msgid "Weapon icons:" +msgstr "Aseiden kuvakkeet:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:45 +msgid "Show weapon ID as:" +msgstr "Näytä aseen tunniste:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:46 +msgid "SHOWAS^None" +msgstr "SHOWAS^Ei mitään." + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:47 +msgid "Number" +msgstr "Numero" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:48 +msgid "Bind" +msgstr "Näppäin" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:51 +msgid "Show Accuracy" +msgstr "Näytä tarkkuus" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:52 +msgid "Show Ammo" +msgstr "Näytä panokset" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:55 +msgid "Ammo bar color:" +msgstr "Ammuskotelon väri" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:61 +msgid "Ammo bar alpha:" +msgstr "Ammuskotelon alpha" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:4 +msgid "Panel HUD Setup" +msgstr "Paneelin näkymän asetukset" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:21 +msgid "Panel background defaults:" +msgstr "Paneelin taustan perusasetukset:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:23 qcsrc/menu/xonotic/util.qc:575 +msgid "Background:" +msgstr "Tausta:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:25 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:37 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:52 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:91 qcsrc/menu/xonotic/util.qc:578 +#: qcsrc/menu/xonotic/util.qc:594 qcsrc/menu/xonotic/util.qc:611 +msgid "Disable" +msgstr "Pois päältä" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:30 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:77 qcsrc/menu/xonotic/util.qc:583 +msgid "Color:" +msgstr "Väri:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:35 qcsrc/menu/xonotic/util.qc:591 +msgid "Border size:" +msgstr "Reunan koko:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:50 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:89 +msgid "Team color:" +msgstr "Joukkueen väri:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:58 qcsrc/menu/xonotic/util.qc:617 +msgid "Test team color in configure mode" +msgstr "Kokeile joukkueen väriä muokkaustilassa" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:61 qcsrc/menu/xonotic/util.qc:620 +msgid "Padding:" +msgstr "Pehmustus:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:68 +msgid "HUD Dock:" +msgstr "Näkymän liitäntä:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:70 +msgid "DOCK^Disabled" +msgstr "DOCK^Pois" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:71 +msgid "DOCK^Small" +msgstr "DOCK^Pieni" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:72 +msgid "DOCK^Medium" +msgstr "DOCK^Keskikokoinen" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:73 +msgid "DOCK^Large" +msgstr "DOCK^Suuri" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:96 +msgid "Grid settings:" +msgstr "Ruudukon asetukset:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:99 +msgid "Snap panels to grid" +msgstr "Katkaise paneelit ruudukkoon" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:102 +msgid "Grid size:" +msgstr "Ruudukon koko:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:103 +msgid "X:" +msgstr "X:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:109 +msgid "Y:" +msgstr "Y:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:117 +msgid "Exit setup" +msgstr "Poistu asetuksista" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:4 +msgid "Multiplayer" +msgstr "Moninpeli" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:18 +msgid "Servers" +msgstr "Palvelimet" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:19 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:5 +msgid "Create" +msgstr "Luo" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:20 +msgid "Demos" +msgstr "Demot" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:5 +msgid "Player Setup" +msgstr "Pelaajan asetukset" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:34 +msgid "Game type:" +msgstr "Pelityyppi" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:46 +msgid "Match settings:" +msgstr "Ottelun asetukset" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:49 +msgid "Time limit:" +msgstr "Aikaraja" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:53 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:61 +msgid "Use map specified default" +msgstr "Käytä kartan omaa oletusarvoa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:56 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:155 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:156 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:157 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:161 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:162 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:163 +msgid "Point limit:" +msgstr "Pisteraja:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:64 +msgid "Player slots:" +msgstr "Pelaajamäärä:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:67 +msgid "Number of bots:" +msgstr "Bottien lukumäärä:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:71 +msgid "Bot skill:" +msgstr "Bottien taitotaso:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:74 +msgid "Botlike" +msgstr "Typerä kone" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:75 +msgid "Beginner" +msgstr "Aloittelija" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:76 +msgid "You will win" +msgstr "Helppo voitto" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:77 +msgid "You can win" +msgstr "Helpohko" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:78 +msgid "You might win" +msgstr "Keskitaso" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:79 +msgid "Advanced" +msgstr "Kehittynyt" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:80 +msgid "Expert" +msgstr "Ekspertti" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:81 +msgid "Pro" +msgstr "Mestari" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:82 +msgid "Assassin" +msgstr "Murhaaja" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:83 +msgid "Unhuman" +msgstr "Epäinhimillinen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:84 +msgid "Godlike" +msgstr "Jumalainen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:88 +msgid "Mutators..." +msgstr "Muokkaukset..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:97 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:57 +msgid "Advanced settings..." +msgstr "Edistyneet asetukset..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:104 +msgid "Map list:" +msgstr "Karttalista" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:110 +msgid "Select all" +msgstr "Valitse kaikki" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:113 +msgid "Select none" +msgstr "Poista kaikki valinnat" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:119 +msgid "Start Multiplayer!" +msgstr "Aloita moninpeli!" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:154 +msgid "Capture limit:" +msgstr "Lipunryöstöraja" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:158 +msgid "Lives:" +msgstr "Elämät:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:159 +msgid "Laps:" +msgstr "Kierrokset:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:160 +msgid "Goals:" +msgstr "Maalit:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:164 +msgid "Frag limit:" +msgstr "Tapporaja:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:6 +msgid "Advanced server settings" +msgstr "Kehittyneet palvelinasetukset" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:25 +msgid "Game settings:" +msgstr "Peliasetukset:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:28 +msgid "Allow spectating" +msgstr "Salli sivustakatsominen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:31 +msgid "Spawn shield:" +msgstr "Uudelleensyntymissuoja:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:36 +msgid "Game speed:" +msgstr "Pelinopeus:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:40 +msgid "Teamplay settings:" +msgstr "Joukkuepeliasetukset:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:43 +msgid "Friendly fire scale:" +msgstr "Joukkuevahingon skaala:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:47 +msgid "Virtual friendly fire (effect only)" +msgstr "Virtuaalinen joukkuevahinko (vain efekti)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:50 +msgid "Friendly fire penalty:" +msgstr "Joukkuevahinkorangaistus:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:54 +msgid "Virtual penalty (effect only)" +msgstr "Virtuaalinen rangaistus (vain efekti)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:57 +msgid "Teams:" +msgstr "Joukkueet:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:66 +msgid "Map voting:" +msgstr "Kartan äänestys:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:68 +msgid "No voting" +msgstr "Ei äänestystä" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:69 +msgid "2 choices" +msgstr "2 valintaa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:70 +msgid "3 choices" +msgstr "3 valintaa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:71 +msgid "4 choices" +msgstr "4 valintaa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:72 +msgid "5 choices" +msgstr "5 valintaa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:73 +msgid "6 choices" +msgstr "6 valintaa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:74 +msgid "7 choices" +msgstr "7 valintaa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:75 +msgid "8 choices" +msgstr "8 valintaa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:76 +msgid "9 choices" +msgstr "9 valintaa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:79 +msgid "Simple majority wins vcall" +msgstr "Suurempi äänimäärä voittaa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:5 +msgid "Map Information" +msgstr "Kartan tiedot" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "Full item placement" +msgstr "Esineiden täysi sijoittaminen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "MinstaGib only" +msgstr "Vain MinstaGib" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:78 +msgid "Title:" +msgstr "Otsikko:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:84 +msgid "Author:" +msgstr "Tekijä:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:90 +msgid "Features:" +msgstr "Ominaisuudet:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:95 +msgid "Game types:" +msgstr "Pelityypit:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:118 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:314 +msgid "Close" +msgstr "Sulje" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:121 +msgid "MAP^Play" +msgstr "Pelaa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:7 +msgid "Mutators" +msgstr "Muokatut pelitilat" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:33 +msgid "All Weapons Arena" +msgstr "Kaikkien aseiden taistelukenttä" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:35 +msgid "Most Weapons Arena" +msgstr "Suurimman osan aseiden taistelukenttä" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:56 +#, c-format +msgid "%s Arena" +msgstr "%s taistelukenttä" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:68 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:167 +msgid "Dodging" +msgstr "Väistely" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:70 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:250 +msgid "MinstaGib" +msgstr "MinstaGib" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:253 +msgid "NIX" +msgstr "NIX" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:74 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:205 +msgid "Rocket Flying" +msgstr "Rakettilentely" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:78 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:264 +msgid "No start weapons" +msgstr "Ei aloitusasetta" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:80 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:189 +msgid "Low gravity" +msgstr "Vajaa painovoima" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:170 +msgid "Cloaked" +msgstr "Näkymätön" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:84 +msgid "Hook" +msgstr "Köysi" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:86 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:173 +msgid "Midair" +msgstr "Jalat irti maasta" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:88 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:176 +msgid "Vampire" +msgstr "Vampyyri" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:90 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:208 +msgid "Piñata" +msgstr "Piñata" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:92 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:211 +msgid "Weapons stay" +msgstr "Aseet jäävät" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:94 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:180 +msgid "Blood loss" +msgstr "Verenvuodatus" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:96 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:202 +msgid "Jet pack" +msgstr "Rakettireppu" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:98 +msgid "MUT^None" +msgstr "MUT^Ei mitään" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:164 +msgid "Gameplay mutators:" +msgstr "Pelityylin muokkaukset:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:196 +msgid "Weapon & item mutators:" +msgstr "Aseiden ja esineiden muokkaukset:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:199 +msgid "Grappling hook" +msgstr "Köysi" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:215 +msgid "Weapon arenas:" +msgstr "Tietyn aseen taistelukenttä" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:218 +msgid "Regular (no arena)" +msgstr "Perinteinen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:239 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:256 +msgid "with laser" +msgstr "laserilla" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:247 +msgid "Special arenas:" +msgstr "Erikoistaistelukentät:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:260 +msgid "Most weapons" +msgstr "Suurin osa aseista" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:4 +msgid "Demo" +msgstr "Demo" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:28 +msgid "Record demos while playing" +msgstr "Tallenna demoja pelin aikana" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:32 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:28 +msgid "Filter:" +msgstr "Suodatin:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:29 +#: qcsrc/menu/xonotic/dialog_settings_input.c:41 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:24 +msgid "Clear" +msgstr "Tyhjennä" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:43 +msgid "Timedemo" +msgstr "Aikademo" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:46 +msgid "DEMO^Play" +msgstr "Pelaa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:4 +msgid "Join" +msgstr "Liity" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:36 +msgid "SRVS^Empty" +msgstr "SRVS^Tyhjä" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:40 +msgid "SRVS^Full" +msgstr "SRVS^Täynnä" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:44 +msgid "Pause" +msgstr "Keskeytä" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:56 +msgid "Address:" +msgstr "Osoite:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:67 +msgid "Info..." +msgstr "Tietoa..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:317 +msgid "Join!" +msgstr "Liity!" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:5 +msgid "Server Information" +msgstr "Palvelimen tiedot" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:115 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:116 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:183 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:189 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:199 +msgid "N/A" +msgstr "N/A" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:158 +#, c-format +msgid "%d/%d, %d free player slots" +msgstr "%d/%d, %d vapaata pelaajapaikkaa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +#, c-format +msgid "%d modified settings" +msgstr "%d muokattua asetusta" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +msgid "Official settings" +msgstr "Viralliset asetukset" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:197 +msgid "N/A (can't connect)" +msgstr "N/A (ei voida yhdistää)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:205 +msgid "not supported (can't connect)" +msgstr "ei tuettu (ei voida yhdistää)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:207 +msgid "not supported (won't encrypt)" +msgstr "ei tuettu (salaus ei onnistu)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:211 +msgid "supported (will encrypt)" +msgstr "tuettu (salaus onnistuu)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:213 +msgid "supported (won't encrypt)" +msgstr "tuettu (salaus ei onnistu)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:217 +msgid "requested (will encrypt)" +msgstr "pyydetty (salaus onnistuu)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:219 +msgid "requested (won't encrypt)" +msgstr "pyydetty (salaus ei onnistu)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:223 +msgid "required (can't connect)" +msgstr "vaadittu (ei voida yhdistää)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:225 +msgid "required (will encrypt)" +msgstr "vaadittu (salaus onnistuu)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:246 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:269 +msgid "Players:" +msgstr "Pelaajat:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:254 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:38 +msgid "Type:" +msgstr "Tyyppi:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:259 +msgid "Map:" +msgstr "Kartta:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:264 +msgid "Gameplay:" +msgstr "Pelitila:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:274 +msgid "Bots:" +msgstr "Botit:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:279 +msgid "Mod:" +msgstr "Modi:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:284 +msgid "Version:" +msgstr "Versio:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:289 +msgid "Ping:" +msgstr "Viive:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:295 +msgid "CA:" +msgstr "CA:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:301 +msgid "Key:" +msgstr "Avain:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:307 +msgid "Encryption:" +msgstr "Salaus:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:63 +msgid "Model:" +msgstr "Hahmo:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:88 +msgid "Field of view:" +msgstr "Näkökenttä:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:92 +msgid "View bobbing:" +msgstr "Näytä huojunta:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:96 +msgid "Zoom factor:" +msgstr "Tarkennuskerroin:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:100 +msgid "Zoom speed:" +msgstr "Tarkennuksen nopeus:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:103 +msgid "Weapon settings..." +msgstr "Aseiden asetukset..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:110 +msgid "Crosshair:" +msgstr "Tähtäin:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:111 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:139 +msgid "Per weapon" +msgstr "Asekohtainen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:130 +msgid "Crosshair size:" +msgstr "Tähtäimen suuruus:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:134 +msgid "Crosshair alpha:" +msgstr "Tähtäimen alpha:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:138 +msgid "Crosshair color:" +msgstr "Tähtäimen väri:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:140 +msgid "By health" +msgstr "Elämän mukaan" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:143 +msgid "Custom" +msgstr "Omavalintainen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:148 +msgid "Enable center dot" +msgstr "Ota tähtäin käyttöön" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:151 +msgid "Size:" +msgstr "Koko:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:158 +msgid "Hit test:" +msgstr "Osumatesti:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:159 +msgid "HTST^None" +msgstr "HTST^Ei mitään." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:160 +msgid "TrueAim" +msgstr "TrueAim" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:161 +msgid "Enemies" +msgstr "Viholliset" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:164 +msgid "Waypoints setup..." +msgstr "Välimatkojen asetukset..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:169 +msgid "Enter HUD editor" +msgstr "Muokkaa näkymää" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:174 +msgid "Force models:" +msgstr "Pakota hahmojen ulkomuoto samanlaiseksi:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:175 +msgid "MDL^None" +msgstr "MDL^Ei mitään." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:176 +msgid "MDL^Custom" +msgstr "MDL^Omavalintainen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:177 +msgid "MDL^All" +msgstr "MDL^Kaikki" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:180 +msgid "Disable gore effects" +msgstr "Ota ylimitoitettu raakuus pois päältä" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:182 +msgid "Gibs:" +msgstr "Raajat:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:184 +msgid "GIBS^None" +msgstr "GIBS^Ei mitään" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:185 +msgid "GIBS^Few" +msgstr "GIBS^Vähän" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:186 +msgid "GIBS^Many" +msgstr "GIBS^Paljon" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:187 +msgid "GIBS^Lots" +msgstr "GIBS^Runsaasti" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:191 +msgid "Damage splash:" +msgstr "Veriroiskeet" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:195 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:173 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:194 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:30 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:41 +#: qcsrc/menu/xonotic/dialog_settings_video.c:109 +msgid "Apply immediately" +msgstr "Ota heti käyttöön" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:5 +msgid "Waypoints" +msgstr "Välietapit" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:23 +msgid "Show base waypoints" +msgstr "Näytä tukikohtien välimatkat" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:25 +msgid "Waypoint scale:" +msgstr "Välietappien skaala:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:29 +msgid "Waypoint alpha:" +msgstr "Välietappien alpha:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:34 +msgid "Show names:" +msgstr "Näytä nimet:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:37 +msgid "Teammates" +msgstr "Oma joukkue" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:38 +msgid "All players" +msgstr "Kaikki pelaajat" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:6 +msgid "Weapon settings" +msgstr "Aseiden asetukset" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:29 +msgid "Weapon priority list:" +msgstr "Aseiden prioriteetti:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:34 +msgid "Up" +msgstr "Ylös" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:37 +msgid "Down" +msgstr "Alas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:41 +msgid "Use priority list for weapon cycling" +msgstr "Käytä prioriteettiä aseiden vaihdossa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:43 +msgid "Auto switch weapons on pickup" +msgstr "Vaihda ase automaattisesti poimimisen jälkeen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:45 +msgid "Draw 1st person weapon model" +msgstr "Piirrä ensimmäisen persoonan asemalli" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:55 +msgid "Flip view horizontally" +msgstr "Käännä näkymä horisontaalisesti" + +#: qcsrc/menu/xonotic/dialog_news.c:4 +msgid "News" +msgstr "Uutiset" + +#: qcsrc/menu/xonotic/dialog_news.c:18 +msgid "http://www.xonotic.org/team/blog/" +msgstr "http://www.xonotic.org/team/blog/" + +#: qcsrc/menu/xonotic/dialog_quit.c:4 +msgid "Quit" +msgstr "Lopeta" + +#: qcsrc/menu/xonotic/dialog_quit.c:17 +msgid "Are you sure you want to quit?" +msgstr "Haluatko aivan varmasti lopettaa pelin?" + +#: qcsrc/menu/xonotic/dialog_quit.c:20 +msgid "Yes" +msgstr "Kyllä" + +#: qcsrc/menu/xonotic/dialog_quit.c:21 +msgid "No" +msgstr "Ei" + +#: qcsrc/menu/xonotic/dialog_settings.c:4 +msgid "Settings" +msgstr "Asetukset" + +#: qcsrc/menu/xonotic/dialog_settings.c:18 +#: qcsrc/menu/xonotic/dialog_settings_input.c:4 +msgid "Input" +msgstr "Ohjaus" + +#: qcsrc/menu/xonotic/dialog_settings.c:19 +#: qcsrc/menu/xonotic/dialog_settings_video.c:4 +msgid "Video" +msgstr "Video" + +#: qcsrc/menu/xonotic/dialog_settings.c:20 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:4 +msgid "Effects" +msgstr "Effektit" + +#: qcsrc/menu/xonotic/dialog_settings.c:21 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:4 +msgid "Audio" +msgstr "Ääni" + +#: qcsrc/menu/xonotic/dialog_settings.c:22 +#: qcsrc/menu/xonotic/dialog_settings_network.c:4 +msgid "Network" +msgstr "Verkko" + +#: qcsrc/menu/xonotic/dialog_settings.c:23 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:4 +msgid "Misc" +msgstr "Sekalainen" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:27 +msgid "Master:" +msgstr "Pääkanava:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:33 +msgid "Music:" +msgstr "Musiikki:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:41 +msgid "VOL^Ambient:" +msgstr "VOL^Ympäristö:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:48 +msgid "Info:" +msgstr "Tiedoitukset:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:55 +msgid "Items:" +msgstr "Esineet:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:62 +msgid "Pain:" +msgstr "Kipu:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:69 +msgid "Player:" +msgstr "Pelaaja:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:76 +msgid "Shots:" +msgstr "Laukaukset:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:83 +msgid "Voice:" +msgstr "Puhe:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:91 +msgid "Weapons:" +msgstr "Aseet:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:98 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:156 +msgid "Frequency:" +msgstr "Taajuus:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:100 +msgid "8 kHz" +msgstr "8 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:101 +msgid "11.025 kHz" +msgstr "11.025 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:102 +msgid "16 kHz" +msgstr "16 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:103 +msgid "22.05 kHz" +msgstr "22.05 Khz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:104 +msgid "24 kHz" +msgstr "24 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:105 +msgid "32 kHz" +msgstr "32 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:106 +msgid "44.1 kHz" +msgstr "44.1 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:107 +msgid "48 kHz" +msgstr "48 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:110 +msgid "Channels:" +msgstr "Kanavat:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:112 +msgid "Mono" +msgstr "Mono" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:113 +msgid "Stereo" +msgstr "Stereo" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:114 +msgid "2.1" +msgstr "2.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:115 +msgid "4" +msgstr "4" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:116 +msgid "5" +msgstr "5" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:117 +msgid "5.1" +msgstr "5.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:118 +msgid "6.1" +msgstr "6.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:119 +msgid "7.1" +msgstr "7.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:123 +msgid "Swap Stereo" +msgstr "Vaihda stereoäänilähteiden paikkaa" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:127 +msgid "Headphone friendly mode" +msgstr "Kuulokeystävällinen tila" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:131 +msgid "Spatial voices:" +msgstr "Tilanneäänet:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:132 +msgid "VOCS^None" +msgstr "VOCS^Ei mitään" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:133 +msgid "VOCS^Taunts" +msgstr "VOCS^Huudahdukset" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:134 +msgid "VOCS^All" +msgstr "VOCS^Kaikki" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:137 +msgid "Taunt range:" +msgstr "Huudahduksen kantama" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:140 +msgid "RNG^Very short" +msgstr "RNG^Hyvin lyhyt" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:141 +msgid "RNG^Short" +msgstr "RNG^Lyhyt" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:142 +msgid "RNG^Normal" +msgstr "RNG^Normaali" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:143 +msgid "RNG^Long" +msgstr "RNG^Pitkä" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:144 +msgid "RNG^Full" +msgstr "RNG^Täysi" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:151 +msgid "Automatic taunts" +msgstr "Automaattiset huudahdukset" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:160 +msgid "Time warning:" +msgstr "Aikavaroitus:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:162 +msgid "WRN^None" +msgstr "WRN^Ei mitään" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:163 +msgid "1 minute" +msgstr "1 minuutti" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:164 +msgid "5 minutes" +msgstr "5 minuuttia" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:165 +msgid "WRN^Both" +msgstr "WRN^Molemmat" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:168 +msgid "Hit indicator" +msgstr "Osumailmaisin" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:170 +msgid "Menu sounds" +msgstr "Valikon äänet" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:38 +msgid "Quality preset:" +msgstr "Laadun esiasetus:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:41 +msgid "PRE^OMG!" +msgstr "PRE^Nörtti" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:42 +msgid "PRE^Low" +msgstr "PRE^Matala" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:43 +msgid "PRE^Medium" +msgstr "PRE^Keskitaso" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:44 +msgid "PRE^Normal" +msgstr "PRE^Normaali" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:45 +msgid "PRE^High" +msgstr "PRE^Korkea" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:46 +msgid "PRE^Ultra" +msgstr "PRE^Hyvin korkea" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:48 +msgid "PRE^Ultimate" +msgstr "PRE^Äärimmäinen" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:52 +msgid "Geometry detail:" +msgstr "Geometriset yksityiskohdat:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:54 +msgid "DET^Lowest" +msgstr "DET^Matalin" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:55 +msgid "DET^Low" +msgstr "DET^Matala" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:56 +msgid "DET^Normal" +msgstr "DET^Normaali" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:57 +msgid "DET^Good" +msgstr "DET^Hyvä" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:58 +msgid "DET^Best" +msgstr "DET^Paras" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:59 +msgid "DET^Insane" +msgstr "DET^Sekopäinen" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:62 +msgid "Antialiasing:" +msgstr "Reunojenpehmennys (Antialiasing):" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:64 +msgid "AA^Disabled" +msgstr "AA^Pois päältä" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:65 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:103 +msgid "2x" +msgstr "2x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:66 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:104 +msgid "4x" +msgstr "4x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:70 +msgid "Texture resolution:" +msgstr "Tekstuurien tarkkuus:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:73 +msgid "RES^Leet" +msgstr "RES^Leet" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:74 +msgid "RES^Lowest" +msgstr "RES^Matalin" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:75 +msgid "RES^Low" +msgstr "RES^Matala" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:76 +msgid "RES^Normal" +msgstr "RES^Normaali" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:77 +msgid "RES^Good" +msgstr "RES^Hyvä" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:78 +msgid "RES^Best" +msgstr "RES^Paras" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:91 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:94 +msgid "Avoid lossy texture compression" +msgstr "Vältä häviöllistä tekstuurien pakkaamista" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:100 +msgid "Anisotropy:" +msgstr "Anisotropia:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:102 +msgid "ANISO^Disabled" +msgstr "ANISO^Pois päältä" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:105 +msgid "8x" +msgstr "8x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:106 +msgid "16x" +msgstr "16x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:110 +msgid "Particle quality:" +msgstr "Kappaleiden laatu:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:113 +msgid "Particle distance:" +msgstr "Kappaleiden etäisyys:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:117 +msgid "Decals" +msgstr "Siirtokuvat" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:118 +msgid "Decals on models" +msgstr "Hahmojen siirtokuvat" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:122 +msgid "Distance:" +msgstr "Etäisyys:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:128 +msgid "Time:" +msgstr "Kesto:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:134 +msgid "Use lightmaps" +msgstr "Käytä valaistuksia" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:135 +msgid "Deluxe mapping" +msgstr "Pikselikohtainen valaistus" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:137 +msgid "Gloss" +msgstr "Kiilto" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:140 +msgid "Offset mapping" +msgstr "Korosta tekstuurien kuhmuja" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:142 +msgid "Relief mapping" +msgstr "Tehokas tekstuurien kuhmujen korostus" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:145 +msgid "Reflections:" +msgstr "Heijastukset:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:148 +msgid "Blurred" +msgstr "Sumea" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:149 +msgid "REFL^Good" +msgstr "REFL^Hyvä" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:150 +msgid "Sharp" +msgstr "Terävä" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:155 +msgid "Show surfaces" +msgstr "Näytä pinnat" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:157 +msgid "No dynamic lighting" +msgstr "Ei dynaamista valaistusta" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:159 +msgid "Flash blend approximation" +msgstr "Yksinkertaiset valot" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:161 +msgid "Realtime dynamic lighting" +msgstr "Reaaliaikainen dynaaminen valaitus" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:162 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:166 +msgid "Shadows" +msgstr "Varjot" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:165 +msgid "Realtime world lighting" +msgstr "Reaaliaikainen ympäristön valaistus" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:170 +msgid "Use normal maps" +msgstr "Käytä tekstuurien suunnattua varjostamista" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:172 +msgid "Soft shadows" +msgstr "Pehmeät varjot" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:175 +msgid "Coronas" +msgstr "Valokehät" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:176 +msgid "Use Occlusion Queries" +msgstr "Käytä Occlusion Queryä" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:178 +msgid "Bloom" +msgstr "Hehku" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:180 +msgid "High Dynamic Range (HDR)" +msgstr "HDR" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:184 +msgid "Motion blur:" +msgstr "Liikesumeus:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:189 +msgid "Blur and sharpen postprocessing" +msgstr "Sumenna ja terävöitä jälkikäsittelyä" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:26 +msgid "Key bindings:" +msgstr "Näppäimet:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:31 +msgid "Change key..." +msgstr "Vaihda näppäin..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:35 +msgid "Edit..." +msgstr "Muokkaa..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:46 +msgid "Sensitivity:" +msgstr "Herkkyys:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:51 +msgid "UI mouse speed:" +msgstr "Käyttöliittymän hiiren nopeus:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:55 +msgid "Mouse filter" +msgstr "Hiiren suodatin" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:57 +msgid "Invert mouse" +msgstr "Käännä hiiren suunta" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:60 +#: qcsrc/menu/xonotic/dialog_settings_input.c:62 +msgid "Use joystick input" +msgstr "Käytä peliohjainta" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:65 +#: qcsrc/menu/xonotic/dialog_settings_input.c:67 +msgid "Turn off OS mouse acceleration" +msgstr "Laita käyttöjärjestelmän hiiren kiihtyvyys pois päältä" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:69 +msgid "\"enter console\" also closes" +msgstr "\"avaa komentorivi\" myös sulkee komentorivin" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:5 +msgid "User defined key bind" +msgstr "Käyttäjän määrittelemä näppäinasetus" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:42 +msgid "Command when pressed:" +msgstr "Komento painaessa:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:45 +msgid "Command when released:" +msgstr "Komento painamisen jälkeen:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:48 +msgid "Save" +msgstr "Tallenna" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:51 +msgid "Cancel" +msgstr "Peruuta" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:26 +msgid "Menu skins:" +msgstr "Päävalikon ulkoasu:" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:47 +msgid "Show current time" +msgstr "Näytä nykyinen kellonaika" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:49 +msgid "Show current date" +msgstr "Näytä nykyinen päivämäärä" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:51 +msgid "Show frames per second" +msgstr "Näytä ruudunpäivitysnopeus (FPS)" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:53 +msgid "Minimize input latency" +msgstr "Minimoi syötteen viive" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:5 +msgid "Advanced settings" +msgstr "Edistyneet asetukset" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:23 +msgid "Cvar filter:" +msgstr "Cvar suodatin" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:34 +msgid "Setting:" +msgstr "Asetus:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:42 +msgid "Value:" +msgstr "Arvo:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:56 +msgid "Description:" +msgstr "Kuvaus:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:26 +msgid "Client-side movement prediction" +msgstr "Asiakasohjelman liikkeen ennustus" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:30 +msgid "Show netgraph" +msgstr "Näytä verkkograafi" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:33 +msgid "Network speed:" +msgstr "Verkon nopeus:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:35 +msgid "56k" +msgstr "56k" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:36 +msgid "ISDN" +msgstr "ISDN" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:37 +msgid "Slow ADSL" +msgstr "Hidas ASL" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:38 +msgid "Fast ADSL" +msgstr "Nopea ADSL" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:39 +msgid "Broadband" +msgstr "Laajakaista" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:42 +msgid "Input packets/s:" +msgstr "Vastaanottopaketit /s:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:46 +msgid "HTTP downloads:" +msgstr "HTTP lataukset:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:49 +msgid "Downloads:" +msgstr "Lataukset:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:53 +msgid "Speed (kB/s):" +msgstr "Nopeus (kb/s)" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:57 +msgid "Client UDP port:" +msgstr "Asiakkaan UDP portti" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:26 +msgid "Resolution:" +msgstr "Näytön tarkkuus:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:29 +msgid "Font/UI size:" +msgstr "Kirjainten/käyttöliittymän koko:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:31 +msgid "SZ^Unreadable" +msgstr "SZ^Miltein näkymätön" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:32 +msgid "SZ^Tiny" +msgstr "SZ^Pikkuruinen" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:33 +msgid "SZ^Little" +msgstr "SZ^Hyvin pieni" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:34 +msgid "SZ^Small" +msgstr "SZ^Pieni" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:35 +msgid "SZ^Medium" +msgstr "SZ^Keskikokoinen" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:36 +msgid "SZ^Large" +msgstr "SZ^Suuri" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:37 +msgid "SZ^Huge" +msgstr "SZ^Valtava" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:38 +msgid "SZ^Gigantic" +msgstr "SZ^Jättiläismäinen" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:39 +msgid "SZ^Colossal" +msgstr "SZ^Massiivinen" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:42 +msgid "Color depth:" +msgstr "Värisävy:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:45 +msgid "Full screen" +msgstr "Kokoruutu" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:46 +msgid "Vertical Synchronization" +msgstr "Pystytahdistus (VSYNC)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:49 +msgid "Use OpenGL 2.0 shaders (GLSL)" +msgstr "Käytä OpenGL 2.0 shaders-varjostuksia (GLSL)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:52 +msgid "Use GLSL to handle color control" +msgstr "Käytä GLSL:ää värien hallinnassa" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:56 +msgid "Vertex Buffer Objects (VBOs)" +msgstr "Vertex Buffer Object (VBO)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:59 +msgid "VBO^Off" +msgstr "VBO^Pois" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:60 +msgid "Vertices, some Tris (compatible)" +msgstr "Verteksit, vähän kolmioita (yhteensopivin)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:63 +msgid "Vertices" +msgstr "Verteksit" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:64 +msgid "Vertices and Triangles" +msgstr "Verteksit ja kolmiot" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:67 +msgid "Depth first:" +msgstr "Syvyyssuuntainen renderöinti:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:69 +msgid "DF^Disabled" +msgstr "DF^Pois" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:70 +msgid "DF^World" +msgstr "DF^Maailma" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:71 +msgid "DF^All" +msgstr "DF^Kaikki" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:75 +msgid "Disable multithreaded OpenGL" +msgstr "Ota monisäkeinen OpenGL pois päältä" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:77 +msgid "Wait for GPU to finish each frame" +msgstr "Anna näytönohjaimen viimeistellä jokainen ruutu" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:80 +msgid "Brightness:" +msgstr "Kirkkaus:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:83 +msgid "Contrast:" +msgstr "Kontrasti:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:86 +msgid "Gamma:" +msgstr "Gamma:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:91 +msgid "Contrast boost:" +msgstr "Kontrastin lisäys:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:96 +msgid "Saturation:" +msgstr "Kylläisyys:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:102 +msgid "LIT^Ambient:" +msgstr "LIT^Ympäristö:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:105 +msgid "Intensity:" +msgstr "Intensiivisyys:" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:4 +msgid "Singleplayer" +msgstr "Yksinpeli" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:127 +msgid "Instant action! (random map with bots)" +msgstr "Suoraan taisteluun! (satunnainen kartta bottien kera)" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:148 +msgid "Start Singleplayer!" +msgstr "Aloita yksinpeli!" + +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:4 +msgid "Winner" +msgstr "Voittaja" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:5 +msgid "Team Selection" +msgstr "Joukkueen valinta" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:41 +msgid "join 'best' team (auto-select)" +msgstr "liity 'parhaimpaan' joukkueeseen" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:45 +msgid "red" +msgstr "punainen" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:46 +msgid "blue" +msgstr "sininen" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:47 +msgid "yellow" +msgstr "keltainen" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:48 +msgid "pink" +msgstr "pinkki" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:51 +msgid "spectate" +msgstr "seuraa sivusta" + +#: qcsrc/menu/xonotic/mainwindow.c:35 qcsrc/menu/xonotic/mainwindow.c:38 +msgid "Do not press this button again!" +msgstr "Älä paina enää näppäintä!" + +#: qcsrc/menu/xonotic/maplist.c:278 +msgid "" +"Huh? Can't play this (m is NULL). Refiltering so this won't happen again.\n" +msgstr "" +"Höh? Tätä ei voida pelata (m on NULL). Uudelleensuodatetaan jottei vastaava " +"enää toistuisi, anteeksi häiriö.\n" + +#: qcsrc/menu/xonotic/maplist.c:286 +#, c-format +msgid "%s's Xonotic Server" +msgstr "%s Xonotic-palvelin" + +#: qcsrc/menu/xonotic/maplist.c:291 +msgid "" +"Huh? Can't play this (invalid game type). Refiltering so this won't happen " +"again.\n" +msgstr "" +"Höh? Tätä ei voida pelata (epäkelpo pelityyppi). Uudelleensuodatetaan jottei " +"vastaava enää toistuisi.\n" + +#: qcsrc/menu/xonotic/playermodel.c:174 +msgid "<no model found>" +msgstr "<mallia ei löytynyt>" + +#: qcsrc/menu/xonotic/serverlist.c:185 +msgid "Remove" +msgstr "Poista" + +#: qcsrc/menu/xonotic/serverlist.c:187 +msgid "Bookmark" +msgstr "Kirjanmerkki" + +#: qcsrc/menu/xonotic/serverlist.c:527 +msgid "Ping" +msgstr "Viive" + +#: qcsrc/menu/xonotic/serverlist.c:528 +msgid "Host name" +msgstr "Palvelimen nimi" + +#: qcsrc/menu/xonotic/serverlist.c:529 +msgid "Map" +msgstr "Kartta" + +#: qcsrc/menu/xonotic/serverlist.c:530 +msgid "Type" +msgstr "Tyyppi" + +#: qcsrc/menu/xonotic/serverlist.c:531 +msgid "Players" +msgstr "Pelaajat" + +#: qcsrc/menu/xonotic/skinlist.c:105 +msgid "<TITLE>" +msgstr "<TITLE>" + +#: qcsrc/menu/xonotic/skinlist.c:106 +msgid "<AUTHOR>" +msgstr "<AUTHOR>" + +#: qcsrc/menu/xonotic/slider_decibels.c:50 +msgid "VOL^OFF" +msgstr "VOL^OFF" + +#: qcsrc/menu/xonotic/slider_decibels.c:52 +msgid "VOL^MAX" +msgstr "VOL^MAX" + +#: qcsrc/menu/xonotic/slider_decibels.c:53 +#, c-format +msgid "%s dB" +msgstr "%s dB" + +#: qcsrc/menu/xonotic/slider_resolution.c:65 +#, c-format +msgid "%dx%d" +msgstr "%dx%d" + +#: qcsrc/menu/xonotic/util.qc:270 +#, c-format +msgid "Received HTTP request data for an invalid id %d.\n" +msgstr "Vastaanotettiin epäkelpo HTTP datapyyntö: %d.\n" + +#: qcsrc/menu/xonotic/util.qc:285 +#, c-format +msgid "error receiving update notification: status is %d\n" +msgstr "virhe vastaanottaessa päivitystiedotetta: tilanne %d\n" + +#: qcsrc/menu/xonotic/util.qc:290 +msgid "error: received HTML instead of an update notification\n" +msgstr "virhe: vastaanotettiin HTML päivitystiedotteen asemesta\n" + +#: qcsrc/menu/xonotic/util.qc:295 +msgid "error: received carriage returns from update notification server\n" +msgstr "virhe: vastaanotettiin tyhjää dataa päivitystiedotepalvelimelta\n" + +#: qcsrc/menu/xonotic/util.qc:316 +#, c-format +msgid "" +"Update can be downloaded at:\n" +"%s\n" +msgstr "" +"Päivitys on ladattavissa:\n" +"%s\n" + +#: qcsrc/menu/xonotic/util.qc:337 +msgid "Autogenerating mapinfo for newly added maps..." +msgstr "" +"Luodaan automaattisesti karttatietoja vastikään lisätyille kartoille..." + +#: qcsrc/menu/xonotic/util.qc:367 +#, c-format +msgid "^1%s TEST BUILD" +msgstr "^1%s TESTIVERSIO" + +#: qcsrc/menu/xonotic/util.qc:432 +#, c-format +msgid "Update to %s now!" +msgstr "Päivitä versioon %s nyt!" + +#: qcsrc/menu/xonotic/util.qc:501 +msgid "" +"^1ERROR: Texture compression is required but not supported.\n" +"^1Expect visual problems.\n" +msgstr "" +"^1VIRHE: Tekstuurien pakkaus vaaditaan mutta ei ole tuettuna.\n" +"^1Grafiikkavirheitä odotettavissa.\n" + +#: qcsrc/menu/xonotic/util.qc:523 +msgid "Arena" +msgstr "Areena (Arena)" + +#: qcsrc/menu/xonotic/util.qc:524 +msgid "Assault" +msgstr "Rynnäkkö (Assault)" + +#: qcsrc/menu/xonotic/util.qc:525 +msgid "Capture The Flag" +msgstr "Lipunryöstö (CTF)" + +#: qcsrc/menu/xonotic/util.qc:526 +msgid "Clan Arena" +msgstr "Klaaniareena (Clan Arena)" + +#: qcsrc/menu/xonotic/util.qc:527 +msgid "Deathmatch" +msgstr "Mättö (Deathmatch)" + +#: qcsrc/menu/xonotic/util.qc:528 +msgid "Domination" +msgstr "Hallinta (Domination)" + +#: qcsrc/menu/xonotic/util.qc:529 +msgid "Freeze Tag" +msgstr "Pakkashippa (Freeze Tag)" + +#: qcsrc/menu/xonotic/util.qc:530 +msgid "Keepaway" +msgstr "Pakomatka (Keepaway)" + +#: qcsrc/menu/xonotic/util.qc:531 +msgid "Key Hunt" +msgstr "Avaimenetsintä (Key Hunt)" + +#: qcsrc/menu/xonotic/util.qc:532 +msgid "Last Man Standing" +msgstr "Viimeiseen mieheen (Last Man Standing)" + +#: qcsrc/menu/xonotic/util.qc:533 +msgid "Nexball" +msgstr "Nexpallo (Nexball)" + +#: qcsrc/menu/xonotic/util.qc:534 +msgid "Onslaught" +msgstr "Suurtaistelu (Onslaught)" + +#: qcsrc/menu/xonotic/util.qc:535 +msgid "Race" +msgstr "Kilpailu (RACE)" + +#: qcsrc/menu/xonotic/util.qc:536 +msgid "Race CTS" +msgstr "Kilpailu CTS (RACE CTS)" + +#: qcsrc/menu/xonotic/util.qc:537 +msgid "Runematch" +msgstr "Riimu-ottelu (Runematch)" + +#: qcsrc/menu/xonotic/util.qc:538 +msgid "Team Deathmatch" +msgstr "Joukkuemättö (Team Deatchmatch)" + +#: qcsrc/menu/xonotic/util.qc:557 +#, c-format +msgid "@!#%'n Tuba Throwing" +msgstr "@!#% tuubanheitto!" + +#: qcsrc/menu/xonotic/util.qc:577 qcsrc/menu/xonotic/util.qc:593 +#: qcsrc/menu/xonotic/util.qc:602 qcsrc/menu/xonotic/util.qc:610 +#: qcsrc/menu/xonotic/util.qc:622 +msgid "Default" +msgstr "Perusasetus" + +#: qcsrc/menu/xonotic/util.qc:588 +msgid "Use default" +msgstr "Käytä perusasetusta" + +#: qcsrc/menu/xonotic/util.qc:608 +msgid "Team Color:" +msgstr "Joukkueen väri" + +#: qcsrc/menu/xonotic/util.qh:47 +msgid "Enable panel" +msgstr "Ota paneeli käyttöön" + +#: qcsrc/server/w_crylink.qc:2 +msgid "Crylink" +msgstr "Crylink" + +#: qcsrc/server/w_crylink.qc:666 +#, c-format +msgid "%s succeeded at self-destructing themself with the Crylink" +msgstr "%s hautoi itsetuhoisia ajatuksia Crylink kädessä" + +#: qcsrc/server/w_crylink.qc:671 +#, c-format +msgid "%s could not hide from %s's Crylink" +msgstr "%s ei kyennyt pakenemaan pelaajan %s Crylinkkiä" + +#: qcsrc/server/w_crylink.qc:673 +#, c-format +msgid "%s was too close to %s's Crylink" +msgstr "%s oli liian lähellä pelaajan %s ampumarataa" + +#: qcsrc/server/w_crylink.qc:675 +#, c-format +msgid "%s took a close look at %s's Crylink" +msgstr "%s pääsi tutustumaan lähemmin pelaajan %s kauniiseen Crylinkkiin" + +#: qcsrc/server/w_electro.qc:2 +msgid "Electro" +msgstr "Electro" + +#: qcsrc/server/w_electro.qc:574 +#, c-format +msgid "%s could not remember where they put plasma" +msgstr "%s ei sattunut muistamaan minne se plasma oikein kuuluikaan" + +#: qcsrc/server/w_electro.qc:576 +#, c-format +msgid "%s played with plasma" +msgstr "%s leikki plasmalla, ei hyvä" + +#: qcsrc/server/w_electro.qc:583 +#, c-format +msgid "%s just noticed %s's blue ball" +msgstr "%s näki pelaajan %s sinisen pallon" + +#: qcsrc/server/w_electro.qc:585 +#, c-format +msgid "%s got in touch with %s's blue ball" +msgstr "%s pääsi tutustumaan pelaajan %s siniseen palloon" + +#: qcsrc/server/w_electro.qc:590 +#, c-format +msgid "%s felt the electrifying air of %s's combo" +msgstr "%s tunsi sähköä ilmassa pelaajan %s tulituksen jälkeen" + +#: qcsrc/server/w_electro.qc:592 +#, c-format +msgid "%s got too close to %s's blue beam" +msgstr "%s joutui liian lähelle pelaajan %s sinistä sädettä" + +#: qcsrc/server/w_electro.qc:594 +#, c-format +msgid "%s was blasted by %s's blue beam" +msgstr "%s posahti pelaajan %s siniseen säteeseen" + +#: qcsrc/server/w_fireball.qc:2 +msgid "Fireball" +msgstr "Fireball" + +#: qcsrc/server/w_fireball.qc:417 +#, c-format +msgid "%s forgot about some firemine" +msgstr "%s unohti tulimiinansa" + +#: qcsrc/server/w_fireball.qc:419 qcsrc/server/w_hlac.qc:240 +#, c-format +msgid "%s should have used a smaller gun" +msgstr "%s olisi pitänyt käyttää pienempää asetta" + +#: qcsrc/server/w_fireball.qc:426 +#, c-format +msgid "%s tried to catch %s's firemine" +msgstr "%s koetti napata pelaajan %s tulimiinan" + +#: qcsrc/server/w_fireball.qc:428 +#, c-format +msgid "%s fatefully ignored %s's firemine" +msgstr "%s kohtalokkaasti tutustui pelaajan %s tulimiinaan" + +#: qcsrc/server/w_fireball.qc:435 +#, c-format +msgid "%s could not hide from %s's fireball" +msgstr "%s ei kyennyt pakenemaan pelaajan %s tulipalloa" + +#: qcsrc/server/w_fireball.qc:437 +#, c-format +msgid "%s saw the pretty lights of %s's fireball" +msgstr "&s näki kauniita valoja pelaajan %s tulipallosta" + +#: qcsrc/server/w_fireball.qc:440 +#, c-format +msgid "%s got too close to %s's fireball" +msgstr "%s joutui turhan lähelle pelaajan %s tulipalloa" + +#: qcsrc/server/w_fireball.qc:442 +#, c-format +msgid "%s tasted %s's fireball" +msgstr "%s maistoi pelaajan %s tulipalloa" + +#: qcsrc/server/w_grenadelauncher.qc:2 +msgid "Mortar" +msgstr "Mortar" + +#: qcsrc/server/w_grenadelauncher.qc:383 +#, c-format +msgid "%s tried out his own grenade" +msgstr "%s testasi räjähtääkö oma kranaatti" + +#: qcsrc/server/w_grenadelauncher.qc:385 +#, c-format +msgid "%s detonated" +msgstr "%s pössähti" + +#: qcsrc/server/w_grenadelauncher.qc:391 +#, c-format +msgid "%s didn't see %s's grenade" +msgstr "%s ei nähnyt pelaajan %s kranaattia" + +#: qcsrc/server/w_grenadelauncher.qc:393 +#, c-format +msgid "%s almost dodged %s's grenade" +msgstr "%s väisti melkein pelaajan %s kranaatin" + +#: qcsrc/server/w_grenadelauncher.qc:395 +#, c-format +msgid "%s ate %s's grenade" +msgstr "%s söi pelaajan %s kranaatin" + +#: qcsrc/server/w_hagar.qc:2 +msgid "Hagar" +msgstr "Hagar" + +#: qcsrc/server/w_hagar.qc:395 qcsrc/server/w_seeker.qc:655 +#, c-format +msgid "%s played with tiny rockets" +msgstr "%s leikki pienien rakettien kanssa" + +#: qcsrc/server/w_hagar.qc:399 +#, c-format +msgid "%s hoped %s's missiles wouldn't bounce" +msgstr "%s toivoi ettei pelaajan %s raketit olisi kimmonneet" + +#: qcsrc/server/w_hagar.qc:401 qcsrc/server/w_seeker.qc:661 +#, c-format +msgid "%s was pummeled by %s" +msgstr "%s joutui pelaajan %s nuijimaksi" + +#: qcsrc/server/w_hlac.qc:2 +msgid "Heavy Laser Assault Cannon" +msgstr "HLAC" + +#: qcsrc/server/w_hlac.qc:242 +#, c-format +msgid "%s was cut down by %s" +msgstr "%s joutui pelaajan %s niittämäksi" + +#: qcsrc/server/w_hook.qc:2 +msgid "Grappling Hook" +msgstr "Grabbling Hook" + +#: qcsrc/server/w_hook.qc:266 qcsrc/server/w_porto.qc:296 +#, c-format +msgid "%s did the impossible" +msgstr "%s teki mahdottomat" + +#: qcsrc/server/w_hook.qc:268 +#, c-format +msgid "%s has run into %s's gravity bomb" +msgstr "%s juoksi pelaajan %s pommiin" + +#: qcsrc/server/w_laser.qc:2 +msgid "Laser" +msgstr "Laser" + +#: qcsrc/server/w_laser.qc:311 +#, c-format +msgid "%s lasered themself to hell" +msgstr "%s lähetti itsensä laserilla helvettiin" + +#: qcsrc/server/w_laser.qc:315 +#, c-format +msgid "%s was cut in half by %s's gauntlet" +msgstr "%s leikkaantui kahtia pelaajan %s taisteluhansikkaaseen" + +#: qcsrc/server/w_laser.qc:317 +#, c-format +msgid "%s was lasered to death by %s" +msgstr "%s kuoli pelaajan %s laseriin" + +#: qcsrc/server/w_minelayer.qc:2 +msgid "Mine Layer" +msgstr "Mine Layer" + +#: qcsrc/server/w_minelayer.qc:523 qcsrc/server/w_rocketlauncher.qc:501 +#, c-format +msgid "%s exploded" +msgstr "%s räjähti" + +#: qcsrc/server/w_minelayer.qc:527 +#, c-format +msgid "%s got too close to %s's mine" +msgstr "%s joutui liian lähelle pelaajan %s miinaa" + +#: qcsrc/server/w_minelayer.qc:529 +#, c-format +msgid "%s almost dodged %s's mine" +msgstr "%s miltein väisti pelaajan %s miinan" + +#: qcsrc/server/w_minelayer.qc:531 +#, c-format +msgid "%s stepped on %s's mine" +msgstr "%s astui pelaajan %s miinaan" + +#: qcsrc/server/w_minstanex.qc:2 +msgid "MinstaNex" +msgstr "MinstaNex" + +#: qcsrc/server/w_minstanex.qc:293 qcsrc/server/w_nex.qc:253 +#: qcsrc/server/w_shotgun.qc:215 qcsrc/server/w_uzi.qc:317 +#, c-format +msgid "%s is now thinking with portals" +msgstr "%s kokee portaalit" + +#: qcsrc/server/w_minstanex.qc:295 qcsrc/server/w_nex.qc:255 +#, c-format +msgid "%s has been vaporized by %s" +msgstr "%s höyrystyi pelaajan %s toimesta" + +#: qcsrc/server/w_nex.qc:2 +msgid "Nex" +msgstr "Nex" + +#: qcsrc/server/w_porto.qc:2 +msgid "Port-O-Launch" +msgstr "Port-O-Launch" + +#: qcsrc/server/w_porto.qc:298 +#, c-format +msgid "%s felt %s doing the impossible to him" +msgstr "%s tunsi kuinka pelaaja %s teki hänelle mahdottoman tempun" + +#: qcsrc/server/w_rifle.qc:2 +msgid "Rifle" +msgstr "Rifle" + +#: qcsrc/server/w_rifle.qc:233 +#, c-format +msgid "%s shot themself automatically" +msgstr "%s ampui itsensä täysin omatoimisesti" + +#: qcsrc/server/w_rifle.qc:235 +#, c-format +msgid "%s sniped themself somehow" +msgstr "%s onnistui jotenkin ampumaan omaan jalkaansa" + +#: qcsrc/server/w_rifle.qc:242 +#, c-format +msgid "%s failed to hide from %s's bullet hail" +msgstr "%s ei kyennyt pakenemaan pelaajan %s luotisadetta" + +#: qcsrc/server/w_rifle.qc:244 +#, c-format +msgid "%s died in %s's bullet hail" +msgstr "%s kuoli pelaajan %s luotisateeseen" + +#: qcsrc/server/w_rifle.qc:251 +#, c-format +msgid "%s failed to hide from %s's rifle" +msgstr "%s ei kyennyt piiloutumaan pelaajan %s kivääriä" + +#: qcsrc/server/w_rifle.qc:256 +#, c-format +msgid "%s got hit in the head by %s" +msgstr "%s sai päähänsä reiän pelaajan %s toimesta" + +#: qcsrc/server/w_rifle.qc:258 qcsrc/server/w_uzi.qc:321 +#, c-format +msgid "%s was sniped by %s" +msgstr "%s ammuttiin alas, kuolonlaukauksen tarjosi %s" + +#: qcsrc/server/w_rocketlauncher.qc:2 +msgid "Rocket Launcher" +msgstr "Rocket Launcher" + +#: qcsrc/server/w_rocketlauncher.qc:505 +#, c-format +msgid "%s got too close to %s's rocket" +msgstr "%s joutui liian lähelle pelaajan %s rakettia" + +#: qcsrc/server/w_rocketlauncher.qc:507 +#, c-format +msgid "%s almost dodged %s's rocket" +msgstr "%s miltein väisti pelaajan %s raketin" + +#: qcsrc/server/w_rocketlauncher.qc:509 +#, c-format +msgid "%s ate %s's rocket" +msgstr "%s söi pelaajan %s raketin" + +#: qcsrc/server/w_seeker.qc:2 +msgid "T.A.G. Seeker" +msgstr "T.A.G. Seeker" + +#: qcsrc/server/w_seeker.qc:659 +#, c-format +msgid "%s was tagged by %s" +msgstr "%s joutui pelaajan %s leimaamaksi ja tuhoamaksi" + +#: qcsrc/server/w_shotgun.qc:2 +msgid "Shotgun" +msgstr "Shotgun" + +#: qcsrc/server/w_shotgun.qc:219 +#, c-format +msgid "%2$s ^7slapped %1$s ^7around a bit with a large ^2shotgun" +msgstr "%2$s ^7murjoi pelaajaa %1$s ^2haulikon tylpällä päällä" + +#: qcsrc/server/w_shotgun.qc:221 +#, c-format +msgid "%s was gunned by %s" +msgstr "%s ammuttiin alas pelaajan %s toimesta" + +#: qcsrc/server/w_tuba.qc:2 +#, c-format +msgid "@!#%'n Tuba" +msgstr "@!#% tuuba" + +#: qcsrc/server/w_tuba.qc:252 +#, c-format +msgid "%s hurt his own ears with the @!#%%'n Tuba" +msgstr "%s tärykalvot räjähti, kun hän soitteli @!#%% tuubaa" + +#: qcsrc/server/w_tuba.qc:256 +#, c-format +msgid "%s died of %s's great playing on the @!#%%'n Tuba" +msgstr "" +"%s kuoli ihastuksesta kuullessaan pelaajan %s kaunista @!#%% tuubansoittoa" + +#: qcsrc/server/w_uzi.qc:2 +msgid "Machine Gun" +msgstr "Machine Gun" + +#: qcsrc/server/w_uzi.qc:323 +#, c-format +msgid "%s was riddled full of holes by %s" +msgstr "%s sai muutaman uuden ilmanvaihtoreiän, kun %s tarjosi niitä" diff --git a/menu.dat.fr.po b/menu.dat.fr.po new file mode 100644 index 0000000000..461ce8b405 --- /dev/null +++ b/menu.dat.fr.po @@ -0,0 +1,2896 @@ +# Xonotic French Translation. +# Copyright (C) 2011 +# This file is distributed under the same license as the PACKAGE package. +# +# Calinou <hugohachel@gmail.com>, 2011. +# Maxime Paradis <taximus.micro@gmail.com>, 2011. +msgid "" +msgstr "" +"Project-Id-Version: Xonotic 0.1preview\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-09-02 07:51+0200\n" +"PO-Revision-Date: 2011-08-23 18:51-0400\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.2\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: qcsrc/common/mapinfo.qc:1092 qcsrc/menu/xonotic/skinlist.c:163 +#, c-format +msgid "%s: %s" +msgstr "%s: %s" + +#: qcsrc/menu/gamecommand.qc:47 +#, c-format +msgid "error: status is %d\n" +msgstr "erreur: le status est %d\n" + +#: qcsrc/menu/gamecommand.qc:65 +msgid "Usage: menu_cmd command..., where possible commands are:\n" +msgstr "Utilisation: menu_cmd commande..., les commandes possibles sont:\n" + +#: qcsrc/menu/gamecommand.qc:66 +msgid " sync - reloads all cvars on the current menu page\n" +msgstr " sync - recharge toutes les variables sur la page actuelle\n" + +#: qcsrc/menu/gamecommand.qc:67 +msgid " directmenu ITEM - select a menu item as main item\n" +msgstr "" +" directmenu OBJET - sélectionner un objet de menu comme objet principal\n" + +#: qcsrc/menu/gamecommand.qc:193 +msgid "error creating curl handle\n" +msgstr "erreur de création du curl handle" + +#: qcsrc/menu/gamecommand.qc:239 +msgid "Invalid command. For a list of supported commands, try menu_cmd help.\n" +msgstr "" +"Commande invalide. Pour une liste des commandes supportées, tapez menu_cmd " +"help (dans la console).\n" + +#: qcsrc/menu/item/gecko.c:49 +msgid "Browser not initialized!" +msgstr "Navigateur non initialisé !" + +#: qcsrc/menu/item/label.c:63 +#, c-format +msgid "NOTE: label text %s too wide for label, condensed by factor %f\n" +msgstr "" +"REMARQUE: le texte label %s est trop large pour un label, condensé par le " +"facteur %f\n" + +#: qcsrc/menu/item/listbox.c:300 +#, c-format +msgid "Item %d" +msgstr "Objet %d" + +#: qcsrc/menu/item/slider.c:64 +#, c-format +msgid "%d (%s)" +msgstr "%d (%s)" + +#: qcsrc/menu/item/textslider.c:29 qcsrc/menu/item/textslider.c:31 +msgid "custom" +msgstr "personnalisé" + +#: qcsrc/menu/menu.qc:29 +#, c-format +msgid "^4MQC Build information: ^1%s\n" +msgstr "^4MQC Information de version : %s (français)\n" + +#: qcsrc/menu/xonotic/campaign.c:284 +#: qcsrc/menu/xonotic/dialog_singleplayer.c:134 +msgid "???" +msgstr "???" + +#: qcsrc/menu/xonotic/campaign.c:285 +#, c-format +msgid "Level %d: %s" +msgstr "Niveau %d: %s" + +#: qcsrc/menu/xonotic/cvarlist.c:85 +msgid "will be saved to config.cfg" +msgstr "sera sauvegardé vers config.cfg" + +#: qcsrc/menu/xonotic/cvarlist.c:87 +msgid "will not be saved" +msgstr "ne sera pas sauvegardé vers config.cfg" + +#: qcsrc/menu/xonotic/cvarlist.c:89 +msgid "private" +msgstr "privé" + +#: qcsrc/menu/xonotic/cvarlist.c:91 +msgid "engine setting" +msgstr "paramètre moteur" + +#: qcsrc/menu/xonotic/cvarlist.c:93 +msgid "read only" +msgstr "lecture seule" + +#: qcsrc/menu/xonotic/dialog_credits.c:5 +msgid "Credits" +msgstr "Crédits" + +#: qcsrc/menu/xonotic/dialog_credits.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:269 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:41 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:57 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:61 +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:21 +msgid "OK" +msgstr "OK" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:4 +msgid "Welcome" +msgstr "Bienvenue" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:33 +msgid "" +"Welcome to Xonotic, please select your language preference and enter your " +"player name to get started. You can change these options later through the " +"menu system." +msgstr "" +"Bienvenue sur Xonotic, veuillez sélectionner votre langue et entrer votre " +"pseudonyme pour commencer. Vous pouvez changer ces options plus tard dans " +"les menus." + +#: qcsrc/menu/xonotic/dialog_firstrun.c:38 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:35 +msgid "Text language:" +msgstr "Langue écran:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:47 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:40 +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:39 +msgid "Name:" +msgstr "Pseudonyme:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:69 +msgid "Save settings" +msgstr "Sauvegarder" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:4 +msgid "Ammo Panel" +msgstr "Panneau de munitions" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:22 +msgid "Ammunition display:" +msgstr "Affichage munitions:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:25 +msgid "Show only current ammo type" +msgstr "Ne montrer que le type de munition actuel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:28 +msgid "Align icon:" +msgstr "Aligner l'icône" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:29 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:36 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:40 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:40 +msgid "Left" +msgstr "Gauche" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:38 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:41 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:41 +msgid "Right" +msgstr "Droite" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:4 +msgid "Centerprint" +msgstr "Écriture du centre" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:23 +msgid "Message duration:" +msgstr "Durée du message:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:27 +msgid "Fade time:" +msgstr "Temps d'effacement d'une entrée:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:31 +msgid "Flip messages order" +msgstr "Inverser l'ordre des notifications" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:33 +msgid "Text alignment:" +msgstr "Alignement icônes:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:37 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:50 +msgid "Center" +msgstr "Centre" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:41 +msgid "Font scale:" +msgstr "Taille de police:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:4 +msgid "Chat Panel" +msgstr "Panneau de Chat" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:22 +msgid "Chat entries:" +msgstr "Entrées Chat:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:25 +msgid "Chat size:" +msgstr "Taille du Chat:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:29 +msgid "Chat lifetime:" +msgstr "Durée du Chat:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:33 +msgid "Chat beep sound" +msgstr "Sons Chat:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:4 +msgid "Engine Info Panel" +msgstr "Panneau Info Moteur" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:22 +msgid "Engine info:" +msgstr "Info Moteur:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:25 +msgid "Use an averaging algorithm for fps" +msgstr "Utiliser un algorithme pour calculer les FPS" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:4 +msgid "Health/Armor Panel" +msgstr "Panneau Santé/Armure" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:22 +msgid "Enable status bar" +msgstr "Activer jauges" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:24 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:24 +msgid "Status bar alignment:" +msgstr "Alignement jauges:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:42 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:42 +msgid "Inward" +msgstr "Intérieur" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:43 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:43 +msgid "Outward" +msgstr "Extérieur" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:37 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:37 +msgid "Icon alignment:" +msgstr "Alignement icônes:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:45 +msgid "Flip health and armor positions" +msgstr "Échanger positions Santé/Armure" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:4 +msgid "Info Messages Panel" +msgstr "Panneau d'Information" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:22 +msgid "Info messages:" +msgstr "Messages d'Info:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:25 +msgid "Flip align" +msgstr "Échanger alignement" + +#: qcsrc/menu/xonotic/dialog_hudpanel_modicons.c:4 +msgid "Mod Icons Panel" +msgstr "Panneau d'Icônes de Mode" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:4 +msgid "Notification Panel" +msgstr "Panneau de Notifications" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:22 +msgid "Notifications:" +msgstr "Notifications:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:25 +msgid "Also print notifications to the console" +msgstr "Montrer notifications sur la console" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:28 +msgid "Flip notify order" +msgstr "Inverser l'ordre de notification" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:31 +msgid "Entry lifetime:" +msgstr "Durée d'une entrée:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:35 +msgid "Entry fadetime:" +msgstr "Temps d'effacement d'une entrée:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:4 +msgid "Physics Panel" +msgstr "Panneau d'effets physiques" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:21 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:21 +msgid "Panel disabled" +msgstr "Panneau désactivé" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:23 +msgid "Panel enabled" +msgstr "Panneau activé" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:24 +msgid "Panel enabled even observing" +msgstr "Panneau activé même en spectateur" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:25 +msgid "Panel enabled only in Race/CTS" +msgstr "Panneau activé seulement en Race/CTS" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:31 +msgid "Status bar" +msgstr "Barre de statut" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:48 +msgid "Left align" +msgstr "À gauche" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:34 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:52 +msgid "Right align" +msgstr "À droite" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:35 +msgid "Inward align" +msgstr "Aligner vers l'intérieur" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:36 +msgid "Outward align" +msgstr "Aligner vers l'extérieur" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:40 +msgid "Flip speed/acceleration positions" +msgstr "Échanger positions Vitesse/Accélération" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:44 +msgid "Speed:" +msgstr "Vitesse:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:45 +msgid "Include vertical speed" +msgstr "Inclure vitesse verticale" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:56 +msgid "Speed unit:" +msgstr "Unité de vitesse" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:58 +msgid "qu/s" +msgstr "qu/s" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:59 +msgid "m/s" +msgstr "m/s" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:60 +msgid "km/h" +msgstr "km/h" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:61 +msgid "mph" +msgstr "mph" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:62 +msgid "knots" +msgstr "noeuds" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:64 +msgid "Show" +msgstr "Montrer" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:67 +msgid "Top speed" +msgstr "Vitesse maximale:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:73 +msgid "Acceleration:" +msgstr "Accélération:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:74 +msgid "Include vertical acceleration" +msgstr "Inclure accélération verticale" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:4 +msgid "Powerups Panel" +msgstr "Panneau des Pouvoirs" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:45 +msgid "Flip strength and shield positions" +msgstr "Échanger les positions Force/Bouclier" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:4 +msgid "Pressed Keys Panel" +msgstr "Panneau Touches Pressées" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:22 +msgid "Panel enabled when spectating" +msgstr "Panneau activé en spectateur" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:23 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:23 +msgid "Panel always enabled" +msgstr "Panneau toujours activé" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:30 +msgid "Forced aspect:" +msgstr "Aspect forcé:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_racetimer.c:4 +msgid "Race Timer Panel" +msgstr "Chronomètre Course" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:4 +msgid "Radar Panel" +msgstr "Panneau Mini-carte" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:22 +msgid "Panel enabled in teamgames" +msgstr "Panneau activé en Équipe" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:29 +msgid "Radar:" +msgstr "Mini-carte:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:32 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:43 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:154 +#: qcsrc/menu/xonotic/util.qc:600 +msgid "Alpha:" +msgstr "Opacité:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:36 +msgid "Rotation:" +msgstr "Rotation:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:38 +msgid "Forward" +msgstr "Direction marche" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:39 +msgid "West" +msgstr "Ouest" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:40 +msgid "South" +msgstr "Sud" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:41 +msgid "East" +msgstr "Est" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:42 +msgid "North" +msgstr "Nord" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:46 +msgid "Scale:" +msgstr "Échelle:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:50 +msgid "Zoom mode:" +msgstr "Mode de Zoom:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:52 +msgid "Zoomed in" +msgstr "Zoomé" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:53 +msgid "Zoomed out" +msgstr "Dézoomé" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:54 +msgid "Always zoomed" +msgstr "Toujours Zoomé" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:55 +msgid "Never zoomed" +msgstr "Toujours Dézoomé" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:4 +msgid "Score Panel" +msgstr "Tableau des scores" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:22 +msgid "Score:" +msgstr "Score:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:25 +msgid "Rankings:" +msgstr "Rangs:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:26 +msgid "Off" +msgstr "Désactivé" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:27 +msgid "And me" +msgstr "Et moi" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:28 +msgid "Pure" +msgstr "Pure" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:4 +msgid "Timer Panel" +msgstr "Chronomètre" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:22 +msgid "Timer:" +msgstr "Chronomètre:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:25 +msgid "Show elapsed time" +msgstr "Montrer temps passé" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:4 +msgid "Vote Panel" +msgstr "Panneau de Vote" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:22 +msgid "Alpha after voting:" +msgstr "Opacité après vote:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:4 +msgid "Weapons Panel" +msgstr "Panneau d'armes" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:24 +msgid "Fade out after:" +msgstr "Effacer après:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:26 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:36 +msgid "Never" +msgstr "Jamais" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:28 +#, c-format +msgid "%ds" +msgstr "%dsec." + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:32 +msgid "Fade effect:" +msgstr "Effet d'effacement:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:35 +msgid "EF^None" +msgstr "Aucun" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:36 +msgid "Slide" +msgstr "Glisse" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:37 +msgid "Alpha" +msgstr "Opacité" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:38 +msgid "EF^Both" +msgstr "Les deux" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:42 +msgid "Weapon icons:" +msgstr "Icônes d'armes:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:45 +msgid "Show weapon ID as:" +msgstr "Montrer le numéro d'arme:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:46 +msgid "SHOWAS^None" +msgstr "Aucun" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:47 +msgid "Number" +msgstr "Numéro" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:48 +msgid "Bind" +msgstr "Touche" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:51 +msgid "Show Accuracy" +msgstr "Monter la précision" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:52 +msgid "Show Ammo" +msgstr "Montrer barre de munitions" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:55 +msgid "Ammo bar color:" +msgstr "Couleur barre de munitions:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:61 +msgid "Ammo bar alpha:" +msgstr "Opacité barre de munitions:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:4 +msgid "Panel HUD Setup" +msgstr "Configuration Interface" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:21 +msgid "Panel background defaults:" +msgstr "Fond du Panneau par défaut:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:23 qcsrc/menu/xonotic/util.qc:575 +msgid "Background:" +msgstr "Arrière-plan:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:25 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:37 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:52 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:91 qcsrc/menu/xonotic/util.qc:578 +#: qcsrc/menu/xonotic/util.qc:594 qcsrc/menu/xonotic/util.qc:611 +msgid "Disable" +msgstr "Désactiver" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:30 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:77 qcsrc/menu/xonotic/util.qc:583 +msgid "Color:" +msgstr "Couleur:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:35 qcsrc/menu/xonotic/util.qc:591 +msgid "Border size:" +msgstr "Taille des bords:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:50 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:89 +msgid "Team color:" +msgstr "Couleur d'équipe:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:58 qcsrc/menu/xonotic/util.qc:617 +msgid "Test team color in configure mode" +msgstr "Afficher la couleur d'équipe en mode configuration" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:61 qcsrc/menu/xonotic/util.qc:620 +msgid "Padding:" +msgstr "Ajustement:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:68 +msgid "HUD Dock:" +msgstr "Contour interface:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:70 +msgid "DOCK^Disabled" +msgstr "Désactivé" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:71 +msgid "DOCK^Small" +msgstr "Petit" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:72 +msgid "DOCK^Medium" +msgstr "Moyen" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:73 +msgid "DOCK^Large" +msgstr "Grand" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:96 +msgid "Grid settings:" +msgstr "Paramètres grille:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:99 +msgid "Snap panels to grid" +msgstr "Coller panneaux sur la grille" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:102 +msgid "Grid size:" +msgstr "Taille de grille:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:103 +msgid "X:" +msgstr "Hori.:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:109 +msgid "Y:" +msgstr "Vert.:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:117 +msgid "Exit setup" +msgstr "Sauvegarder et quitter" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:4 +msgid "Multiplayer" +msgstr "Multijoueur" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:18 +msgid "Servers" +msgstr "Serveurs" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:19 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:5 +msgid "Create" +msgstr "Créer" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:20 +msgid "Demos" +msgstr "Vidéos" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:5 +msgid "Player Setup" +msgstr "Paramètres Joueur" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:34 +msgid "Game type:" +msgstr "Mode de jeu:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:46 +msgid "Match settings:" +msgstr "Paramètres match:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:49 +msgid "Time limit:" +msgstr "Limite de temps:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:53 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:61 +msgid "Use map specified default" +msgstr "Utiliser le paramètre de carte" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:56 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:155 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:156 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:157 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:161 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:162 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:163 +msgid "Point limit:" +msgstr "Limite de points:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:64 +msgid "Player slots:" +msgstr "Nombre de joueurs max.:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:67 +msgid "Number of bots:" +msgstr "Nombre de robots:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:71 +msgid "Bot skill:" +msgstr "Difficulté robot:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:74 +msgid "Botlike" +msgstr "Nul" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:75 +msgid "Beginner" +msgstr "Jeu d'enfant" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:76 +msgid "You will win" +msgstr "Très Facile" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:77 +msgid "You can win" +msgstr "Facile" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:78 +msgid "You might win" +msgstr "Assez Facile" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:79 +msgid "Advanced" +msgstr "Avancé" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:80 +msgid "Expert" +msgstr "Expert" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:81 +msgid "Pro" +msgstr "Professionnel" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:82 +msgid "Assassin" +msgstr "Assassin" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:83 +msgid "Unhuman" +msgstr "Inhumain" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:84 +msgid "Godlike" +msgstr "Dieu" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:88 +msgid "Mutators..." +msgstr "Spéciales..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:97 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:57 +msgid "Advanced settings..." +msgstr "Paramètres avancés..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:104 +msgid "Map list:" +msgstr "Liste de cartes:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:110 +msgid "Select all" +msgstr "Tout sélectionner" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:113 +msgid "Select none" +msgstr "Ne rien sélectionner" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:119 +msgid "Start Multiplayer!" +msgstr "Démarrer!" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:154 +msgid "Capture limit:" +msgstr "Limite de captures:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:158 +msgid "Lives:" +msgstr "Vies:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:159 +msgid "Laps:" +msgstr "Tours:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:160 +msgid "Goals:" +msgstr "Buts:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:164 +msgid "Frag limit:" +msgstr "Limite de tués:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:6 +msgid "Advanced server settings" +msgstr "Paramètres serveur avancés" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:25 +msgid "Game settings:" +msgstr "Paramètres jeu" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:28 +msgid "Allow spectating" +msgstr "Autoriser les spectateurs" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:31 +msgid "Spawn shield:" +msgstr "Bouclier de départ:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:36 +msgid "Game speed:" +msgstr "Vitesse de jeu:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:40 +msgid "Teamplay settings:" +msgstr "Paramètres Jeu d'équipe:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:43 +msgid "Friendly fire scale:" +msgstr "Facteur Dégâts équipiers:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:47 +msgid "Virtual friendly fire (effect only)" +msgstr "Dégâts équipiers virtuels (seulement effets)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:50 +msgid "Friendly fire penalty:" +msgstr "Pénalité Dégâts équipiers:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:54 +msgid "Virtual penalty (effect only)" +msgstr "Pénalité Dégâts équipiers virtuelle (seulement effets)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:57 +msgid "Teams:" +msgstr "Équipes:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:66 +msgid "Map voting:" +msgstr "Vote carte suivante:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:68 +msgid "No voting" +msgstr "Pas de vote" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:69 +msgid "2 choices" +msgstr "2 choix" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:70 +msgid "3 choices" +msgstr "3 choix" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:71 +msgid "4 choices" +msgstr "4 choix" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:72 +msgid "5 choices" +msgstr "5 choix" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:73 +msgid "6 choices" +msgstr "6 choix" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:74 +msgid "7 choices" +msgstr "7 choix" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:75 +msgid "8 choices" +msgstr "8 choix" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:76 +msgid "9 choices" +msgstr "9 choix" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:79 +msgid "Simple majority wins vcall" +msgstr "Majorité 51% pour gagner le vote" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:5 +msgid "Map Information" +msgstr "Information carte:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "Full item placement" +msgstr "Objets présents" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "MinstaGib only" +msgstr "MinstaGib seulement" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:78 +msgid "Title:" +msgstr "Titre:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:84 +msgid "Author:" +msgstr "Auteur:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:90 +msgid "Features:" +msgstr "Fonctions:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:95 +msgid "Game types:" +msgstr "Modes de jeux:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:118 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:314 +msgid "Close" +msgstr "Fermer" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:121 +msgid "MAP^Play" +msgstr "Jouer" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:7 +msgid "Mutators" +msgstr "Spéciales" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:33 +msgid "All Weapons Arena" +msgstr "Toutes les armes" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:35 +msgid "Most Weapons Arena" +msgstr "Beaucoup d'armes" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:56 +#, c-format +msgid "%s Arena" +msgstr "Arène de %s" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:68 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:167 +msgid "Dodging" +msgstr "Esquives" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:70 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:250 +msgid "MinstaGib" +msgstr "MinstaGib" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:253 +msgid "NIX" +msgstr "NIX" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:74 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:205 +msgid "Rocket Flying" +msgstr "Roquettes volantes" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:78 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:264 +msgid "No start weapons" +msgstr "Pas d'armes au début" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:80 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:189 +msgid "Low gravity" +msgstr "Gravité basse" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:170 +msgid "Cloaked" +msgstr "Joueurs transparents" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:84 +msgid "Hook" +msgstr "Grappin" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:86 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:173 +msgid "Midair" +msgstr "Midair" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:88 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:176 +msgid "Vampire" +msgstr "Vampire" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:90 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:208 +msgid "Piñata" +msgstr "Piñata" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:92 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:211 +msgid "Weapons stay" +msgstr "Armes infinies" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:94 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:180 +msgid "Blood loss" +msgstr "Perte de sang" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:96 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:202 +msgid "Jet pack" +msgstr "Jet pack" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:98 +msgid "MUT^None" +msgstr "Aucun" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:164 +msgid "Gameplay mutators:" +msgstr "Spéciales Mode de jeu:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:196 +msgid "Weapon & item mutators:" +msgstr "Spéciales Armes et Objets:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:199 +msgid "Grappling hook" +msgstr "Grappin" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:215 +msgid "Weapon arenas:" +msgstr "Arènes d'armes:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:218 +msgid "Regular (no arena)" +msgstr "Régulier (pas d'Arène)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:239 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:256 +msgid "with laser" +msgstr "avec le laser" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:247 +msgid "Special arenas:" +msgstr "Arènes Spéciales:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:260 +msgid "Most weapons" +msgstr "Beaucoup d'armes" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:4 +msgid "Demo" +msgstr "Vidéo" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:28 +msgid "Record demos while playing" +msgstr "Auto-enregistrement des Vidéos" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:32 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:28 +msgid "Filter:" +msgstr "Recherche:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:29 +#: qcsrc/menu/xonotic/dialog_settings_input.c:41 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:24 +msgid "Clear" +msgstr "Effacer" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:43 +msgid "Timedemo" +msgstr "Test Performance" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:46 +msgid "DEMO^Play" +msgstr "Jouer" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:4 +msgid "Join" +msgstr "Joindre" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:36 +msgid "SRVS^Empty" +msgstr "Vide" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:40 +msgid "SRVS^Full" +msgstr "Tout" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:44 +msgid "Pause" +msgstr "Pause" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:56 +msgid "Address:" +msgstr "Adresse:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:67 +msgid "Info..." +msgstr "Info..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:317 +msgid "Join!" +msgstr "Joindre !" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:5 +msgid "Server Information" +msgstr "Information Serveur" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:115 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:116 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:183 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:189 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:199 +msgid "N/A" +msgstr "N/A" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:158 +#, c-format +msgid "%d/%d, %d free player slots" +msgstr "%d/%d, %d Emplacements libres" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +#, c-format +msgid "%d modified settings" +msgstr "paramètres modifiés: %d" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +msgid "Official settings" +msgstr "Paramètres Officiels" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:197 +msgid "N/A (can't connect)" +msgstr "N/A (ne peut pas se connecter)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:205 +msgid "not supported (can't connect)" +msgstr "non supporté (ne peut pas se connecter)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:207 +msgid "not supported (won't encrypt)" +msgstr "non supporté (pas de cryptage)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:211 +msgid "supported (will encrypt)" +msgstr "supporté (cryptage)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:213 +msgid "supported (won't encrypt)" +msgstr "supporté (pas de cryptage)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:217 +msgid "requested (will encrypt)" +msgstr "demandé (cryptage)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:219 +msgid "requested (won't encrypt)" +msgstr "demandé (pas de cryptage)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:223 +msgid "required (can't connect)" +msgstr "nécessaire (ne peut pas se connecter)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:225 +msgid "required (will encrypt)" +msgstr "nécessaire (cryptage)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:246 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:269 +msgid "Players:" +msgstr "Joueurs:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:254 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:38 +msgid "Type:" +msgstr "Type:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:259 +msgid "Map:" +msgstr "Carte:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:264 +msgid "Gameplay:" +msgstr "Mode:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:274 +msgid "Bots:" +msgstr "Robots:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:279 +msgid "Mod:" +msgstr "Modification:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:284 +msgid "Version:" +msgstr "Version:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:289 +msgid "Ping:" +msgstr "Latence:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:295 +msgid "CA:" +msgstr "CA:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:301 +msgid "Key:" +msgstr "Clé:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:307 +msgid "Encryption:" +msgstr "Cryptage:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:63 +msgid "Model:" +msgstr "Personnage:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:88 +msgid "Field of view:" +msgstr "Champ de vision:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:92 +msgid "View bobbing:" +msgstr "Caméra marche:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:96 +msgid "Zoom factor:" +msgstr "Facteur de Zoom:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:100 +msgid "Zoom speed:" +msgstr "Vitesse de Zoom:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:103 +msgid "Weapon settings..." +msgstr "Paramètres armes..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:110 +msgid "Crosshair:" +msgstr "Viseur:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:111 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:139 +msgid "Per weapon" +msgstr "Par arme" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:130 +msgid "Crosshair size:" +msgstr "Taille viseur:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:134 +msgid "Crosshair alpha:" +msgstr "Opacité viseur:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:138 +msgid "Crosshair color:" +msgstr "Couleur viseur:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:140 +msgid "By health" +msgstr "Par vie" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:143 +msgid "Custom" +msgstr "Personnalisé" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:148 +msgid "Enable center dot" +msgstr "Activer point central" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:151 +msgid "Size:" +msgstr "Taille:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:158 +msgid "Hit test:" +msgstr "Détection toucher:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:159 +msgid "HTST^None" +msgstr "Aucun" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:160 +msgid "TrueAim" +msgstr "TrueAim" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:161 +msgid "Enemies" +msgstr "Ennemis" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:164 +msgid "Waypoints setup..." +msgstr "Paramètres Waypoints..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:169 +msgid "Enter HUD editor" +msgstr "Éditer l'interface" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:174 +msgid "Force models:" +msgstr "Forcer personnages:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:175 +msgid "MDL^None" +msgstr "Aucun" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:176 +msgid "MDL^Custom" +msgstr "Personnalisé" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:177 +msgid "MDL^All" +msgstr "Tout" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:180 +msgid "Disable gore effects" +msgstr "Désactiver effets gore" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:182 +msgid "Gibs:" +msgstr "Gibs:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:184 +msgid "GIBS^None" +msgstr "Aucun" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:185 +msgid "GIBS^Few" +msgstr "Quelques" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:186 +msgid "GIBS^Many" +msgstr "Plusieurs" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:187 +msgid "GIBS^Lots" +msgstr "Beaucoup" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:191 +msgid "Damage splash:" +msgstr "Effet santé faible:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:195 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:173 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:194 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:30 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:41 +#: qcsrc/menu/xonotic/dialog_settings_video.c:109 +msgid "Apply immediately" +msgstr "Appliquer maintenant" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:5 +msgid "Waypoints" +msgstr "Waypoints" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:23 +msgid "Show base waypoints" +msgstr "Montrer les Waypoints de drapeau" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:25 +msgid "Waypoint scale:" +msgstr "Taille des Waypoints:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:29 +msgid "Waypoint alpha:" +msgstr "Opacité Waypoints:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:34 +msgid "Show names:" +msgstr "Montrer les noms:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:37 +msgid "Teammates" +msgstr "Équipiers" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:38 +msgid "All players" +msgstr "Tous les joueurs" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:6 +msgid "Weapon settings" +msgstr "Paramètres d'armes" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:29 +msgid "Weapon priority list:" +msgstr "Liste de priorité armes:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:34 +msgid "Up" +msgstr "Haut" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:37 +msgid "Down" +msgstr "Bas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:41 +msgid "Use priority list for weapon cycling" +msgstr "Utiliser la liste de priorité pour changer les armes" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:43 +msgid "Auto switch weapons on pickup" +msgstr "Changer d'arme en prenant une arme meilleure" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:45 +msgid "Draw 1st person weapon model" +msgstr "Afficher l'arme à la première personne" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:55 +msgid "Flip view horizontally" +msgstr "Vue Miroir" + +#: qcsrc/menu/xonotic/dialog_news.c:4 +msgid "News" +msgstr "News" + +#: qcsrc/menu/xonotic/dialog_news.c:18 +msgid "http://www.xonotic.org/team/blog/" +msgstr "http://www.xonotic.org/team/blog/" + +#: qcsrc/menu/xonotic/dialog_quit.c:4 +msgid "Quit" +msgstr "Quitter" + +#: qcsrc/menu/xonotic/dialog_quit.c:17 +msgid "Are you sure you want to quit?" +msgstr "Voulez-vous vraiment quitter ?" + +#: qcsrc/menu/xonotic/dialog_quit.c:20 +msgid "Yes" +msgstr "Oui" + +#: qcsrc/menu/xonotic/dialog_quit.c:21 +msgid "No" +msgstr "Non" + +#: qcsrc/menu/xonotic/dialog_settings.c:4 +msgid "Settings" +msgstr "Préférences" + +#: qcsrc/menu/xonotic/dialog_settings.c:18 +#: qcsrc/menu/xonotic/dialog_settings_input.c:4 +msgid "Input" +msgstr "Contrôles" + +#: qcsrc/menu/xonotic/dialog_settings.c:19 +#: qcsrc/menu/xonotic/dialog_settings_video.c:4 +msgid "Video" +msgstr "Vidéo" + +#: qcsrc/menu/xonotic/dialog_settings.c:20 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:4 +msgid "Effects" +msgstr "Graphiques" + +#: qcsrc/menu/xonotic/dialog_settings.c:21 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:4 +msgid "Audio" +msgstr "Audio" + +#: qcsrc/menu/xonotic/dialog_settings.c:22 +#: qcsrc/menu/xonotic/dialog_settings_network.c:4 +msgid "Network" +msgstr "Réseau" + +#: qcsrc/menu/xonotic/dialog_settings.c:23 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:4 +msgid "Misc" +msgstr "Autres" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:27 +msgid "Master:" +msgstr "Général:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:33 +msgid "Music:" +msgstr "Musique:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:41 +msgid "VOL^Ambient:" +msgstr "Ambiance:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:48 +msgid "Info:" +msgstr "Information:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:55 +msgid "Items:" +msgstr "Objets:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:62 +msgid "Pain:" +msgstr "Douleur:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:69 +msgid "Player:" +msgstr "Joueur:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:76 +msgid "Shots:" +msgstr "Tirs:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:83 +msgid "Voice:" +msgstr "Voix:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:91 +msgid "Weapons:" +msgstr "Armes:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:98 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:156 +msgid "Frequency:" +msgstr "Fréquence:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:100 +msgid "8 kHz" +msgstr "8 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:101 +msgid "11.025 kHz" +msgstr "11.025 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:102 +msgid "16 kHz" +msgstr "16 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:103 +msgid "22.05 kHz" +msgstr "22.05 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:104 +msgid "24 kHz" +msgstr "24 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:105 +msgid "32 kHz" +msgstr "32 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:106 +msgid "44.1 kHz" +msgstr "44.1 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:107 +msgid "48 kHz" +msgstr "48 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:110 +msgid "Channels:" +msgstr "Canaux:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:112 +msgid "Mono" +msgstr "Mono" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:113 +msgid "Stereo" +msgstr "Stéréo" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:114 +msgid "2.1" +msgstr "2.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:115 +msgid "4" +msgstr "4" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:116 +msgid "5" +msgstr "5" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:117 +msgid "5.1" +msgstr "5.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:118 +msgid "6.1" +msgstr "6.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:119 +msgid "7.1" +msgstr "7.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:123 +msgid "Swap Stereo" +msgstr "Échanger les canaux Stéréo" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:127 +msgid "Headphone friendly mode" +msgstr "Mode casque audio" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:131 +msgid "Spatial voices:" +msgstr "Voix personnages:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:132 +msgid "VOCS^None" +msgstr "Aucun" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:133 +msgid "VOCS^Taunts" +msgstr "Voix" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:134 +msgid "VOCS^All" +msgstr "Tout" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:137 +msgid "Taunt range:" +msgstr "Distance voix:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:140 +msgid "RNG^Very short" +msgstr "Très court" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:141 +msgid "RNG^Short" +msgstr "Court" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:142 +msgid "RNG^Normal" +msgstr "Normal" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:143 +msgid "RNG^Long" +msgstr "Long" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:144 +msgid "RNG^Full" +msgstr "Tout" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:151 +msgid "Automatic taunts" +msgstr "Voix automatiques" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:160 +msgid "Time warning:" +msgstr "Avertissement temps:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:162 +msgid "WRN^None" +msgstr "Aucun" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:163 +msgid "1 minute" +msgstr "1 minute" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:164 +msgid "5 minutes" +msgstr "5 minutes" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:165 +msgid "WRN^Both" +msgstr "Les deux" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:168 +msgid "Hit indicator" +msgstr "Son tir réussi" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:170 +msgid "Menu sounds" +msgstr "Sons du menu" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:38 +msgid "Quality preset:" +msgstr "Qualité effets:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:41 +msgid "PRE^OMG!" +msgstr "OMG!" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:42 +msgid "PRE^Low" +msgstr "Bas" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:43 +msgid "PRE^Medium" +msgstr "Moyen" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:44 +msgid "PRE^Normal" +msgstr "Normal" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:45 +msgid "PRE^High" +msgstr "Élevé" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:46 +msgid "PRE^Ultra" +msgstr "Très Élevé" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:48 +msgid "PRE^Ultimate" +msgstr "Ultime" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:52 +msgid "Geometry detail:" +msgstr "Détail géométrie:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:54 +msgid "DET^Lowest" +msgstr "Très Bas" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:55 +msgid "DET^Low" +msgstr "Bas" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:56 +msgid "DET^Normal" +msgstr "Normal" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:57 +msgid "DET^Good" +msgstr "Bon" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:58 +msgid "DET^Best" +msgstr "Élevé" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:59 +msgid "DET^Insane" +msgstr "Extrême" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:62 +msgid "Antialiasing:" +msgstr "Anticrénelage:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:64 +msgid "AA^Disabled" +msgstr "Désactivé" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:65 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:103 +msgid "2x" +msgstr "2x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:66 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:104 +msgid "4x" +msgstr "4x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:70 +msgid "Texture resolution:" +msgstr "Qualité textures:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:73 +msgid "RES^Leet" +msgstr "Leet" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:74 +msgid "RES^Lowest" +msgstr "Très Bas" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:75 +msgid "RES^Low" +msgstr "Bas" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:76 +msgid "RES^Normal" +msgstr "Normal" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:77 +msgid "RES^Good" +msgstr "Bon" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:78 +msgid "RES^Best" +msgstr "Élevé" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:91 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:94 +msgid "Avoid lossy texture compression" +msgstr "Éviter la compression rapide" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:100 +msgid "Anisotropy:" +msgstr "Filtrage Anisotrope:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:102 +msgid "ANISO^Disabled" +msgstr "Désactivé" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:105 +msgid "8x" +msgstr "8x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:106 +msgid "16x" +msgstr "16x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:110 +msgid "Particle quality:" +msgstr "Qualité particules:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:113 +msgid "Particle distance:" +msgstr "Distance max. particules:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:117 +msgid "Decals" +msgstr "Marques impacts" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:118 +msgid "Decals on models" +msgstr "Décalques sur les modèles" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:122 +msgid "Distance:" +msgstr "Distance max.:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:128 +msgid "Time:" +msgstr "Temps:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:134 +msgid "Use lightmaps" +msgstr "Utiliser les lightmaps" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:135 +msgid "Deluxe mapping" +msgstr "Textures Deluxe" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:137 +msgid "Gloss" +msgstr "Brillance textures" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:140 +msgid "Offset mapping" +msgstr "Textures relief" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:142 +msgid "Relief mapping" +msgstr "Textures relief avancé" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:145 +msgid "Reflections:" +msgstr "Réflexions:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:148 +msgid "Blurred" +msgstr "Flou" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:149 +msgid "REFL^Good" +msgstr "Bon" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:150 +msgid "Sharp" +msgstr "Net" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:155 +msgid "Show surfaces" +msgstr "Textures unies" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:157 +msgid "No dynamic lighting" +msgstr "Pas de lumières dynamiques" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:159 +msgid "Flash blend approximation" +msgstr "Lumières dynamiques rapides" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:161 +msgid "Realtime dynamic lighting" +msgstr "Lumières dynamiques en temps réel" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:162 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:166 +msgid "Shadows" +msgstr "Ombres" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:165 +msgid "Realtime world lighting" +msgstr "Lumières carte en temps réel" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:170 +msgid "Use normal maps" +msgstr "Lumières Deluxe" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:172 +msgid "Soft shadows" +msgstr "Ombres avancées" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:175 +msgid "Coronas" +msgstr "Brillance Lumière" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:176 +msgid "Use Occlusion Queries" +msgstr "Utiliser l'Occlusion du rendu" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:178 +msgid "Bloom" +msgstr "Effets d'éblouissement" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:180 +msgid "High Dynamic Range (HDR)" +msgstr "High Dynamic Range (HDR)" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:184 +msgid "Motion blur:" +msgstr "Flou de vitesse:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:189 +msgid "Blur and sharpen postprocessing" +msgstr "Flou et netteté post-processeur" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:26 +msgid "Key bindings:" +msgstr "Contrôles:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:31 +msgid "Change key..." +msgstr "Changer touche..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:35 +msgid "Edit..." +msgstr "Éditer..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:46 +msgid "Sensitivity:" +msgstr "Sensibilité:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:51 +msgid "UI mouse speed:" +msgstr "Vitesse souris menus:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:55 +msgid "Mouse filter" +msgstr "Filtre Souris" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:57 +msgid "Invert mouse" +msgstr "Inverser souris (axe Y)" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:60 +#: qcsrc/menu/xonotic/dialog_settings_input.c:62 +msgid "Use joystick input" +msgstr "Utiliser une manette" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:65 +#: qcsrc/menu/xonotic/dialog_settings_input.c:67 +msgid "Turn off OS mouse acceleration" +msgstr "Désactiver l'accélération souris de l'OS" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:69 +msgid "\"enter console\" also closes" +msgstr "\"ouvrir la console\" ferme aussi la console" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:5 +msgid "User defined key bind" +msgstr "Touche d'exécution:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:42 +msgid "Command when pressed:" +msgstr "Commande quand appuyée:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:45 +msgid "Command when released:" +msgstr "Commande quand relâchée:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:48 +msgid "Save" +msgstr "Sauvegarder" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:51 +msgid "Cancel" +msgstr "Annuler" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:26 +msgid "Menu skins:" +msgstr "Apparences menu:" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:47 +msgid "Show current time" +msgstr "Montrer l'heure" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:49 +msgid "Show current date" +msgstr "Montrer la date" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:51 +msgid "Show frames per second" +msgstr "Montrer les Images Par Seconde" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:53 +msgid "Minimize input latency" +msgstr "Minimiser la latence des contrôles" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:5 +msgid "Advanced settings" +msgstr "Paramètres avancés" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:23 +msgid "Cvar filter:" +msgstr "Recherche de commandes:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:34 +msgid "Setting:" +msgstr "Paramètre:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:42 +msgid "Value:" +msgstr "Valeur:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:56 +msgid "Description:" +msgstr "Description:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:26 +msgid "Client-side movement prediction" +msgstr "Prédiction des mouvements joueur" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:30 +msgid "Show netgraph" +msgstr "Montrer le netgraphe" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:33 +msgid "Network speed:" +msgstr "Vitesse réseau:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:35 +msgid "56k" +msgstr "56k" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:36 +msgid "ISDN" +msgstr "ISDN" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:37 +msgid "Slow ADSL" +msgstr "ADSL lent" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:38 +msgid "Fast ADSL" +msgstr "ADSL rapide" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:39 +msgid "Broadband" +msgstr "Câble/Fibre optique" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:42 +msgid "Input packets/s:" +msgstr "Paquets entrants/seconde:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:46 +msgid "HTTP downloads:" +msgstr "Téléchargements:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:49 +msgid "Downloads:" +msgstr "Téléchargements simultanés:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:53 +msgid "Speed (kB/s):" +msgstr "Vitesse (Ko/seconde):" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:57 +msgid "Client UDP port:" +msgstr "Port UDP client:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:26 +msgid "Resolution:" +msgstr "Résolution:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:29 +msgid "Font/UI size:" +msgstr "Taille typo:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:31 +msgid "SZ^Unreadable" +msgstr "Illisible" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:32 +msgid "SZ^Tiny" +msgstr "Minuscule" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:33 +msgid "SZ^Little" +msgstr "Très Petit" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:34 +msgid "SZ^Small" +msgstr "Petit" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:35 +msgid "SZ^Medium" +msgstr "Moyen" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:36 +msgid "SZ^Large" +msgstr "Grand" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:37 +msgid "SZ^Huge" +msgstr "Très Grand" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:38 +msgid "SZ^Gigantic" +msgstr "Géant" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:39 +msgid "SZ^Colossal" +msgstr "Gigantesque" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:42 +msgid "Color depth:" +msgstr "Profondeur de couleurs:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:45 +msgid "Full screen" +msgstr "Plein écran" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:46 +msgid "Vertical Synchronization" +msgstr "Synchronisation verticale" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:49 +msgid "Use OpenGL 2.0 shaders (GLSL)" +msgstr "Utiliser shader OpenGL 2.0 (GLSL)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:52 +msgid "Use GLSL to handle color control" +msgstr "Utiliser GLSL pour gérer les couleurs" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:56 +msgid "Vertex Buffer Objects (VBOs)" +msgstr "Objets en tampon mémoire (VBOs)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:59 +msgid "VBO^Off" +msgstr "Désactivé" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:60 +msgid "Vertices, some Tris (compatible)" +msgstr "Points, quelques Triangles (compatible)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:63 +msgid "Vertices" +msgstr "Points" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:64 +msgid "Vertices and Triangles" +msgstr "Points et Triangles" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:67 +msgid "Depth first:" +msgstr "Profondeur d'abord:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:69 +msgid "DF^Disabled" +msgstr "Désactivé" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:70 +msgid "DF^World" +msgstr "Monde" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:71 +msgid "DF^All" +msgstr "Tout" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:75 +msgid "Disable multithreaded OpenGL" +msgstr "Désactiver OpenGL multi-coeurs" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:77 +msgid "Wait for GPU to finish each frame" +msgstr "Attendre le GPU pour finir chaque trame" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:80 +msgid "Brightness:" +msgstr "Luminosité:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:83 +msgid "Contrast:" +msgstr "Contraste:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:86 +msgid "Gamma:" +msgstr "Gamma:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:91 +msgid "Contrast boost:" +msgstr "Amélioration contraste:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:96 +msgid "Saturation:" +msgstr "Saturation:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:102 +msgid "LIT^Ambient:" +msgstr "Ambiance:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:105 +msgid "Intensity:" +msgstr "Intensité:" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:4 +msgid "Singleplayer" +msgstr "Monojoueur" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:127 +msgid "Instant action! (random map with bots)" +msgstr "Instant action! (map aléatoire avec bots)" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:148 +msgid "Start Singleplayer!" +msgstr "Démarrer !" + +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:4 +msgid "Winner" +msgstr "Gagné" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:5 +msgid "Team Selection" +msgstr "Sélection d'équipe" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:41 +msgid "join 'best' team (auto-select)" +msgstr "auto-sélection équipe (recommandé)" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:45 +msgid "red" +msgstr "rouge" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:46 +msgid "blue" +msgstr "bleu" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:47 +msgid "yellow" +msgstr "jaune" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:48 +msgid "pink" +msgstr "rose" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:51 +msgid "spectate" +msgstr "mode spectateur" + +#: qcsrc/menu/xonotic/mainwindow.c:35 qcsrc/menu/xonotic/mainwindow.c:38 +msgid "Do not press this button again!" +msgstr "N'appuyez plus sur ce bouton !" + +#: qcsrc/menu/xonotic/maplist.c:278 +msgid "" +"Huh? Can't play this (m is NULL). Refiltering so this won't happen again.\n" +msgstr "" +"Euh? Ne peut pas être joué. Re-filtrage pour éviter des nouveaux problèmes.\n" + +#: qcsrc/menu/xonotic/maplist.c:286 +#, c-format +msgid "%s's Xonotic Server" +msgstr "%s's Xonotic Server" + +#: qcsrc/menu/xonotic/maplist.c:291 +msgid "" +"Huh? Can't play this (invalid game type). Refiltering so this won't happen " +"again.\n" +msgstr "" +"Euh? Ne peut pas être joué. Mode de jeu invalide. Re-filtrage pour éviter " +"des nouveaux problèmes.\n" + +#: qcsrc/menu/xonotic/playermodel.c:174 +msgid "<no model found>" +msgstr "<modèle non trouvé>" + +#: qcsrc/menu/xonotic/serverlist.c:185 +msgid "Remove" +msgstr "Supprimer" + +#: qcsrc/menu/xonotic/serverlist.c:187 +msgid "Bookmark" +msgstr "Marque-page" + +#: qcsrc/menu/xonotic/serverlist.c:527 +msgid "Ping" +msgstr "Latence" + +#: qcsrc/menu/xonotic/serverlist.c:528 +msgid "Host name" +msgstr "Nom d'Hôte" + +#: qcsrc/menu/xonotic/serverlist.c:529 +msgid "Map" +msgstr "Carte" + +#: qcsrc/menu/xonotic/serverlist.c:530 +msgid "Type" +msgstr "Mode" + +#: qcsrc/menu/xonotic/serverlist.c:531 +msgid "Players" +msgstr "Joueurs" + +#: qcsrc/menu/xonotic/skinlist.c:105 +msgid "<TITLE>" +msgstr "<TITRE>" + +#: qcsrc/menu/xonotic/skinlist.c:106 +msgid "<AUTHOR>" +msgstr "<AUTEUR>" + +#: qcsrc/menu/xonotic/slider_decibels.c:50 +msgid "VOL^OFF" +msgstr "OFF" + +#: qcsrc/menu/xonotic/slider_decibels.c:52 +msgid "VOL^MAX" +msgstr "MAX" + +#: qcsrc/menu/xonotic/slider_decibels.c:53 +#, c-format +msgid "%s dB" +msgstr "%s dB" + +#: qcsrc/menu/xonotic/slider_resolution.c:65 +#, c-format +msgid "%dx%d" +msgstr "%dx%d" + +#: qcsrc/menu/xonotic/util.qc:270 +#, c-format +msgid "Received HTTP request data for an invalid id %d.\n" +msgstr "A reçu la demande HTTP d'ID invalide %d.\n" + +#: qcsrc/menu/xonotic/util.qc:285 +#, c-format +msgid "error receiving update notification: status is %d\n" +msgstr "" +"erreur pour recevoir la notification de mise à jour: le statut est %d\n" + +#: qcsrc/menu/xonotic/util.qc:290 +msgid "error: received HTML instead of an update notification\n" +msgstr "" +"erreur: a reçu un fichier HTML et non une notification de mise à jour\n" + +#: qcsrc/menu/xonotic/util.qc:295 +msgid "error: received carriage returns from update notification server\n" +msgstr "" +"erreur: a reçu un message erroné depuis le serveur de notifications de M.A." +"J.\n" + +#: qcsrc/menu/xonotic/util.qc:316 +#, c-format +msgid "" +"Update can be downloaded at:\n" +"%s\n" +msgstr "" +"La mise à jour peut être téléchargée ici:\n" +"%s\n" + +#: qcsrc/menu/xonotic/util.qc:337 +msgid "Autogenerating mapinfo for newly added maps..." +msgstr "Génération des mapinfo pour les nouvelles cartes ajoutées..." + +#: qcsrc/menu/xonotic/util.qc:367 +#, c-format +msgid "^1%s TEST BUILD" +msgstr "VERSION DE TEST ^1%s" + +#: qcsrc/menu/xonotic/util.qc:432 +#, c-format +msgid "Update to %s now!" +msgstr "Mettez à jour vers %s maintenant !" + +#: qcsrc/menu/xonotic/util.qc:501 +msgid "" +"^1ERROR: Texture compression is required but not supported.\n" +"^1Expect visual problems.\n" +msgstr "" +"^1ERROR: La texture de compression est nécessaire mais non supportée.\n" +"^1Attendez vous à voir des problèmes de rendu.\n" + +#: qcsrc/menu/xonotic/util.qc:523 +msgid "Arena" +msgstr "Arène Duel" + +#: qcsrc/menu/xonotic/util.qc:524 +msgid "Assault" +msgstr "Assaut" + +#: qcsrc/menu/xonotic/util.qc:525 +msgid "Capture The Flag" +msgstr "Capture Du Drapeau" + +#: qcsrc/menu/xonotic/util.qc:526 +msgid "Clan Arena" +msgstr "Arène Équipes" + +#: qcsrc/menu/xonotic/util.qc:527 +msgid "Deathmatch" +msgstr "Match à Mort" + +#: qcsrc/menu/xonotic/util.qc:528 +msgid "Domination" +msgstr "Domination" + +#: qcsrc/menu/xonotic/util.qc:529 +msgid "Freeze Tag" +msgstr "Freeze Tag" + +#: qcsrc/menu/xonotic/util.qc:530 +msgid "Keepaway" +msgstr "Cache-Cache Du Drapeau" + +#: qcsrc/menu/xonotic/util.qc:531 +msgid "Key Hunt" +msgstr "Chasse aux Clés" + +#: qcsrc/menu/xonotic/util.qc:532 +msgid "Last Man Standing" +msgstr "Dernier Survivant" + +#: qcsrc/menu/xonotic/util.qc:533 +msgid "Nexball" +msgstr "Nexball" + +#: qcsrc/menu/xonotic/util.qc:534 +msgid "Onslaught" +msgstr "Onslaught" + +#: qcsrc/menu/xonotic/util.qc:535 +msgid "Race" +msgstr "Course" + +#: qcsrc/menu/xonotic/util.qc:536 +msgid "Race CTS" +msgstr "Course CTS" + +#: qcsrc/menu/xonotic/util.qc:537 +msgid "Runematch" +msgstr "Runematch" + +#: qcsrc/menu/xonotic/util.qc:538 +msgid "Team Deathmatch" +msgstr "Match à Mort Équipe" + +#: qcsrc/menu/xonotic/util.qc:557 +#, c-format +msgid "@!#%'n Tuba Throwing" +msgstr "Lancer de @!#%'n Tuba" + +#: qcsrc/menu/xonotic/util.qc:577 qcsrc/menu/xonotic/util.qc:593 +#: qcsrc/menu/xonotic/util.qc:602 qcsrc/menu/xonotic/util.qc:610 +#: qcsrc/menu/xonotic/util.qc:622 +msgid "Default" +msgstr "Par défaut" + +#: qcsrc/menu/xonotic/util.qc:588 +msgid "Use default" +msgstr "Par défaut" + +#: qcsrc/menu/xonotic/util.qc:608 +msgid "Team Color:" +msgstr "Couleur d'équipe:" + +#: qcsrc/menu/xonotic/util.qh:47 +msgid "Enable panel" +msgstr "Activer ce panneau" + +#: qcsrc/server/w_crylink.qc:2 +msgid "Crylink" +msgstr "Crylink" + +#: qcsrc/server/w_crylink.qc:666 +#, c-format +msgid "%s succeeded at self-destructing themself with the Crylink" +msgstr "%s a réussi à se suicider avec le Crylink" + +#: qcsrc/server/w_crylink.qc:671 +#, c-format +msgid "%s could not hide from %s's Crylink" +msgstr "%s n'a pas pu se cacher du Crylink de %s" + +#: qcsrc/server/w_crylink.qc:673 +#, c-format +msgid "%s was too close to %s's Crylink" +msgstr "%s a été trop près du Crylink de %s" + +#: qcsrc/server/w_crylink.qc:675 +#, c-format +msgid "%s took a close look at %s's Crylink" +msgstr "%s a voulu voir se qui se trouvait dans le Crylink de %s" + +#: qcsrc/server/w_electro.qc:2 +msgid "Electro" +msgstr "Electro" + +#: qcsrc/server/w_electro.qc:574 +#, c-format +msgid "%s could not remember where they put plasma" +msgstr "%s ne se souvenait pas où il a tiré du plasma" + +#: qcsrc/server/w_electro.qc:576 +#, c-format +msgid "%s played with plasma" +msgstr "%s a joué avec du plasma" + +#: qcsrc/server/w_electro.qc:583 +#, c-format +msgid "%s just noticed %s's blue ball" +msgstr "%s vient de remarquer la boule plasma de %s" + +#: qcsrc/server/w_electro.qc:585 +#, c-format +msgid "%s got in touch with %s's blue ball" +msgstr "%s s'est fait toucher par la boule plasma de %s" + +#: qcsrc/server/w_electro.qc:590 +#, c-format +msgid "%s felt the electrifying air of %s's combo" +msgstr "%s se sent électrisé par le combo de %s" + +#: qcsrc/server/w_electro.qc:592 +#, c-format +msgid "%s got too close to %s's blue beam" +msgstr "%s a été trop près du rayon plasma de %s" + +#: qcsrc/server/w_electro.qc:594 +#, c-format +msgid "%s was blasted by %s's blue beam" +msgstr "%s a été désintégré à cause du rayon plasma de %s" + +#: qcsrc/server/w_fireball.qc:2 +msgid "Fireball" +msgstr "Boule de Feu" + +#: qcsrc/server/w_fireball.qc:417 +#, c-format +msgid "%s forgot about some firemine" +msgstr "%s n'a pas étudié la combustion des boules de feu" + +#: qcsrc/server/w_fireball.qc:419 qcsrc/server/w_hlac.qc:240 +#, c-format +msgid "%s should have used a smaller gun" +msgstr "%s aurait dû utiliser une arme plus petite" + +#: qcsrc/server/w_fireball.qc:426 +#, c-format +msgid "%s tried to catch %s's firemine" +msgstr "%s a pensé que la boule de feu de %s était un ballon de football" + +#: qcsrc/server/w_fireball.qc:428 +#, c-format +msgid "%s fatefully ignored %s's firemine" +msgstr "%s a ignoré la boule de feu de %s" + +#: qcsrc/server/w_fireball.qc:435 +#, c-format +msgid "%s could not hide from %s's fireball" +msgstr "%s n'a pas réussi à se cacher de la boule de feu de %s" + +#: qcsrc/server/w_fireball.qc:437 +#, c-format +msgid "%s saw the pretty lights of %s's fireball" +msgstr "%s a vu les belles lumières de la boule de feu de %s" + +#: qcsrc/server/w_fireball.qc:440 +#, c-format +msgid "%s got too close to %s's fireball" +msgstr "%s s'est trop approché de la boule de feu de %s" + +#: qcsrc/server/w_fireball.qc:442 +#, c-format +msgid "%s tasted %s's fireball" +msgstr "%s a goûté la boule de feu de %s" + +#: qcsrc/server/w_grenadelauncher.qc:2 +msgid "Mortar" +msgstr "Mortier" + +#: qcsrc/server/w_grenadelauncher.qc:383 +#, c-format +msgid "%s tried out his own grenade" +msgstr "%s a mangé sa propre grenade" + +#: qcsrc/server/w_grenadelauncher.qc:385 +#, c-format +msgid "%s detonated" +msgstr "%s a fait boum" + +#: qcsrc/server/w_grenadelauncher.qc:391 +#, c-format +msgid "%s didn't see %s's grenade" +msgstr "%s n'a pas vu la grenade de %s" + +#: qcsrc/server/w_grenadelauncher.qc:393 +#, c-format +msgid "%s almost dodged %s's grenade" +msgstr "%s a presque réussi à esquiver la grenade de %s" + +#: qcsrc/server/w_grenadelauncher.qc:395 +#, c-format +msgid "%s ate %s's grenade" +msgstr "%s a mangé la grenade de %s" + +#: qcsrc/server/w_hagar.qc:2 +msgid "Hagar" +msgstr "Hagar" + +#: qcsrc/server/w_hagar.qc:395 qcsrc/server/w_seeker.qc:655 +#, c-format +msgid "%s played with tiny rockets" +msgstr "%s a joué avec des petits missiles" + +#: qcsrc/server/w_hagar.qc:399 +#, c-format +msgid "%s hoped %s's missiles wouldn't bounce" +msgstr "%s a pensé que les petits missiles de %s ne rebondissaient pas" + +#: qcsrc/server/w_hagar.qc:401 qcsrc/server/w_seeker.qc:661 +#, c-format +msgid "%s was pummeled by %s" +msgstr "%s a trop mangé de mini-missiles de la part de %s" + +#: qcsrc/server/w_hlac.qc:2 +msgid "Heavy Laser Assault Cannon" +msgstr "Canon Laser Lourd d'Assaut " + +#: qcsrc/server/w_hlac.qc:242 +#, c-format +msgid "%s was cut down by %s" +msgstr "%s s'est fait couper par %s" + +#: qcsrc/server/w_hook.qc:2 +msgid "Grappling Hook" +msgstr "Grappin" + +#: qcsrc/server/w_hook.qc:266 qcsrc/server/w_porto.qc:296 +#, c-format +msgid "%s did the impossible" +msgstr "%s a fait l'impossible" + +#: qcsrc/server/w_hook.qc:268 +#, c-format +msgid "%s has run into %s's gravity bomb" +msgstr "%s a été emprisonné par la bombe à gravité de %s" + +#: qcsrc/server/w_laser.qc:2 +msgid "Laser" +msgstr "Laser" + +#: qcsrc/server/w_laser.qc:311 +#, c-format +msgid "%s lasered themself to hell" +msgstr "%s s'est suicidé au laser" + +#: qcsrc/server/w_laser.qc:315 +#, c-format +msgid "%s was cut in half by %s's gauntlet" +msgstr "%s s'est fait couper en deux par le laser de %s" + +#: qcsrc/server/w_laser.qc:317 +#, c-format +msgid "%s was lasered to death by %s" +msgstr "%s a été désintégré par le laser de %s" + +#: qcsrc/server/w_minelayer.qc:2 +msgid "Mine Layer" +msgstr "Lance-Mines" + +#: qcsrc/server/w_minelayer.qc:523 qcsrc/server/w_rocketlauncher.qc:501 +#, c-format +msgid "%s exploded" +msgstr "%s a explosé" + +#: qcsrc/server/w_minelayer.qc:527 +#, c-format +msgid "%s got too close to %s's mine" +msgstr "%s s'est trop approché de la mine de %s" + +#: qcsrc/server/w_minelayer.qc:529 +#, c-format +msgid "%s almost dodged %s's mine" +msgstr "%s a presque esquivé la mine de %s" + +#: qcsrc/server/w_minelayer.qc:531 +#, c-format +msgid "%s stepped on %s's mine" +msgstr "%s a marché sur la mine de %s" + +#: qcsrc/server/w_minstanex.qc:2 +msgid "MinstaNex" +msgstr "MinstaNex" + +#: qcsrc/server/w_minstanex.qc:293 qcsrc/server/w_nex.qc:253 +#: qcsrc/server/w_shotgun.qc:215 qcsrc/server/w_uzi.qc:317 +#, c-format +msgid "%s is now thinking with portals" +msgstr "%s pense maintenant avec les portails" + +#: qcsrc/server/w_minstanex.qc:295 qcsrc/server/w_nex.qc:255 +#, c-format +msgid "%s has been vaporized by %s" +msgstr "%s s'est fait vaporiser par %s" + +#: qcsrc/server/w_nex.qc:2 +msgid "Nex" +msgstr "Nex" + +#: qcsrc/server/w_porto.qc:2 +msgid "Port-O-Launch" +msgstr "Lance-O-Port" + +#: qcsrc/server/w_porto.qc:298 +#, c-format +msgid "%s felt %s doing the impossible to him" +msgstr "%s a eu tort de prendre le portail de %s" + +#: qcsrc/server/w_rifle.qc:2 +msgid "Rifle" +msgstr "Fusil" + +#: qcsrc/server/w_rifle.qc:233 +#, c-format +msgid "%s shot themself automatically" +msgstr "%s s'est suicidé au sniper" + +#: qcsrc/server/w_rifle.qc:235 +#, c-format +msgid "%s sniped themself somehow" +msgstr "%s a oublié le cran de sûreté en chargeant" + +#: qcsrc/server/w_rifle.qc:242 +#, c-format +msgid "%s failed to hide from %s's bullet hail" +msgstr "%s n'a pas pu se cacher de la nuée de balles de %s" + +#: qcsrc/server/w_rifle.qc:244 +#, c-format +msgid "%s died in %s's bullet hail" +msgstr "%s est mort de la nuée de balles de %s" + +#: qcsrc/server/w_rifle.qc:251 +#, c-format +msgid "%s failed to hide from %s's rifle" +msgstr "%s n'a pas réussi à se cacher du sniper de %s" + +#: qcsrc/server/w_rifle.qc:256 +#, c-format +msgid "%s got hit in the head by %s" +msgstr "%s s'est fait décapiter au sniper par %s" + +#: qcsrc/server/w_rifle.qc:258 qcsrc/server/w_uzi.qc:321 +#, c-format +msgid "%s was sniped by %s" +msgstr "%s s'est fait descendre au sniper par %s" + +#: qcsrc/server/w_rocketlauncher.qc:2 +msgid "Rocket Launcher" +msgstr "Lance-Roquettes" + +#: qcsrc/server/w_rocketlauncher.qc:505 +#, c-format +msgid "%s got too close to %s's rocket" +msgstr "%s s'est trop approché de la roquette de %s" + +#: qcsrc/server/w_rocketlauncher.qc:507 +#, c-format +msgid "%s almost dodged %s's rocket" +msgstr "%s a presque esquivé la roquette de %s" + +#: qcsrc/server/w_rocketlauncher.qc:509 +#, c-format +msgid "%s ate %s's rocket" +msgstr "%s a mangé la roquette de %s" + +#: qcsrc/server/w_seeker.qc:2 +msgid "T.A.G. Seeker" +msgstr "T.A.G. Chercheur" + +#: qcsrc/server/w_seeker.qc:659 +#, c-format +msgid "%s was tagged by %s" +msgstr "%s s'est fait tagguer par %s" + +#: qcsrc/server/w_shotgun.qc:2 +msgid "Shotgun" +msgstr "Fusil" + +#: qcsrc/server/w_shotgun.qc:219 +#, c-format +msgid "%2$s ^7slapped %1$s ^7around a bit with a large ^2shotgun" +msgstr "%2$s ^7a baffé %1$s ^7avec un ^2fusil" + +#: qcsrc/server/w_shotgun.qc:221 +#, c-format +msgid "%s was gunned by %s" +msgstr "%s s'est fait fusiller par %s" + +#: qcsrc/server/w_tuba.qc:2 +#, c-format +msgid "@!#%'n Tuba" +msgstr "@!#% Tuba" + +#: qcsrc/server/w_tuba.qc:252 +#, c-format +msgid "%s hurt his own ears with the @!#%%'n Tuba" +msgstr "%s s'est fait casser les tympans par son propre tuba" + +#: qcsrc/server/w_tuba.qc:256 +#, c-format +msgid "%s died of %s's great playing on the @!#%%'n Tuba" +msgstr "%s n'a pas aimé la musique de %s et en est mort" + +#: qcsrc/server/w_uzi.qc:2 +msgid "Machine Gun" +msgstr "Mitraillette" + +#: qcsrc/server/w_uzi.qc:323 +#, c-format +msgid "%s was riddled full of holes by %s" +msgstr "%s s'est fait trouer par %s" + +#~ msgid "Damage & water blur" +#~ msgstr "Flou de d�g�ts:" + +#~ msgid "Powerup sharpen" +#~ msgstr "Panneau des Pouvoirs" diff --git a/menu.dat.hu.po b/menu.dat.hu.po new file mode 100644 index 0000000000..7d04e238af --- /dev/null +++ b/menu.dat.hu.po @@ -0,0 +1,2951 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR: xaN1C4n3 <robalm@freemail.hu>, 2011.01.19 +# corrected by xaN1C4n3, 2011.12.20. +# further corrected by C.Brutail, 2011.12.28. +# version 2.1 +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-09-02 07:51+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language:\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: qcsrc/common/mapinfo.qc:1092 qcsrc/menu/xonotic/skinlist.c:163 +#, c-format +msgid "%s: %s" +msgstr "%s: %s" + +#: qcsrc/menu/gamecommand.qc:47 +#, c-format +msgid "error: status is %d\n" +msgstr "Hiba: állapot %d\n" + +#: qcsrc/menu/gamecommand.qc:65 +msgid "Usage: menu_cmd command..., where possible commands are:\n" +msgstr "Használat: menu_cmd parancs..., ahol a lehetséges parancs:\n" + +#: qcsrc/menu/gamecommand.qc:66 +msgid " sync - reloads all cvars on the current menu page\n" +msgstr "sync - újratölti az összes cvar-t az aktuális menü oldalon\n" + +#: qcsrc/menu/gamecommand.qc:67 +msgid " directmenu ITEM - select a menu item as main item\n" +msgstr " directmenu TÁRGY - kiválaszt egy menü pontot, fő tárgynak\n" + +#: qcsrc/menu/gamecommand.qc:193 +msgid "error creating curl handle\n" +msgstr "Curl kezelő hibát okozott\n" + +#: qcsrc/menu/gamecommand.qc:239 +msgid "Invalid command. For a list of supported commands, try menu_cmd help.\n" +msgstr "" +" Érvénytelen parancs. A támogatott parancsok listájáért, próbáld a menu_cmd " +"segitséget.\n" + +#: qcsrc/menu/item/gecko.c:49 +msgid "Browser not initialized!" +msgstr "A böngésző nem indult el!" + +#: qcsrc/menu/item/label.c:63 +#, c-format +msgid "NOTE: label text %s too wide for label, condensed by factor %f\n" +msgstr "MEGJEGYZÉS: a(z) %s szöveg túl széles címkének, csökkentsd %f-el\n" + +#: qcsrc/menu/item/listbox.c:300 +#, c-format +msgid "Item %d" +msgstr "Tárgy %d" + +#: qcsrc/menu/item/slider.c:64 +#, c-format +msgid "%d (%s)" +msgstr "%d (%s)" + +#: qcsrc/menu/item/textslider.c:29 qcsrc/menu/item/textslider.c:31 +msgid "custom" +msgstr "egyéni" + +#: qcsrc/menu/menu.qc:29 +#, fuzzy, c-format +msgid "^4MQC Build information: ^1%s\n" +msgstr "^4MQC Build információ: %s\n" + +#: qcsrc/menu/xonotic/campaign.c:284 +#: qcsrc/menu/xonotic/dialog_singleplayer.c:134 +msgid "???" +msgstr "???" + +#: qcsrc/menu/xonotic/campaign.c:285 +#, c-format +msgid "Level %d: %s" +msgstr "Szint %d: %s" + +#: qcsrc/menu/xonotic/cvarlist.c:85 +msgid "will be saved to config.cfg" +msgstr "A config.cfg-be lesz mentve" + +#: qcsrc/menu/xonotic/cvarlist.c:87 +msgid "will not be saved" +msgstr "Nem lesz elmentve" + +#: qcsrc/menu/xonotic/cvarlist.c:89 +msgid "private" +msgstr "magán" + +#: qcsrc/menu/xonotic/cvarlist.c:91 +msgid "engine setting" +msgstr "grafikus motor beállítás" + +#: qcsrc/menu/xonotic/cvarlist.c:93 +msgid "read only" +msgstr "csak olvasható" + +#: qcsrc/menu/xonotic/dialog_credits.c:5 +msgid "Credits" +msgstr "Közreműködők" + +#: qcsrc/menu/xonotic/dialog_credits.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:269 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:41 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:57 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:61 +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:21 +msgid "OK" +msgstr "Rendben" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:4 +msgid "Welcome" +msgstr "Üdvözlet" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:33 +msgid "" +"Welcome to Xonotic, please select your language preference and enter your " +"player name to get started. You can change these options later through the " +"menu system." +msgstr "Üdvözlünk a Xonotic-ban! Kérjük, a kezdéshez válaszd ki a használni kívánt nyelvet " +"és írd be a játékos nevedet! Később ezeket meg is tudod változtatni " +"a menürendszerben." + +#: qcsrc/menu/xonotic/dialog_firstrun.c:38 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:35 +msgid "Text language:" +msgstr "Szöveg nyelv:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:47 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:40 +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:39 +msgid "Name:" +msgstr "Név:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:69 +msgid "Save settings" +msgstr "Beállítások mentése" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:4 +msgid "Ammo Panel" +msgstr "Lőszer Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:22 +msgid "Ammunition display:" +msgstr "Lőszer kijelző:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:25 +msgid "Show only current ammo type" +msgstr "Csak az aktuális lőszer típus megjelenítése" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:28 +msgid "Align icon:" +msgstr "Ikon sorrend:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:29 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:36 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:40 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:40 +msgid "Left" +msgstr "Bal" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:38 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:41 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:41 +msgid "Right" +msgstr "Jobb" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:4 +msgid "Centerprint" +msgstr "Közép" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:23 +#, fuzzy +msgid "Message duration:" +msgstr "Színtelítettség:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:27 +#, fuzzy +msgid "Fade time:" +msgstr "Bejegyzés elhalványulási ideje:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:31 +#, fuzzy +msgid "Flip messages order" +msgstr "Értesítési sorrend megfordítása" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:33 +#, fuzzy +msgid "Text alignment:" +msgstr "Szöveg igazítás:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:37 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:50 +msgid "Center" +msgstr "Közép" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:41 +#, fuzzy +msgid "Font scale:" +msgstr "Betűméret:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:4 +msgid "Chat Panel" +msgstr "Csevely Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:22 +msgid "Chat entries:" +msgstr "Csevely bejegyzések:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:25 +msgid "Chat size:" +msgstr "Csevely méret:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:29 +msgid "Chat lifetime:" +msgstr "Csevely élettartam:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:33 +msgid "Chat beep sound" +msgstr "Csevely sípszó" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:4 +msgid "Engine Info Panel" +msgstr "Grafikus motor információs panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:22 +msgid "Engine info:" +msgstr "Grafikus motor Információ:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:25 +msgid "Use an averaging algorithm for fps" +msgstr "Átlagoló algoritmus használata az fps-hez" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:4 +msgid "Health/Armor Panel" +msgstr "Életerő/Páncél Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:22 +msgid "Enable status bar" +msgstr "Állapotsor engedélyezése" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:24 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:24 +msgid "Status bar alignment:" +msgstr "Állapotsor igazítás:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:42 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:42 +msgid "Inward" +msgstr "Befelé" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:43 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:43 +msgid "Outward" +msgstr "Kifelé" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:37 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:37 +msgid "Icon alignment:" +msgstr "Ikon igazítás:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:45 +msgid "Flip health and armor positions" +msgstr "Életerő és páncél pozíciójának cseréje" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:4 +msgid "Info Messages Panel" +msgstr "Infó üzenetek panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:22 +msgid "Info messages:" +msgstr "Infó üzenetek:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:25 +msgid "Flip align" +msgstr "Fordított igazítás" + +#: qcsrc/menu/xonotic/dialog_hudpanel_modicons.c:4 +msgid "Mod Icons Panel" +msgstr "Mod ikonok panelje" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:4 +msgid "Notification Panel" +msgstr "Értesítő Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:22 +msgid "Notifications:" +msgstr "Értesítések:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:25 +msgid "Also print notifications to the console" +msgstr "Az értesítéseket a konzolra is kiírja" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:28 +msgid "Flip notify order" +msgstr "Értesítési sorrend megfordítása" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:31 +msgid "Entry lifetime:" +msgstr "Bejegyzés élettartama:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:35 +msgid "Entry fadetime:" +msgstr "Bejegyzés elhalványulási ideje:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:4 +#, fuzzy +msgid "Physics Panel" +msgstr "Fizika Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:21 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:21 +msgid "Panel disabled" +msgstr "Panel kikapcsolva" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:23 +#, fuzzy +msgid "Panel enabled" +msgstr "Panel engedélyezése" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:24 +#, fuzzy +msgid "Panel enabled even observing" +msgstr "Panel engedélyezett, még nézőként is" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:25 +#, fuzzy +msgid "Panel enabled only in Race/CTS" +msgstr "Panel csak Verseny/CTS-ben engedélyezett" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:31 +#, fuzzy +msgid "Status bar" +msgstr "Állapotsor" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:48 +msgid "Left align" +msgstr "Balra igazít" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:34 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:52 +msgid "Right align" +msgstr "Jobbra igazít" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:35 +#, fuzzy +msgid "Inward align" +msgstr "Befelé" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:36 +#, fuzzy +msgid "Outward align" +msgstr "Kifelé" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:40 +#, fuzzy +msgid "Flip speed/acceleration positions" +msgstr "Sebesség/gyorsulás poziciójának cseréje" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:44 +#, fuzzy +msgid "Speed:" +msgstr "Sebesség (kB/s):" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:45 +msgid "Include vertical speed" +msgstr "Függőleges sebességet is" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:56 +msgid "Speed unit:" +msgstr "Sebesség mértékegysége:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:58 +msgid "qu/s" +msgstr "qu/s" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:59 +msgid "m/s" +msgstr "m/s" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:60 +msgid "km/h" +msgstr "km/h" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:61 +msgid "mph" +msgstr "mph" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:62 +msgid "knots" +msgstr "csomó" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:64 +#, fuzzy +msgid "Show" +msgstr "Mutasd" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:67 +#, fuzzy +msgid "Top speed" +msgstr "Csúcssebesség" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:73 +#, fuzzy +msgid "Acceleration:" +msgstr "Gyorsulás:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:74 +msgid "Include vertical acceleration" +msgstr "Függőleges sebességet is" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:4 +msgid "Powerups Panel" +msgstr "Powerupok Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:45 +msgid "Flip strength and shield positions" +msgstr "Erő és pajzs pozíciók felcserélése" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:4 +msgid "Pressed Keys Panel" +msgstr "Lenyomott gombok lapja" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:22 +msgid "Panel enabled when spectating" +msgstr "Panel csak nézőként engedélyezett" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:23 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:23 +msgid "Panel always enabled" +msgstr "Panel mindig látható" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:30 +msgid "Forced aspect:" +msgstr "Kényszerített nézőpont:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_racetimer.c:4 +msgid "Race Timer Panel" +msgstr "Időmérő Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:4 +msgid "Radar Panel" +msgstr "Radar Panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:22 +msgid "Panel enabled in teamgames" +msgstr "Panel csapatjátékokban engedélyezve" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:29 +msgid "Radar:" +msgstr "Radar:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:32 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:43 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:154 +#: qcsrc/menu/xonotic/util.qc:600 +msgid "Alpha:" +msgstr "Átlátszóság:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:36 +msgid "Rotation:" +msgstr "Forgatás:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:38 +msgid "Forward" +msgstr "Előre" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:39 +msgid "West" +msgstr "Nyugat" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:40 +msgid "South" +msgstr "Dél" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:41 +msgid "East" +msgstr "Kelet" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:42 +msgid "North" +msgstr "Észak" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:46 +msgid "Scale:" +msgstr "Méret:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:50 +msgid "Zoom mode:" +msgstr "Nagyítási mód:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:52 +msgid "Zoomed in" +msgstr "Nagyítás" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:53 +msgid "Zoomed out" +msgstr "Kicsinyítés" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:54 +msgid "Always zoomed" +msgstr "Mindig nagyított" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:55 +msgid "Never zoomed" +msgstr "Sohasem nagyított" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:4 +msgid "Score Panel" +msgstr "Pontjelző panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:22 +msgid "Score:" +msgstr "Pont:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:25 +msgid "Rankings:" +msgstr "Helyezés:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:26 +#, fuzzy +msgid "Off" +msgstr "Kikapcsolva" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:27 +msgid "And me" +msgstr "És nekem" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:28 +msgid "Pure" +msgstr "Tiszta" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:4 +msgid "Timer Panel" +msgstr "Időmérő panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:22 +msgid "Timer:" +msgstr "Időzítő:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:25 +msgid "Show elapsed time" +msgstr "Eltelt idő mutatása" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:4 +msgid "Vote Panel" +msgstr "Szavazó panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:22 +msgid "Alpha after voting:" +msgstr "Átlátszóság szavazat után:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:4 +msgid "Weapons Panel" +msgstr "Fegyver panel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:24 +msgid "Fade out after:" +msgstr "Elhalványulás késleltetés:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:26 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:36 +msgid "Never" +msgstr "Soha" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:28 +#, c-format +msgid "%ds" +msgstr "%ds" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:32 +msgid "Fade effect:" +msgstr "Elhalványulás hatása:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:35 +msgid "EF^None" +msgstr "EF^Nincs" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:36 +msgid "Slide" +msgstr "Becsúszó" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:37 +msgid "Alpha" +msgstr "Halványuló" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:38 +#, fuzzy +msgid "EF^Both" +msgstr "Mindkettő" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:42 +msgid "Weapon icons:" +msgstr "Fegyver ikonok:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:45 +msgid "Show weapon ID as:" +msgstr "A Fegyver ID megjelenítése mint:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:46 +msgid "SHOWAS^None" +msgstr "Sehogy" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:47 +msgid "Number" +msgstr "Számmal" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:48 +msgid "Bind" +msgstr "Billentyű" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:51 +msgid "Show Accuracy" +msgstr "Pontosság mutatása" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:52 +msgid "Show Ammo" +msgstr "Lőszer mutatása" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:55 +msgid "Ammo bar color:" +msgstr "Lőszer jelző színe:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:61 +msgid "Ammo bar alpha:" +msgstr "Lőszer jelző átlátszósága:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:4 +msgid "Panel HUD Setup" +msgstr "HUD panel beállítása" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:21 +msgid "Panel background defaults:" +msgstr "Alapértelmezett panel háttér:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:23 qcsrc/menu/xonotic/util.qc:575 +msgid "Background:" +msgstr "Háttér:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:25 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:37 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:52 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:91 qcsrc/menu/xonotic/util.qc:578 +#: qcsrc/menu/xonotic/util.qc:594 qcsrc/menu/xonotic/util.qc:611 +msgid "Disable" +msgstr "Letiltás" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:30 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:77 qcsrc/menu/xonotic/util.qc:583 +msgid "Color:" +msgstr "Szín:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:35 qcsrc/menu/xonotic/util.qc:591 +msgid "Border size:" +msgstr "Keret méret:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:50 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:89 +msgid "Team color:" +msgstr "Csapat szín:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:58 qcsrc/menu/xonotic/util.qc:617 +msgid "Test team color in configure mode" +msgstr "Csapat szín tesztelés beállítás közben" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:61 qcsrc/menu/xonotic/util.qc:620 +msgid "Padding:" +msgstr "Kitöltés:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:68 +msgid "HUD Dock:" +msgstr "HUD rögzítők:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:70 +msgid "DOCK^Disabled" +msgstr "Letiltva" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:71 +msgid "DOCK^Small" +msgstr "Kicsi" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:72 +msgid "DOCK^Medium" +msgstr "Közepes" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:73 +msgid "DOCK^Large" +msgstr "Nagy" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:96 +msgid "Grid settings:" +msgstr "Rács beállítások:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:99 +msgid "Snap panels to grid" +msgstr "Panelek rácshoz igazítása" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:102 +msgid "Grid size:" +msgstr "Rács méret:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:103 +msgid "X:" +msgstr "X:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:109 +msgid "Y:" +msgstr "Y:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:117 +msgid "Exit setup" +msgstr "Kilépés a beállításokból" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:4 +msgid "Multiplayer" +msgstr "Többjátékos mód" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:18 +msgid "Servers" +msgstr "Szerverek" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:19 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:5 +msgid "Create" +msgstr "Létrehozás" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:20 +msgid "Demos" +msgstr "Demók" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:5 +msgid "Player Setup" +msgstr "Játékos beállítások" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:34 +msgid "Game type:" +msgstr "Játék típusa:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:46 +msgid "Match settings:" +msgstr "Meccs beállítások:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:49 +msgid "Time limit:" +msgstr "Időhatár:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:53 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:61 +msgid "Use map specified default" +msgstr "Pályához tartozó alapérték használata" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:56 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:155 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:156 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:157 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:161 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:162 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:163 +msgid "Point limit:" +msgstr "Ponthatár:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:64 +msgid "Player slots:" +msgstr "Maximális játékosszám" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:67 +msgid "Number of bots:" +msgstr "Botok száma:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:71 +msgid "Bot skill:" +msgstr "Botok szintje" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:74 +msgid "Botlike" +msgstr "Béna" + +# :))) +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:75 +msgid "Beginner" +msgstr "Kezdő" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:76 +msgid "You will win" +msgstr "Te fogsz nyerni" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:77 +msgid "You can win" +msgstr "Nyerhetsz" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:78 +msgid "You might win" +msgstr "Talán győzhetsz" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:79 +msgid "Advanced" +msgstr "Rutinos" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:80 +msgid "Expert" +msgstr "Tapasztalt" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:81 +msgid "Pro" +msgstr "Hivatásos" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:82 +msgid "Assassin" +msgstr "Gyilkológép" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:83 +msgid "Unhuman" +msgstr "Embertelen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:84 +msgid "Godlike" +msgstr "MAGA AZ ISTEN" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:88 +msgid "Mutators..." +msgstr "Módosítók..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:97 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:57 +msgid "Advanced settings..." +msgstr "Haladó beállítások..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:104 +msgid "Map list:" +msgstr "Pályalista:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:110 +msgid "Select all" +msgstr "Az összes" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:113 +msgid "Select none" +msgstr "Egyik sem" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:119 +msgid "Start Multiplayer!" +msgstr "Többjátékos indítása!" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:154 +msgid "Capture limit:" +msgstr "Zászlórablások száma:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:158 +msgid "Lives:" +msgstr "Életek:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:159 +msgid "Laps:" +msgstr "Körök:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:160 +msgid "Goals:" +msgstr "Célok:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:164 +msgid "Frag limit:" +msgstr "Gyilok határérték:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:6 +msgid "Advanced server settings" +msgstr "Haladó szerver beállítások" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:25 +msgid "Game settings:" +msgstr "Játék beállítások:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:28 +msgid "Allow spectating" +msgstr "Nézők engedélyezése" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:31 +msgid "Spawn shield:" +msgstr "Páncél megjelenés:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:36 +msgid "Game speed:" +msgstr "Játék sebessége:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:40 +msgid "Teamplay settings:" +msgstr "Csapatjáték beállítások:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:43 +msgid "Friendly fire scale:" +msgstr "Csapattárs sebzés mértéke:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:47 +msgid "Virtual friendly fire (effect only)" +msgstr "Látszólagos csapattárs sebzés (csak látvány)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:50 +msgid "Friendly fire penalty:" +msgstr "Csapattárs megsebzésének büntetése:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:54 +msgid "Virtual penalty (effect only)" +msgstr "Látszólagos büntetés (csak látvány)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:57 +msgid "Teams:" +msgstr "Csapatok:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:66 +msgid "Map voting:" +msgstr "Pálya szavazás:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:68 +msgid "No voting" +msgstr "Nincs szavazás" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:69 +msgid "2 choices" +msgstr "2 lehetőség" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:70 +msgid "3 choices" +msgstr "3 lehetőség" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:71 +msgid "4 choices" +msgstr "4 lehetőség" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:72 +msgid "5 choices" +msgstr "5 lehetőség" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:73 +msgid "6 choices" +msgstr "6 lehetőség" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:74 +msgid "7 choices" +msgstr "7 lehetőség" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:75 +msgid "8 choices" +msgstr "8 lehetőség" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:76 +msgid "9 choices" +msgstr "9 lehetőség" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:79 +msgid "Simple majority wins vcall" +msgstr "Egyszerű többség nyer" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:5 +msgid "Map Information" +msgstr "Pálya Információ" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "Full item placement" +msgstr "Minden tárgy elhelyezése" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "MinstaGib only" +msgstr "Csak MinstaGib" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:78 +msgid "Title:" +msgstr "Cím:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:84 +msgid "Author:" +msgstr "Szerző:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:90 +msgid "Features:" +msgstr "Jellemzők:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:95 +msgid "Game types:" +msgstr "Játék típusok:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:118 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:314 +msgid "Close" +msgstr "Bezár" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:121 +#, fuzzy +msgid "MAP^Play" +msgstr "Indítás" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:7 +msgid "Mutators" +msgstr "Módosítók" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:33 +msgid "All Weapons Arena" +msgstr "Minden Fegyver Aréna" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:35 +msgid "Most Weapons Arena" +msgstr "Legtöbb Fegyver Aréna" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:56 +#, c-format +msgid "%s Arena" +msgstr "%s Aréna" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:68 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:167 +msgid "Dodging" +msgstr "Félreugrás" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:70 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:250 +msgid "MinstaGib" +msgstr "MinstaGib" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:253 +msgid "NIX" +msgstr "NIX" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:74 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:205 +msgid "Rocket Flying" +msgstr "Rakéta repülés" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:78 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:264 +msgid "No start weapons" +msgstr "Nincs kezdő fegyver" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:80 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:189 +msgid "Low gravity" +msgstr "Alacsony gravitáció" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:170 +msgid "Cloaked" +msgstr "Álcázott" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:84 +msgid "Hook" +msgstr "Kampó" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:86 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:173 +msgid "Midair" +msgstr "Sebzés csak levegőben" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:88 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:176 +msgid "Vampire" +msgstr "Vámpír" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:90 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:208 +msgid "Piñata" +msgstr "Piñata" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:92 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:211 +msgid "Weapons stay" +msgstr "Fegyverek maradnak" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:94 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:180 +msgid "Blood loss" +msgstr "Vérveszteség" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:96 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:202 +msgid "Jet pack" +msgstr "Jet pack" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:98 +msgid "MUT^None" +msgstr "Nincs" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:164 +msgid "Gameplay mutators:" +msgstr "Játékmenet módosítók:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:196 +msgid "Weapon & item mutators:" +msgstr "Fegyver és tárgy módosítók:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:199 +msgid "Grappling hook" +msgstr "Vonóhorog" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:215 +msgid "Weapon arenas:" +msgstr "Fegyver Arénák:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:218 +msgid "Regular (no arena)" +msgstr "Hagyományos (nincs módosítás)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:239 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:256 +msgid "with laser" +msgstr "lézerrel" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:247 +msgid "Special arenas:" +msgstr "Különleges Arénák:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:260 +msgid "Most weapons" +msgstr "A legtöbb fegyver" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:4 +msgid "Demo" +msgstr "Demók" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:28 +msgid "Record demos while playing" +msgstr "Játék közben demók rögzítése" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:32 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:28 +msgid "Filter:" +msgstr "Szűrés:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:29 +#: qcsrc/menu/xonotic/dialog_settings_input.c:41 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:24 +msgid "Clear" +msgstr "Törlés" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:43 +msgid "Timedemo" +msgstr "Időmérés" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:46 +#, fuzzy +msgid "DEMO^Play" +msgstr "Lejátszás" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:4 +msgid "Join" +msgstr "Csatlakozás" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:36 +msgid "SRVS^Empty" +msgstr "SRVS^Üres" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:40 +msgid "SRVS^Full" +msgstr "SRVS^Teli" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:44 +msgid "Pause" +msgstr "Szünet" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:56 +msgid "Address:" +msgstr "Cím:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:67 +msgid "Info..." +msgstr "Infó..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:317 +msgid "Join!" +msgstr "Csatlakozok!" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:5 +msgid "Server Information" +msgstr "Szerver információ" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:115 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:116 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:183 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:189 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:199 +msgid "N/A" +msgstr "N/A" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:158 +#, c-format +msgid "%d/%d, %d free player slots" +msgstr "%d/%d, %d szabad férőhely" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +#, c-format +msgid "%d modified settings" +msgstr "%d módosított beállítások" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +msgid "Official settings" +msgstr "Hivatalos beállítások" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:197 +msgid "N/A (can't connect)" +msgstr "N/A (nem tudok csatlakozni)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:205 +msgid "not supported (can't connect)" +msgstr "nem támogatott (nem tudok csatlakozni)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:207 +msgid "not supported (won't encrypt)" +msgstr "nem támogatott (nem titkosított)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:211 +msgid "supported (will encrypt)" +msgstr "támogatott (titkosított)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:213 +msgid "supported (won't encrypt)" +msgstr "támogatott (nem titkosított)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:217 +msgid "requested (will encrypt)" +msgstr "kért (titkosított)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:219 +msgid "requested (won't encrypt)" +msgstr "kért (nem titkosított)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:223 +msgid "required (can't connect)" +msgstr "szükséges (nem tudok csatlakozni)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:225 +msgid "required (will encrypt)" +msgstr "szükséges (titkosított)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:246 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:269 +msgid "Players:" +msgstr "Játékosok:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:254 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:38 +msgid "Type:" +msgstr "Típus:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:259 +msgid "Map:" +msgstr "Pálya:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:264 +msgid "Gameplay:" +msgstr "Játékmenet:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:274 +msgid "Bots:" +msgstr "Botok:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:279 +msgid "Mod:" +msgstr "Mod:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:284 +msgid "Version:" +msgstr "Verzió:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:289 +msgid "Ping:" +msgstr "Ping:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:295 +msgid "CA:" +msgstr "CA:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:301 +msgid "Key:" +msgstr "Kulcs:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:307 +msgid "Encryption:" +msgstr "Titkosítás:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:63 +msgid "Model:" +msgstr "Modell:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:87 +msgid "Force player models to mine" +msgstr "Ellenség modelljeinek kényszerítése az enyémmel megegyezőre" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:88 +msgid "Field of view:" +msgstr "Látómező:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:92 +msgid "View bobbing:" +msgstr "Fej biccenés:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:96 +msgid "Zoom factor:" +msgstr "Nagyítási szorzó:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:100 +msgid "Zoom speed:" +msgstr "Nagyítás sebessége:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:103 +msgid "Weapon settings..." +msgstr "Fegyverzet beállítások..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:110 +msgid "Crosshair:" +msgstr "Célkereszt:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:111 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:139 +msgid "Per weapon" +msgstr "Fegyverenként" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:130 +msgid "Crosshair size:" +msgstr "Célkereszt mérete:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:134 +msgid "Crosshair alpha:" +msgstr "Célkereszt átlátszósága:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:138 +msgid "Crosshair color:" +msgstr "Célkereszt színe:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:140 +msgid "By health" +msgstr "Életerőtől függ" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:143 +#, fuzzy +msgid "Custom" +msgstr "Egyéni" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:148 +msgid "Enable center dot" +msgstr "Középső pont engedélyezése" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:151 +msgid "Size:" +msgstr "Méret:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:158 +msgid "Hit test:" +msgstr "Találat ellenőrzés:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:159 +msgid "HTST^None" +msgstr "HTST^Nincs" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:160 +msgid "TrueAim" +msgstr "Valós célzás" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:161 +msgid "Enemies" +msgstr "Ellenségek" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:164 +msgid "Waypoints setup..." +msgstr "Iránypontok beállítása..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:169 +msgid "Enter HUD editor" +msgstr "Belépés a HUD szerkesztőbe" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:174 +msgid "Force models:" +msgstr "Modellek kényszerítése:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:175 +msgid "MDL^None" +msgstr "MDL^Nincs" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:176 +msgid "MDL^Custom" +msgstr "MDL^Egyéni" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:177 +msgid "MDL^All" +msgstr "MDL^Mind" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:180 +msgid "Disable gore effects" +msgstr "Véres hatások letiltása" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:182 +msgid "Gibs:" +msgstr "Húscafatok:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:184 +msgid "GIBS^None" +msgstr "GIBS^Nincs" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:185 +msgid "GIBS^Few" +msgstr "GIBS^Kevés" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:186 +msgid "GIBS^Many" +msgstr "GIBS^Sok" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:187 +msgid "GIBS^Lots" +msgstr "GIBS^Rengeteg" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:191 +msgid "Damage splash:" +msgstr "Sérülési rázkódás:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:195 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:173 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:194 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:30 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:41 +#: qcsrc/menu/xonotic/dialog_settings_video.c:109 +msgid "Apply immediately" +msgstr "Azonnali alkalmazás" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:5 +msgid "Waypoints" +msgstr "Iránypontok" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:23 +msgid "Show base waypoints" +msgstr "Bázis-iránypontok mutatása" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:25 +msgid "Waypoint scale:" +msgstr "Iránypontok mérete:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:29 +msgid "Waypoint alpha:" +msgstr "Iránypontok átlátszósága:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:34 +msgid "Show names:" +msgstr "Nevek mutatása:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:37 +msgid "Teammates" +msgstr "Csapattársak" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:38 +msgid "All players" +msgstr "Minden játékos" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:6 +msgid "Weapon settings" +msgstr "Fegyver beállítások" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:29 +msgid "Weapon priority list:" +msgstr "Fegyver elsőbbségi lista:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:34 +msgid "Up" +msgstr "Fel" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:37 +msgid "Down" +msgstr "Le" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:41 +msgid "Use priority list for weapon cycling" +msgstr "Az elsőbbségi listát használom a fegyverváltáshoz" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:43 +msgid "Auto switch weapons on pickup" +msgstr "Automatikus váltás a felvett fegyverre" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:45 +msgid "Draw 1st person weapon model" +msgstr "Kézben tartott fegyver kirajzolása" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:55 +msgid "Flip view horizontally" +msgstr "A képernyő vízszintes tükrözése" + +#: qcsrc/menu/xonotic/dialog_news.c:4 +msgid "News" +msgstr "Hírek" + +#: qcsrc/menu/xonotic/dialog_news.c:18 +msgid "http://www.xonotic.org/team/blog/" +msgstr "http://www.xonotic.org/team/blog/" + +#: qcsrc/menu/xonotic/dialog_quit.c:4 +msgid "Quit" +msgstr "Kilépés" + +#: qcsrc/menu/xonotic/dialog_quit.c:17 +msgid "Are you sure you want to quit?" +msgstr "Biztos ki szeretnél lépni?" + +#: qcsrc/menu/xonotic/dialog_quit.c:20 +msgid "Yes" +msgstr "Igen" + +#: qcsrc/menu/xonotic/dialog_quit.c:21 +msgid "No" +msgstr "Nem" + +#: qcsrc/menu/xonotic/dialog_settings.c:4 +msgid "Settings" +msgstr "Beállítások" + +#: qcsrc/menu/xonotic/dialog_settings.c:18 +#: qcsrc/menu/xonotic/dialog_settings_input.c:4 +msgid "Input" +msgstr "Bemenet" + +#: qcsrc/menu/xonotic/dialog_settings.c:19 +#: qcsrc/menu/xonotic/dialog_settings_video.c:4 +msgid "Video" +msgstr "Videó" + +#: qcsrc/menu/xonotic/dialog_settings.c:20 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:4 +msgid "Effects" +msgstr "Hatások" + +#: qcsrc/menu/xonotic/dialog_settings.c:21 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:4 +msgid "Audio" +msgstr "Hang" + +#: qcsrc/menu/xonotic/dialog_settings.c:22 +#: qcsrc/menu/xonotic/dialog_settings_network.c:4 +msgid "Network" +msgstr "Hálózat" + +#: qcsrc/menu/xonotic/dialog_settings.c:23 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:4 +msgid "Misc" +msgstr "Egyéb" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:27 +msgid "Master:" +msgstr "Általános:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:33 +msgid "Music:" +msgstr "Zene:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:41 +msgid "VOL^Ambient:" +msgstr "VOL^Háttérzajok:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:48 +msgid "Info:" +msgstr "Információ:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:55 +msgid "Items:" +msgstr "Tárgyak:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:62 +msgid "Pain:" +msgstr "Fájdalom:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:69 +msgid "Player:" +msgstr "Játékosok:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:76 +msgid "Shots:" +msgstr "Lövések:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:83 +msgid "Voice:" +msgstr "Beszéd:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:91 +msgid "Weapons:" +msgstr "Fegyverek:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:98 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:156 +msgid "Frequency:" +msgstr "Frekvencia:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:100 +msgid "8 kHz" +msgstr "8 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:101 +msgid "11.025 kHz" +msgstr "11,025 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:102 +msgid "16 kHz" +msgstr "16 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:103 +msgid "22.05 kHz" +msgstr "22,05 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:104 +msgid "24 kHz" +msgstr "24 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:105 +msgid "32 kHz" +msgstr "32 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:106 +msgid "44.1 kHz" +msgstr "44,1 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:107 +msgid "48 kHz" +msgstr "48 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:110 +msgid "Channels:" +msgstr "Csatornák:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:112 +msgid "Mono" +msgstr "Monó" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:113 +msgid "Stereo" +msgstr "Sztereó" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:114 +msgid "2.1" +msgstr "2.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:115 +msgid "4" +msgstr "4" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:116 +msgid "5" +msgstr "5" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:117 +msgid "5.1" +msgstr "5.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:118 +msgid "6.1" +msgstr "6.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:119 +msgid "7.1" +msgstr "7.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:123 +msgid "Swap Stereo" +msgstr "Sztereó felcserélése" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:127 +msgid "Headphone friendly mode" +msgstr "Fejhallgató barát mód" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:131 +msgid "Spatial voices:" +msgstr "Utasítások:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:132 +msgid "VOCS^None" +msgstr "VOCS^Nincs" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:133 +msgid "VOCS^Taunts" +msgstr "VOCS^Gúnyolódás" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:134 +msgid "VOCS^All" +msgstr "VOCS^Minden" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:137 +msgid "Taunt range:" +msgstr "Gúnyolódások hallhatósága:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:140 +msgid "RNG^Very short" +msgstr "RNG^Közvetlen közelről" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:141 +msgid "RNG^Short" +msgstr "RNG^Közelről" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:142 +msgid "RNG^Normal" +msgstr "RNG^Normál" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:143 +msgid "RNG^Long" +msgstr "RNG^Távolról is" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:144 +msgid "RNG^Full" +msgstr "RNG^Teljes pályán" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:151 +msgid "Automatic taunts" +msgstr "Automatikus gúnyolódás" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:160 +msgid "Time warning:" +msgstr "Időre figyelmeztetés:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:162 +msgid "WRN^None" +msgstr "Kikapcsolva" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:163 +msgid "1 minute" +msgstr "1 perc" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:164 +msgid "5 minutes" +msgstr "5 perc" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:165 +msgid "WRN^Both" +msgstr "Mindkettő" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:168 +msgid "Hit indicator" +msgstr "Találat jelző" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:170 +msgid "Menu sounds" +msgstr "Menü hangok" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:38 +msgid "Quality preset:" +msgstr "Grafikai részletesség:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:41 +msgid "PRE^OMG!" +msgstr "PRE^ATYAÉG!" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:42 +msgid "PRE^Low" +msgstr "PRE^Alacsony" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:43 +msgid "PRE^Medium" +msgstr "PRE^Közepes" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:44 +msgid "PRE^Normal" +msgstr "PRE^Normál" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:45 +msgid "PRE^High" +msgstr "PRE^Magas" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:46 +msgid "PRE^Ultra" +msgstr "PRE^Nagyon magas" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:48 +msgid "PRE^Ultimate" +msgstr "PRE^Végső" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:52 +msgid "Geometry detail:" +msgstr "Geometriai részletesség:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:54 +msgid "DET^Lowest" +msgstr "DET^Legalacsonyabb" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:55 +msgid "DET^Low" +msgstr "DET^Alacsony" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:56 +msgid "DET^Normal" +msgstr "DET^Normál" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:57 +msgid "DET^Good" +msgstr "DET^Jó" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:58 +msgid "DET^Best" +msgstr "DET^Magas" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:59 +msgid "DET^Insane" +msgstr "DET^Nagyon magas" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:62 +msgid "Antialiasing:" +msgstr "Élsimítás:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:64 +msgid "AA^Disabled" +msgstr "AA^Letiltva" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:65 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:103 +msgid "2x" +msgstr "2x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:66 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:104 +msgid "4x" +msgstr "4x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:70 +msgid "Texture resolution:" +msgstr "Textúra felbontás:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:73 +msgid "RES^Leet" +msgstr "RES^Semmi" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:74 +msgid "RES^Lowest" +msgstr "RES^Legalacsonyabb" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:75 +msgid "RES^Low" +msgstr "RES^Alacsony" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:76 +msgid "RES^Normal" +msgstr "RES^Normál" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:77 +msgid "RES^Good" +msgstr "RES^Jó" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:78 +msgid "RES^Best" +msgstr "RES^Legjobb" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:91 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:94 +msgid "Avoid lossy texture compression" +msgstr "Veszteséges textúra tömörítés kikapcsolása" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:100 +msgid "Anisotropy:" +msgstr "Anizotrópia:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:102 +msgid "ANISO^Disabled" +msgstr "ANISO^Letiltva" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:105 +msgid "8x" +msgstr "8x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:106 +msgid "16x" +msgstr "16x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:110 +msgid "Particle quality:" +msgstr "Részecskék minősége:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:113 +msgid "Particle distance:" +msgstr "Részecskék megjelenítése:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:117 +msgid "Decals" +msgstr "Vér- és égésnyomok" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:118 +msgid "Decals on models" +msgstr "Foltok a modelleken" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:122 +msgid "Distance:" +msgstr "Megjelenítés távolsága:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:128 +msgid "Time:" +msgstr "Eltűnés ideje" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:134 +msgid "Use lightmaps" +msgstr "Fénytérképek használata" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:135 +msgid "Deluxe mapping" +msgstr "Deluxe mapping" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:137 +msgid "Gloss" +msgstr "Csillogás" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:140 +msgid "Offset mapping" +msgstr "Offset mapping" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:142 +msgid "Relief mapping" +msgstr "Relief mapping" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:145 +msgid "Reflections:" +msgstr "Tükröződés:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:148 +msgid "Blurred" +msgstr "Homályos" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:149 +msgid "REFL^Good" +msgstr "Refl^Jó" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:150 +msgid "Sharp" +msgstr "Éles" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:155 +msgid "Show surfaces" +msgstr "Felületek megjelenítése" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:157 +msgid "No dynamic lighting" +msgstr "Nincsenek dinamikus fények" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:159 +msgid "Flash blend approximation" +msgstr "Elnagyolt villanások" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:161 +msgid "Realtime dynamic lighting" +msgstr "Valós idejű dinamikus fények" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:162 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:166 +msgid "Shadows" +msgstr "Árnyékok" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:165 +msgid "Realtime world lighting" +msgstr "Valósidejű világ fények" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:170 +msgid "Use normal maps" +msgstr "Normal map használata" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:172 +msgid "Soft shadows" +msgstr "Lágy árnyékok" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:175 +msgid "Coronas" +msgstr "Fényudvarok" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:176 +msgid "Use Occlusion Queries" +msgstr "Láthatósági ellenőrzés" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:178 +msgid "Bloom" +msgstr "Ragyogás" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:180 +msgid "High Dynamic Range (HDR)" +msgstr "Magas dinamika tartomány (HDR)" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:184 +msgid "Motion blur:" +msgstr "Mozgási elmosódás:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:189 +msgid "Blur and sharpen postprocessing" +msgstr "Elmosás és élesítés" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:26 +msgid "Key bindings:" +msgstr "Billentyűzet-kiosztás:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:31 +msgid "Change key..." +msgstr "Megváltoztatás..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:35 +msgid "Edit..." +msgstr "Szerkesztés..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:46 +msgid "Sensitivity:" +msgstr "Érzékenység:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:51 +msgid "UI mouse speed:" +msgstr "Menü egér sebessége:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:55 +msgid "Mouse filter" +msgstr "Egérmozgás simítása" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:57 +msgid "Invert mouse" +msgstr "Fordított egérmozgás" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:60 +#: qcsrc/menu/xonotic/dialog_settings_input.c:62 +msgid "Use joystick input" +msgstr "Botkormány bemenet használata" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:65 +#: qcsrc/menu/xonotic/dialog_settings_input.c:67 +msgid "Turn off OS mouse acceleration" +msgstr "OS egér gyorsítás kikapcsolása" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:69 +msgid "\"enter console\" also closes" +msgstr "\"belépés a konzolba\" zár is" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:5 +msgid "User defined key bind" +msgstr "Felhasználó által beállított parancsok" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:42 +msgid "Command when pressed:" +msgstr "Parancs lenyomáskor:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:45 +msgid "Command when released:" +msgstr "Parancs felengedéskor:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:48 +msgid "Save" +msgstr "Mentés" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:51 +msgid "Cancel" +msgstr "Mégsem" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:26 +msgid "Menu skins:" +msgstr "Menü felületek:" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:47 +msgid "Show current time" +msgstr "Jelenlegi idő mutatása" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:49 +msgid "Show current date" +msgstr "Mai dátum mutatása" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:51 +msgid "Show frames per second" +msgstr "A képkocka/másodperc mutatása" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:53 +msgid "Minimize input latency" +msgstr "Bemeneti késleltetés minimalizása" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:5 +msgid "Advanced settings" +msgstr "Haladó beállítások" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:23 +msgid "Cvar filter:" +msgstr "Cvar szűrés:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:34 +msgid "Setting:" +msgstr "Beállítás:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:42 +msgid "Value:" +msgstr "Érték:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:56 +msgid "Description:" +msgstr "Leírás:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:26 +msgid "Client-side movement prediction" +msgstr "Kliens-oldali mozgásbecslés" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:30 +msgid "Show netgraph" +msgstr "Hálózat forgalom megjelenítése" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:33 +msgid "Network speed:" +msgstr "Hálózat sebessége:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:35 +msgid "56k" +msgstr "56k" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:36 +msgid "ISDN" +msgstr "ISDN" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:37 +msgid "Slow ADSL" +msgstr "Lassú ADSL" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:38 +msgid "Fast ADSL" +msgstr "Gyors ADSL" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:39 +msgid "Broadband" +msgstr "Szélessávú" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:42 +msgid "Input packets/s:" +msgstr "Bemeneti csomagok/s:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:46 +msgid "HTTP downloads:" +msgstr "HTTP letöltéseket:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:49 +msgid "Downloads:" +msgstr "Letöltések:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:53 +msgid "Speed (kB/s):" +msgstr "Sebesség (kB/s):" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:57 +msgid "Client UDP port:" +msgstr "Kliens UDP port:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:26 +msgid "Resolution:" +msgstr "Felbontás:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:29 +msgid "Font/UI size:" +msgstr "Betük/Menü mérete:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:31 +msgid "SZ^Unreadable" +msgstr "SZ^Olvashatatlan" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:32 +msgid "SZ^Tiny" +msgstr "SZ^Apró" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:33 +msgid "SZ^Little" +msgstr "SZ^Pici" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:34 +msgid "SZ^Small" +msgstr "SZ^Kicsi" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:35 +msgid "SZ^Medium" +msgstr "SZ^Közepes" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:36 +msgid "SZ^Large" +msgstr "SZ^Nagy" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:37 +msgid "SZ^Huge" +msgstr "SZ^Hatalmas" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:38 +msgid "SZ^Gigantic" +msgstr "SZ^Gigantikus" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:39 +msgid "SZ^Colossal" +msgstr "SZ^Óriási" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:42 +msgid "Color depth:" +msgstr "Színmélység:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:45 +msgid "Full screen" +msgstr "Teljes képernyő" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:46 +msgid "Vertical Synchronization" +msgstr "Szinkonizálás a képernyő frissítéshez" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:49 +msgid "Use OpenGL 2.0 shaders (GLSL)" +msgstr "OpenGL 2.0 shaderek (GLSL) használata" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:52 +msgid "Use GLSL to handle color control" +msgstr "GLSL használata a színvezérlés kezeléséhez" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:56 +msgid "Vertex Buffer Objects (VBOs)" +msgstr "Vertex Buffer Objects (VBOs)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:59 +msgid "VBO^Off" +msgstr "VBO^Off" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:60 +msgid "Vertices, some Tris (compatible)" +msgstr "Csúcspontok, néhány háromszög (kompatibilis)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:63 +msgid "Vertices" +msgstr "Csúcspontok" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:64 +msgid "Vertices and Triangles" +msgstr "Csúcspontok és háromszögek" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:67 +msgid "Depth first:" +msgstr "Mélység először:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:69 +msgid "DF^Disabled" +msgstr "Kikapcsolva" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:70 +msgid "DF^World" +msgstr "Világ" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:71 +msgid "DF^All" +msgstr "Minden" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:75 +msgid "Disable multithreaded OpenGL" +msgstr "Többszálú OpenGL letiltása" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:77 +msgid "Wait for GPU to finish each frame" +msgstr "Várakozás a GPU-ra minden képkockánál" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:80 +msgid "Brightness:" +msgstr "Fényerő:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:83 +msgid "Contrast:" +msgstr "Kontraszt:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:86 +msgid "Gamma:" +msgstr "Gamma:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:91 +msgid "Contrast boost:" +msgstr "Kontraszt növelés:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:96 +msgid "Saturation:" +msgstr "Színtelítettség:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:102 +msgid "LIT^Ambient:" +msgstr "Környezet:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:105 +msgid "Intensity:" +msgstr "Erősség:" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:4 +msgid "Singleplayer" +msgstr "Egyjátékos mód" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:127 +msgid "Instant action! (random map with bots)" +msgstr "Azonnali játék (véletlenszerű pálya botokkal)" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:148 +msgid "Start Singleplayer!" +msgstr "Egyjátékos mód indítása" + +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:4 +msgid "Winner" +msgstr "Győztes" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:5 +msgid "Team Selection" +msgstr "Válassz csapatot!" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:41 +msgid "join 'best' team (auto-select)" +msgstr "Csatlakozás a 'legjobb' csapathoz (automatikus-választás)" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:45 +msgid "red" +msgstr "Vörös" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:46 +msgid "blue" +msgstr "Kék" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:47 +msgid "yellow" +msgstr "Sárga" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:48 +msgid "pink" +msgstr "Rózsaszín" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:51 +msgid "spectate" +msgstr "Nézőként csatlakozok" + +#: qcsrc/menu/xonotic/mainwindow.c:35 qcsrc/menu/xonotic/mainwindow.c:38 +msgid "Do not press this button again!" +msgstr "Ne nyomd meg újra ezt a gombot!" + +#: qcsrc/menu/xonotic/maplist.c:278 +msgid "" +"Huh? Can't play this (m is NULL). Refiltering so this won't happen again.\n" +msgstr "" +"Jajj? Ezzel nem lehet játszani (m is NULL). Állítsd át a szűrést, hogy ne " +"ismétlődjön meg!\n" + +#: qcsrc/menu/xonotic/maplist.c:286 +#, c-format +msgid "%s's Xonotic Server" +msgstr "%s Xonotic szervere" + +#: qcsrc/menu/xonotic/maplist.c:291 +msgid "" +"Huh? Can't play this (invalid game type). Refiltering so this won't happen " +"again.\n" +msgstr "" +"Jajj? Ezzel nem lehet játszani (érvénytelen játék típus). Állítsd át a " +"szűrést, hogy ne ismétlődjön meg!\n" +"." + +#: qcsrc/menu/xonotic/playermodel.c:174 +msgid "<no model found>" +msgstr "<modell nem található>" + +#: qcsrc/menu/xonotic/serverlist.c:185 +msgid "Remove" +msgstr "Eltávolítás" + +#: qcsrc/menu/xonotic/serverlist.c:187 +msgid "Bookmark" +msgstr "Könyvjelző" + +#: qcsrc/menu/xonotic/serverlist.c:527 +msgid "Ping" +msgstr "Ping" + +#: qcsrc/menu/xonotic/serverlist.c:528 +msgid "Host name" +msgstr "Gazda név" + +#: qcsrc/menu/xonotic/serverlist.c:529 +msgid "Map" +msgstr "Pálya" + +#: qcsrc/menu/xonotic/serverlist.c:530 +msgid "Type" +msgstr "Típus" + +#: qcsrc/menu/xonotic/serverlist.c:531 +msgid "Players" +msgstr "Játékosok" + +#: qcsrc/menu/xonotic/skinlist.c:105 +msgid "<TITLE>" +msgstr "<CÍM>" + +#: qcsrc/menu/xonotic/skinlist.c:106 +msgid "<AUTHOR>" +msgstr "<SZERZŐ>" + +#: qcsrc/menu/xonotic/slider_decibels.c:50 +msgid "VOL^OFF" +msgstr "Kikapcsolva" + +#: qcsrc/menu/xonotic/slider_decibels.c:52 +msgid "VOL^MAX" +msgstr "Maximum hangerő" + +#: qcsrc/menu/xonotic/slider_decibels.c:53 +#, c-format +msgid "%s dB" +msgstr "%s dB" + +#: qcsrc/menu/xonotic/slider_resolution.c:65 +#, c-format +msgid "%dx%d" +msgstr "%dx%d" + +#: qcsrc/menu/xonotic/util.qc:270 +#, c-format +msgid "Received HTTP request data for an invalid id %d.\n" +msgstr "Érvénytelen HTTP adatkérés érkezett id %d.\n" + +#: qcsrc/menu/xonotic/util.qc:285 +#, c-format +msgid "error receiving update notification: status is %d\n" +msgstr "Frissítési értesítési hiba: az állapota %d\n" + +#: qcsrc/menu/xonotic/util.qc:290 +msgid "error: received HTML instead of an update notification\n" +msgstr "Hiba: frissítési értesítés helyett egy HTML-t kapott\n" + +#: qcsrc/menu/xonotic/util.qc:295 +msgid "error: received carriage returns from update notification server\n" +msgstr "Hiba: a frissítés értesítő szerverről egy 'kocsi vissza'-t kapott\n" + +#: qcsrc/menu/xonotic/util.qc:316 +#, c-format +msgid "" +"Update can be downloaded at:\n" +"%s\n" +msgstr "" +"Frissítés letölthető: \n" +"%s -ről\n" + +#: qcsrc/menu/xonotic/util.qc:337 +msgid "Autogenerating mapinfo for newly added maps..." +msgstr "MapInfo készítése az újonnan hozzáadott pályákhoz..." + +#: qcsrc/menu/xonotic/util.qc:367 +#, c-format +msgid "^1%s TEST BUILD" +msgstr "^1%s TEST BUILD" + +#: qcsrc/menu/xonotic/util.qc:432 +#, c-format +msgid "Update to %s now!" +msgstr "Most frissítsd %s-re/ra!" + +#: qcsrc/menu/xonotic/util.qc:501 +msgid "" +"^1ERROR: Texture compression is required but not supported.\n" +"^1Expect visual problems.\n" +msgstr "" +"^1Hiba: textúra tömörítés szükséges, de nem támogatott.\n" +"^1Gondok lehetnek a megjelenítéssel.\n" + +#: qcsrc/menu/xonotic/util.qc:523 +msgid "Arena" +msgstr "Aréna" + +#: qcsrc/menu/xonotic/util.qc:524 +msgid "Assault" +msgstr "Ostrom" + +#: qcsrc/menu/xonotic/util.qc:525 +msgid "Capture The Flag" +msgstr "Zászlórablás" + +#: qcsrc/menu/xonotic/util.qc:526 +msgid "Clan Arena" +msgstr "Klán Aréna" + +#: qcsrc/menu/xonotic/util.qc:527 +msgid "Deathmatch" +msgstr "Haláljátszma" + +#: qcsrc/menu/xonotic/util.qc:528 +msgid "Domination" +msgstr "Uralom" + +#: qcsrc/menu/xonotic/util.qc:529 +msgid "Freeze Tag" +msgstr "Fagyasztás" + +#: qcsrc/menu/xonotic/util.qc:530 +msgid "Keepaway" +msgstr "Önzőség" + +#: qcsrc/menu/xonotic/util.qc:531 +msgid "Key Hunt" +msgstr "Kulcsvadászat" + +#: qcsrc/menu/xonotic/util.qc:532 +msgid "Last Man Standing" +msgstr "Csak egy maradhat" + +#: qcsrc/menu/xonotic/util.qc:533 +msgid "Nexball" +msgstr "Nexball" + +#: qcsrc/menu/xonotic/util.qc:534 +msgid "Onslaught" +msgstr "Támadás" + +#: qcsrc/menu/xonotic/util.qc:535 +msgid "Race" +msgstr "Verseny" + +#: qcsrc/menu/xonotic/util.qc:536 +msgid "Race CTS" +msgstr "Ügyességi verseny" + +#: qcsrc/menu/xonotic/util.qc:537 +msgid "Runematch" +msgstr "Rúnameccs" + +#: qcsrc/menu/xonotic/util.qc:538 +msgid "Team Deathmatch" +msgstr "Csapat[os] öldöklés " + +#: qcsrc/menu/xonotic/util.qc:557 +#, c-format +msgid "@!#%'n Tuba Throwing" +msgstr "@!#%'n Tuba Dobás" + +#: qcsrc/menu/xonotic/util.qc:577 qcsrc/menu/xonotic/util.qc:593 +#: qcsrc/menu/xonotic/util.qc:602 qcsrc/menu/xonotic/util.qc:610 +#: qcsrc/menu/xonotic/util.qc:622 +msgid "Default" +msgstr "Alapértelmezett" + +#: qcsrc/menu/xonotic/util.qc:588 +msgid "Use default" +msgstr "Alapértékek használata" + +#: qcsrc/menu/xonotic/util.qc:608 +msgid "Team Color:" +msgstr "Csapat színe:" + +#: qcsrc/menu/xonotic/util.qh:47 +msgid "Enable panel" +msgstr "Panel engedélyezése" + +#: qcsrc/server/w_crylink.qc:2 +msgid "Crylink" +msgstr "Crylink" + +#: qcsrc/server/w_crylink.qc:666 +#, c-format +msgid "%s succeeded at self-destructing themself with the Crylink" +msgstr "%s sikeres öngyikosságot követett el Crylinkkel" + +#: qcsrc/server/w_crylink.qc:671 +#, c-format +msgid "%s could not hide from %s's Crylink" +msgstr "%s nem menekülhetett %s Crylinkje elől" + +#: qcsrc/server/w_crylink.qc:673 +#, c-format +msgid "%s was too close to %s's Crylink" +msgstr "%s túl közel hajolt %s Crylinkjéhez" + +#: qcsrc/server/w_crylink.qc:675 +#, c-format +msgid "%s took a close look at %s's Crylink" +msgstr "%s közelebbről megleste %s Crylinkjét" + +#: qcsrc/server/w_electro.qc:2 +msgid "Electro" +msgstr "Electro" + +#: qcsrc/server/w_electro.qc:574 +#, c-format +msgid "%s could not remember where they put plasma" +msgstr "%s nem tudja, hogy mire való a plazma" + +#: qcsrc/server/w_electro.qc:576 +#, c-format +msgid "%s played with plasma" +msgstr "%s plazmával játszadozott" + +#: qcsrc/server/w_electro.qc:583 +#, c-format +msgid "%s just noticed %s's blue ball" +msgstr "%s csak most vette észre %s kék golyóját" + +#: qcsrc/server/w_electro.qc:585 +#, c-format +msgid "%s got in touch with %s's blue ball" +msgstr "%s lefejelte %s kék golyóját" + +#: qcsrc/server/w_electro.qc:590 +#, c-format +msgid "%s felt the electrifying air of %s's combo" +msgstr "%s felvillanyozódott %s kombójától" + +#: qcsrc/server/w_electro.qc:592 +#, c-format +msgid "%s got too close to %s's blue beam" +msgstr "%s túl közel került %s kék sugarához" + +#: qcsrc/server/w_electro.qc:594 +#, c-format +msgid "%s was blasted by %s's blue beam" +msgstr "%s megsemmisült %s kék sugarától" + +#: qcsrc/server/w_fireball.qc:2 +#, fuzzy +msgid "Fireball" +msgstr "Tűzgolyó" + +#: qcsrc/server/w_fireball.qc:417 +#, c-format +msgid "%s forgot about some firemine" +msgstr "%s megfeledkezett pár gyújtóbombáról" + +#: qcsrc/server/w_fireball.qc:419 qcsrc/server/w_hlac.qc:240 +#, c-format +msgid "%s should have used a smaller gun" +msgstr "%s játszott volna vízipisztollyal " + +#: qcsrc/server/w_fireball.qc:426 +#, c-format +msgid "%s tried to catch %s's firemine" +msgstr "%s megpróbálta elkapni %s gyújtóbombáját" + +#: qcsrc/server/w_fireball.qc:428 +#, c-format +msgid "%s fatefully ignored %s's firemine" +msgstr "%s már tudja, hogy %s gyújtóbombájának figyelmen kívül hagyása végzetes." + +#: qcsrc/server/w_fireball.qc:435 +#, c-format +msgid "%s could not hide from %s's fireball" +msgstr "%s nem tudott elbújni %s tűzgolyójától" + +#: qcsrc/server/w_fireball.qc:437 +#, c-format +msgid "%s saw the pretty lights of %s's fireball" +msgstr "%s látthatta %s tűzgolyójának csinos fényeit" + +#: qcsrc/server/w_fireball.qc:440 +#, c-format +msgid "%s got too close to %s's fireball" +msgstr "%s túl közel merészkedett %s tűzgolyójához" + +#: qcsrc/server/w_fireball.qc:442 +#, c-format +msgid "%s tasted %s's fireball" +msgstr "%s megízlelte %s tűzgolyóját" + +#: qcsrc/server/w_grenadelauncher.qc:2 +#, fuzzy +msgid "Mortar" +msgstr "Mortar" + +#: qcsrc/server/w_grenadelauncher.qc:383 +#, c-format +msgid "%s tried out his own grenade" +msgstr "%s kipróbálta saját gránátját" + +#: qcsrc/server/w_grenadelauncher.qc:385 +#, fuzzy, c-format +msgid "%s detonated" +msgstr "%s felrobbant" + +#: qcsrc/server/w_grenadelauncher.qc:391 +#, c-format +msgid "%s didn't see %s's grenade" +msgstr "%s nem látta %s gránátját" + +#: qcsrc/server/w_grenadelauncher.qc:393 +#, c-format +msgid "%s almost dodged %s's grenade" +msgstr "%s majdnem kicselezte %s gránátját" + +#: qcsrc/server/w_grenadelauncher.qc:395 +#, c-format +msgid "%s ate %s's grenade" +msgstr "%s bekapta %s gránátját" + +#: qcsrc/server/w_hagar.qc:2 +msgid "Hagar" +msgstr "Hagar" + +#: qcsrc/server/w_hagar.qc:395 qcsrc/server/w_seeker.qc:655 +#, c-format +msgid "%s played with tiny rockets" +msgstr "%s kis rakétákkal játszott" + +#: qcsrc/server/w_hagar.qc:399 +#, c-format +msgid "%s hoped %s's missiles wouldn't bounce" +msgstr "%s remélte, hogy %s rakétája nem éri el" + +#: qcsrc/server/w_hagar.qc:401 qcsrc/server/w_seeker.qc:661 +#, c-format +msgid "%s was pummeled by %s" +msgstr "%s -t ledarálta %s Hagarja" + +#: qcsrc/server/w_hlac.qc:2 +msgid "Heavy Laser Assault Cannon" +msgstr "Nehéz Lézer Roham Ágyú" + +#: qcsrc/server/w_hlac.qc:242 +#, c-format +msgid "%s was cut down by %s" +msgstr "%s -t feldarabolta %s" + +#: qcsrc/server/w_hook.qc:2 +#, fuzzy +msgid "Grappling Hook" +msgstr "Vonóhorog" + +#: qcsrc/server/w_hook.qc:266 qcsrc/server/w_porto.qc:296 +#, c-format +msgid "%s did the impossible" +msgstr "%s megcsinálta a lehetetlent" + +#: qcsrc/server/w_hook.qc:268 +#, c-format +msgid "%s has run into %s's gravity bomb" +msgstr "%s beleszalad %s gravitációs bombájába" + +#: qcsrc/server/w_laser.qc:2 +#, fuzzy +msgid "Laser" +msgstr "Lézer" + +#: qcsrc/server/w_laser.qc:311 +#, c-format +msgid "%s lasered themself to hell" +msgstr "%s magán lézershowja rosszul sült el" + +#: qcsrc/server/w_laser.qc:315 +#, c-format +msgid "%s was cut in half by %s's gauntlet" +msgstr "%s -t félbevágta %s kesztyűje" + +#: qcsrc/server/w_laser.qc:317 +#, c-format +msgid "%s was lasered to death by %s" +msgstr "%s meghalt %s lézere által" + +#: qcsrc/server/w_minelayer.qc:2 +#, fuzzy +msgid "Mine Layer" +msgstr "Aknavető" + +#: qcsrc/server/w_minelayer.qc:523 qcsrc/server/w_rocketlauncher.qc:501 +#, c-format +msgid "%s exploded" +msgstr "%s felrobbant" + +#: qcsrc/server/w_minelayer.qc:527 +#, c-format +msgid "%s got too close to %s's mine" +msgstr "%s túl közel került %s aknájához" + +#: qcsrc/server/w_minelayer.qc:529 +#, c-format +msgid "%s almost dodged %s's mine" +msgstr "%s majdnem elkerülte %s aknáját" + +#: qcsrc/server/w_minelayer.qc:531 +#, c-format +msgid "%s stepped on %s's mine" +msgstr "%s rálépett %s aknájára" + +#: qcsrc/server/w_minstanex.qc:2 +#, fuzzy +msgid "MinstaNex" +msgstr "MinstaGib" + +#: qcsrc/server/w_minstanex.qc:293 qcsrc/server/w_nex.qc:253 +#: qcsrc/server/w_shotgun.qc:215 qcsrc/server/w_uzi.qc:317 +#, c-format +msgid "%s is now thinking with portals" +msgstr "%s most már portálokkal mereng" + +#: qcsrc/server/w_minstanex.qc:295 qcsrc/server/w_nex.qc:255 +#, c-format +msgid "%s has been vaporized by %s" +msgstr "%s -t gázzá vált %s által" + +#: qcsrc/server/w_nex.qc:2 +#, fuzzy +msgid "Nex" +msgstr "Nex" + +#: qcsrc/server/w_porto.qc:2 +msgid "Port-O-Launch" +msgstr "Port-O-Launch" + +#: qcsrc/server/w_porto.qc:298 +#, c-format +msgid "%s felt %s doing the impossible to him" +msgstr "%s érezte, hogy %s lehetetlen tett vele" + +#: qcsrc/server/w_rifle.qc:2 +msgid "Rifle" +msgstr "Puska" + +#: qcsrc/server/w_rifle.qc:233 +#, c-format +msgid "%s shot themself automatically" +msgstr "%s saját magát lőtte agyon" + +#: qcsrc/server/w_rifle.qc:235 +#, c-format +msgid "%s sniped themself somehow" +msgstr "%s-t levadászta saját magát valahogy" + +#: qcsrc/server/w_rifle.qc:242 +#, c-format +msgid "%s failed to hide from %s's bullet hail" +msgstr "%s -nak nem sikerült elbújnia %s golyózápora elől " + +#: qcsrc/server/w_rifle.qc:244 +#, c-format +msgid "%s died in %s's bullet hail" +msgstr "%s meghalt %s golyózáporában" + +#: qcsrc/server/w_rifle.qc:251 +#, c-format +msgid "%s failed to hide from %s's rifle" +msgstr "%s -nak nem sikerült elbújnia %s puskája elöl" + +#: qcsrc/server/w_rifle.qc:256 +#, c-format +msgid "%s got hit in the head by %s" +msgstr "%s -t fejen találta %s" + +#: qcsrc/server/w_rifle.qc:258 qcsrc/server/w_uzi.qc:321 +#, c-format +msgid "%s was sniped by %s" +msgstr "%s -t levadászta %s" + +#: qcsrc/server/w_rocketlauncher.qc:2 +msgid "Rocket Launcher" +msgstr "Rakétavető" + +#: qcsrc/server/w_rocketlauncher.qc:505 +#, c-format +msgid "%s got too close to %s's rocket" +msgstr "%s túl közel kerül %s rakétájához" + +#: qcsrc/server/w_rocketlauncher.qc:507 +#, c-format +msgid "%s almost dodged %s's rocket" +msgstr "%s majdnem kicselezte %s rakétáját" + +#: qcsrc/server/w_rocketlauncher.qc:509 +#, c-format +msgid "%s ate %s's rocket" +msgstr "%s megette %s rakétáját" + +#: qcsrc/server/w_seeker.qc:2 +msgid "T.A.G. Seeker" +msgstr "T.A.G. Seeker" + +#: qcsrc/server/w_seeker.qc:659 +#, c-format +msgid "%s was tagged by %s" +msgstr "%s-t megjelölte %s" + +#: qcsrc/server/w_shotgun.qc:2 +#, fuzzy +msgid "Shotgun" +msgstr "Vadászpuska" + +#: qcsrc/server/w_shotgun.qc:219 +#, c-format +msgid "%2$s ^7slapped %1$s ^7around a bit with a large ^2shotgun" +msgstr "%2$s ^7úgy elverte %1$s -t ^7 a ^2puskályával, mintha ^7szívlapáttal csapta volna agyon" + +#: qcsrc/server/w_shotgun.qc:221 +#, c-format +msgid "%s was gunned by %s" +msgstr "%s-t lelőtte %s" + +#: qcsrc/server/w_tuba.qc:2 +#, fuzzy, c-format +msgid "@!#%'n Tuba" +msgstr "@!#%'n Tuba Dobás" + +#: qcsrc/server/w_tuba.qc:252 +#, c-format +msgid "%s hurt his own ears with the @!#%%'n Tuba" +msgstr "%s se bírta tovább a @!#%%'n Tuba hangját" + +#: qcsrc/server/w_tuba.qc:256 +#, c-format +msgid "%s died of %s's great playing on the @!#%%'n Tuba" +msgstr "%s meghalt %s nagyszerű @!#%%'n Tuba játékától" + +#: qcsrc/server/w_uzi.qc:2 +msgid "Machine Gun" +msgstr "Gépfegyver" + +#: qcsrc/server/w_uzi.qc:323 +#, c-format +msgid "%s was riddled full of holes by %s" +msgstr "%s -t %s szitává lyuggatta" + +#, fuzzy +#~ msgid "Damage & water blur" +#~ msgstr "Sérülés és víz elmosás" + +#, fuzzy +#~ msgid "Powerup sharpen" +#~ msgstr "Powerup élesítés" + +#~ msgid "Speedometer" +#~ msgstr "Sebességmérő" + +#~ msgid "qu/s (hidden)" +#~ msgstr "qu/s (rejtett)" + +#~ msgid "Show accelerometer" +#~ msgstr "Gyorsulásmérő mutatása" + +#~ msgid "Accelerometer scale:" +#~ msgstr "Gyorsulásmérő beosztás:" + +#~ msgid "" +#~ "Please answer a few initial questions to enhance the game experience." +#~ msgstr "" +#~ "A jobb játékélmény érdekében, kérlek, válaszolj pár inditó kérdésre!" + +#~ msgid "Waypoint settings:" +#~ msgstr "Iránypont beállítások:" + +#~ msgid "%d/%d" +#~ msgstr "%d/%d" diff --git a/menu.dat.it.po b/menu.dat.it.po new file mode 100644 index 0000000000..187fa667f9 --- /dev/null +++ b/menu.dat.it.po @@ -0,0 +1,2918 @@ +# Xonotic Menu +# Copyright (C) 2011 Team Xonotic +# This file is distributed under the same license as the PACKAGE package. +# Felice Sallustio <fel.sallustio@gmail.com>, 2011. +# Antonio 'terencehill' Piu <piuntn@gmail.com>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: 0.1preview\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-09-02 07:51+0200\n" +"PO-Revision-Date: 2011-09-04 01:40+0100\n" +"Last-Translator: Antonio 'terencehill' Piu <piuntn@gmail.com>\n" +"Language-Team: Antonio 'terencehill' Piu <piuntn@gmail.com>\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Italian\n" + +#: qcsrc/common/mapinfo.qc:1092 qcsrc/menu/xonotic/skinlist.c:163 +#, c-format +msgid "%s: %s" +msgstr "%s: %s" + +#: qcsrc/menu/gamecommand.qc:47 +#, c-format +msgid "error: status is %d\n" +msgstr "errore: lo stato è impostato su %d\n" + +#: qcsrc/menu/gamecommand.qc:65 +msgid "Usage: menu_cmd command..., where possible commands are:\n" +msgstr "Uso: menu_cmd comando..., dove i possibili comandi sono:\n" + +#: qcsrc/menu/gamecommand.qc:66 +msgid " sync - reloads all cvars on the current menu page\n" +msgstr " sync - ricarica tutte le cvar sulla corrente pagina\n" + +#: qcsrc/menu/gamecommand.qc:67 +msgid " directmenu ITEM - select a menu item as main item\n" +msgstr " directmenu OGGETTO - seleziona un oggetto come il principale\n" + +#: qcsrc/menu/gamecommand.qc:193 +msgid "error creating curl handle\n" +msgstr "error creating curl handle\n" + +#: qcsrc/menu/gamecommand.qc:239 +msgid "Invalid command. For a list of supported commands, try menu_cmd help.\n" +msgstr "" +"Comando non valido. Per una lista dei comandi supportati, prova menu_cmd " +"help.\n" + +#: qcsrc/menu/item/gecko.c:49 +msgid "Browser not initialized!" +msgstr "Browser non inizializzato!" + +#: qcsrc/menu/item/label.c:63 +#, c-format +msgid "NOTE: label text %s too wide for label, condensed by factor %f\n" +msgstr "" +"NOTA: testo dell'etichetta %s troppo grande per l'etichetta, compresso di un " +"fattore %f\n" + +#: qcsrc/menu/item/listbox.c:300 +#, c-format +msgid "Item %d" +msgstr "Oggetto %d" + +#: qcsrc/menu/item/slider.c:64 +#, c-format +msgid "%d (%s)" +msgstr "%d (%s)" + +#: qcsrc/menu/item/textslider.c:29 qcsrc/menu/item/textslider.c:31 +msgid "custom" +msgstr "personalizzato" + +#: qcsrc/menu/menu.qc:29 +#, c-format +msgid "^4MQC Build information: ^1%s\n" +msgstr "^4MQC Build information: ^1%s\n" + +#: qcsrc/menu/xonotic/campaign.c:284 +#: qcsrc/menu/xonotic/dialog_singleplayer.c:134 +msgid "???" +msgstr "???" + +#: qcsrc/menu/xonotic/campaign.c:285 +#, c-format +msgid "Level %d: %s" +msgstr "Livello %d: %s" + +#: qcsrc/menu/xonotic/cvarlist.c:85 +msgid "will be saved to config.cfg" +msgstr "sarà salvato su config.cfg" + +#: qcsrc/menu/xonotic/cvarlist.c:87 +msgid "will not be saved" +msgstr "non sarà salvato" + +#: qcsrc/menu/xonotic/cvarlist.c:89 +msgid "private" +msgstr "privata" + +#: qcsrc/menu/xonotic/cvarlist.c:91 +msgid "engine setting" +msgstr "impostazioni motore" + +#: qcsrc/menu/xonotic/cvarlist.c:93 +msgid "read only" +msgstr "sola lettura" + +#: qcsrc/menu/xonotic/dialog_credits.c:5 +msgid "Credits" +msgstr "Crediti" + +#: qcsrc/menu/xonotic/dialog_credits.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:269 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:41 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:57 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:61 +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:21 +msgid "OK" +msgstr "OK" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:4 +msgid "Welcome" +msgstr "Benvenuto" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:33 +msgid "" +"Welcome to Xonotic, please select your language preference and enter your " +"player name to get started. You can change these options later through the " +"menu system." +msgstr "" +"Benvenuto in Xonotic, per favore selezione la tua lingua e inserisci il tuo " +"nome come giocatore per iniziare. Puoi cambiare queste opzioni più tardi " +"tramite il menu." + +#: qcsrc/menu/xonotic/dialog_firstrun.c:38 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:35 +msgid "Text language:" +msgstr "Lingua di testo:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:47 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:40 +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:39 +msgid "Name:" +msgstr "Nome:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:69 +msgid "Save settings" +msgstr "Salva impostazioni" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:4 +msgid "Ammo Panel" +msgstr "Pannello munizioni" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:22 +msgid "Ammunition display:" +msgstr "Mostra munizioni:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:25 +msgid "Show only current ammo type" +msgstr "Mostra solo il tipo corrente di munizioni" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:28 +msgid "Align icon:" +msgstr "Allinea icone:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:29 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:36 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:40 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:40 +msgid "Left" +msgstr "Sinistra" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:38 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:41 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:41 +msgid "Right" +msgstr "Destra" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:4 +msgid "Centerprint" +msgstr "Centerprint" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:23 +msgid "Message duration:" +msgstr "Durata messaggi:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:27 +msgid "Fade time:" +msgstr "Durata dissolvenza:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:31 +msgid "Flip messages order" +msgstr "Inverti ordine messaggi" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:33 +msgid "Text alignment:" +msgstr "Allineamento testo:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:37 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:50 +msgid "Center" +msgstr "Centro" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:41 +msgid "Font scale:" +msgstr "Scala testo:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:4 +msgid "Chat Panel" +msgstr "Pannello Chat" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:22 +msgid "Chat entries:" +msgstr "N° righe della chat:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:25 +msgid "Chat size:" +msgstr "Dimensioni chat:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:29 +msgid "Chat lifetime:" +msgstr "Durata chat:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:33 +msgid "Chat beep sound" +msgstr "Suono della chat" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:4 +msgid "Engine Info Panel" +msgstr "Pannello info motore" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:22 +msgid "Engine info:" +msgstr "Info motore:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:25 +msgid "Use an averaging algorithm for fps" +msgstr "Usa un algoritmo mediano per gli fps" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:4 +msgid "Health/Armor Panel" +msgstr "Pannello vita/armatura" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:22 +msgid "Enable status bar" +msgstr "Abilita barra di stato" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:24 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:24 +msgid "Status bar alignment:" +msgstr "Allineamento barra di stato:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:42 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:42 +msgid "Inward" +msgstr "Interno" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:43 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:43 +msgid "Outward" +msgstr "Esterno" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:37 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:37 +msgid "Icon alignment:" +msgstr "Allineamento icone:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:45 +msgid "Flip health and armor positions" +msgstr "Inverti posizioni di vita e armatura" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:4 +msgid "Info Messages Panel" +msgstr "Pannello delle informazioni" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:22 +msgid "Info messages:" +msgstr "Informazioni" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:25 +msgid "Flip align" +msgstr "Inverti allineamento" + +#: qcsrc/menu/xonotic/dialog_hudpanel_modicons.c:4 +msgid "Mod Icons Panel" +msgstr "Pannello delle icone delle Mod" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:4 +msgid "Notification Panel" +msgstr "Pannello di notifica" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:22 +msgid "Notifications:" +msgstr "Notifiche:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:25 +msgid "Also print notifications to the console" +msgstr "Mostra anche le notifiche sulla console" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:28 +msgid "Flip notify order" +msgstr "Inverti ordine notifiche" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:31 +msgid "Entry lifetime:" +msgstr "Durata notifica:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:35 +msgid "Entry fadetime:" +msgstr "Durata dissolvenza:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:4 +msgid "Physics Panel" +msgstr "Pannello Fisica" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:21 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:21 +msgid "Panel disabled" +msgstr "Pannello disabilitato" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:23 +msgid "Panel enabled" +msgstr "Pannello abilitato" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:24 +msgid "Panel enabled even observing" +msgstr "Pannello abilitato anche osservando" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:25 +msgid "Panel enabled only in Race/CTS" +msgstr "Pannello abilitato solo in Corsa/CTS" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:31 +msgid "Status bar" +msgstr "Barra di stato" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:48 +msgid "Left align" +msgstr "Allinea a sinistra" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:34 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:52 +msgid "Right align" +msgstr "Allinea a destra" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:35 +msgid "Inward align" +msgstr "Allinea all'interno" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:36 +msgid "Outward align" +msgstr "Allinea all'esterno" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:40 +msgid "Flip speed/acceleration positions" +msgstr "Inverti posizioni velocità/accelerazione" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:44 +msgid "Speed:" +msgstr "Velocità:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:45 +msgid "Include vertical speed" +msgstr "Includi velocità verticale" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:56 +msgid "Speed unit:" +msgstr "Unità di velocità:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:58 +msgid "qu/s" +msgstr "qu/s" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:59 +msgid "m/s" +msgstr "m/s" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:60 +msgid "km/h" +msgstr "km/h" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:61 +msgid "mph" +msgstr "mph" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:62 +msgid "knots" +msgstr "nodi" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:64 +msgid "Show" +msgstr "Mostra" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:67 +msgid "Top speed" +msgstr "Velocità massima" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:73 +msgid "Acceleration:" +msgstr "Accelerazione:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:74 +msgid "Include vertical acceleration" +msgstr "Includi accelerazione verticale" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:4 +msgid "Powerups Panel" +msgstr "Pannello dei Powerup" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:45 +msgid "Flip strength and shield positions" +msgstr "Inverti posizioni di forza e scudo" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:4 +msgid "Pressed Keys Panel" +msgstr "Pannello dei tasto premuti" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:22 +msgid "Panel enabled when spectating" +msgstr "Pannello abilitato quando spettatore" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:23 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:23 +msgid "Panel always enabled" +msgstr "Pannello sempre abilitato" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:30 +msgid "Forced aspect:" +msgstr "Forza aspetto:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_racetimer.c:4 +msgid "Race Timer Panel" +msgstr "Pannello tempi Corsa" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:4 +msgid "Radar Panel" +msgstr "Pannello Radar" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:22 +msgid "Panel enabled in teamgames" +msgstr "Pannello abilitato nei teamgames" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:29 +msgid "Radar:" +msgstr "Radar:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:32 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:43 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:154 +#: qcsrc/menu/xonotic/util.qc:600 +msgid "Alpha:" +msgstr "Opacità:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:36 +msgid "Rotation:" +msgstr "Rotazione:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:38 +msgid "Forward" +msgstr "Avanti" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:39 +msgid "West" +msgstr "Ovest" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:40 +msgid "South" +msgstr "Sud" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:41 +msgid "East" +msgstr "Est" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:42 +msgid "North" +msgstr "Nord" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:46 +msgid "Scale:" +msgstr "Scala:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:50 +msgid "Zoom mode:" +msgstr "Modalità zoom:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:52 +msgid "Zoomed in" +msgstr "Ingrandito" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:53 +msgid "Zoomed out" +msgstr "Non ingrandito" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:54 +msgid "Always zoomed" +msgstr "Sempre ingrandito" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:55 +msgid "Never zoomed" +msgstr "Mai ingrandito" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:4 +msgid "Score Panel" +msgstr "Pannello punteggio" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:22 +msgid "Score:" +msgstr "Punteggi:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:25 +msgid "Rankings:" +msgstr "Classifica:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:26 +msgid "Off" +msgstr "Off" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:27 +msgid "And me" +msgstr "E me" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:28 +msgid "Pure" +msgstr "Puro" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:4 +msgid "Timer Panel" +msgstr "Pannello tempo" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:22 +msgid "Timer:" +msgstr "Tempo:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:25 +msgid "Show elapsed time" +msgstr "Mostra tempo trascorso" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:4 +msgid "Vote Panel" +msgstr "Pannello di voto" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:22 +msgid "Alpha after voting:" +msgstr "Opacità dopo aver votato:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:4 +msgid "Weapons Panel" +msgstr "Pannello armi" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:24 +msgid "Fade out after:" +msgstr "Dissolvi dopo:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:26 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:36 +msgid "Never" +msgstr "Mai" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:28 +#, c-format +msgid "%ds" +msgstr "%ds" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:32 +msgid "Fade effect:" +msgstr "Effetto dissolvenza:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:35 +msgid "EF^None" +msgstr "EF^Nessuno" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:36 +msgid "Slide" +msgstr "Slide" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:37 +msgid "Alpha" +msgstr "Opacità" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:38 +msgid "EF^Both" +msgstr "EF^Entrambi" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:42 +msgid "Weapon icons:" +msgstr "Icone armi:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:45 +msgid "Show weapon ID as:" +msgstr "Mostra ID arma come:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:46 +msgid "SHOWAS^None" +msgstr "SHOWAS^Nessuno" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:47 +msgid "Number" +msgstr "Numero" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:48 +msgid "Bind" +msgstr "Tasto" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:51 +msgid "Show Accuracy" +msgstr "Mostra precisione" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:52 +msgid "Show Ammo" +msgstr "Mostra munizioni" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:55 +msgid "Ammo bar color:" +msgstr "Colore barra munizioni:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:61 +msgid "Ammo bar alpha:" +msgstr "Opacità barra munizioni:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:4 +msgid "Panel HUD Setup" +msgstr "Setup del Panel HUD" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:21 +msgid "Panel background defaults:" +msgstr "Predefiniti dello sfondo del pannello:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:23 qcsrc/menu/xonotic/util.qc:575 +msgid "Background:" +msgstr "Sfondo:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:25 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:37 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:52 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:91 qcsrc/menu/xonotic/util.qc:578 +#: qcsrc/menu/xonotic/util.qc:594 qcsrc/menu/xonotic/util.qc:611 +msgid "Disable" +msgstr "Disabilita" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:30 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:77 qcsrc/menu/xonotic/util.qc:583 +msgid "Color:" +msgstr "Colore:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:35 qcsrc/menu/xonotic/util.qc:591 +msgid "Border size:" +msgstr "Dimensioni bordo:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:50 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:89 +msgid "Team color:" +msgstr "Colore team:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:58 qcsrc/menu/xonotic/util.qc:617 +msgid "Test team color in configure mode" +msgstr "Prova colore team in modalità configurazione" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:61 qcsrc/menu/xonotic/util.qc:620 +msgid "Padding:" +msgstr "Riempimento:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:68 +msgid "HUD Dock:" +msgstr "Sfondo dell'HUD:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:70 +msgid "DOCK^Disabled" +msgstr "DOCK^Disabilitato" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:71 +msgid "DOCK^Small" +msgstr "DOCK^Piccolo" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:72 +msgid "DOCK^Medium" +msgstr "DOCK^Medio" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:73 +msgid "DOCK^Large" +msgstr "DOCK^Largo" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:96 +msgid "Grid settings:" +msgstr "Impostazioni griglia:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:99 +msgid "Snap panels to grid" +msgstr "Incolla i pannelli alla griglia" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:102 +msgid "Grid size:" +msgstr "Dimensioni griglia:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:103 +msgid "X:" +msgstr "X:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:109 +msgid "Y:" +msgstr "Y:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:117 +msgid "Exit setup" +msgstr "Esci dal setup" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:4 +msgid "Multiplayer" +msgstr "Multiplayer" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:18 +msgid "Servers" +msgstr "Server" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:19 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:5 +msgid "Create" +msgstr "Crea" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:20 +msgid "Demos" +msgstr "Demo" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:5 +msgid "Player Setup" +msgstr "Setup giocatore" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:34 +msgid "Game type:" +msgstr "Tipo di gioco:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:46 +msgid "Match settings:" +msgstr "Impostazioni partita:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:49 +msgid "Time limit:" +msgstr "Limite di tempo:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:53 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:61 +msgid "Use map specified default" +msgstr "Usa le impostazioni di default della mappa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:56 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:155 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:156 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:157 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:161 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:162 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:163 +msgid "Point limit:" +msgstr "Limite di punteggio:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:64 +msgid "Player slots:" +msgstr "Posti per giocatori:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:67 +msgid "Number of bots:" +msgstr "Numero di bot:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:71 +msgid "Bot skill:" +msgstr "Abilità bot:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:74 +msgid "Botlike" +msgstr "\"Come un bot\"" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:75 +msgid "Beginner" +msgstr "Principiante" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:76 +msgid "You will win" +msgstr "Vincerai" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:77 +msgid "You can win" +msgstr "Puoi vincere" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:78 +msgid "You might win" +msgstr "Potresti vincere" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:79 +msgid "Advanced" +msgstr "Avanzato" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:80 +msgid "Expert" +msgstr "Esperto" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:81 +msgid "Pro" +msgstr "Pro" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:82 +msgid "Assassin" +msgstr "Assassino" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:83 +msgid "Unhuman" +msgstr "Inumano" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:84 +msgid "Godlike" +msgstr "\"Come un Dio\"" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:88 +msgid "Mutators..." +msgstr "Mutatori..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:97 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:57 +msgid "Advanced settings..." +msgstr "Impostazioni avanzate..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:104 +msgid "Map list:" +msgstr "Lista delle mappe:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:110 +msgid "Select all" +msgstr "Seleziona tutto" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:113 +msgid "Select none" +msgstr "Deseleziona tutto" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:119 +msgid "Start Multiplayer!" +msgstr "Inizia Multiplayer!" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:154 +msgid "Capture limit:" +msgstr "Limite catture:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:158 +msgid "Lives:" +msgstr "Vite:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:159 +msgid "Laps:" +msgstr "Giri:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:160 +msgid "Goals:" +msgstr "Goal:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:164 +msgid "Frag limit:" +msgstr "Limite di frag:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:6 +msgid "Advanced server settings" +msgstr "Impostazioni avanzate server" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:25 +msgid "Game settings:" +msgstr "Impostazioni gioco:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:28 +msgid "Allow spectating" +msgstr "Permetti spettatori" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:31 +msgid "Spawn shield:" +msgstr "Protezione nascita:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:36 +msgid "Game speed:" +msgstr "Velocità gioco:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:40 +msgid "Teamplay settings:" +msgstr "Impostazioni Teamplay:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:43 +msgid "Friendly fire scale:" +msgstr "Scala di fuoco amico:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:47 +msgid "Virtual friendly fire (effect only)" +msgstr "Penalità virtuale (solo effetto)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:50 +msgid "Friendly fire penalty:" +msgstr "Penalità fuoco amico:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:54 +msgid "Virtual penalty (effect only)" +msgstr "Penalità virtuale (solo effetto)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:57 +msgid "Teams:" +msgstr "Team:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:66 +msgid "Map voting:" +msgstr "Voto della mappa:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:68 +msgid "No voting" +msgstr "Nessun voto" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:69 +msgid "2 choices" +msgstr "2 scelte" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:70 +msgid "3 choices" +msgstr "3 scelte" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:71 +msgid "4 choices" +msgstr "4 scelte" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:72 +msgid "5 choices" +msgstr "5 scelte" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:73 +msgid "6 choices" +msgstr "6 scelte" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:74 +msgid "7 choices" +msgstr "7 scelte" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:75 +msgid "8 choices" +msgstr "8 scelte" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:76 +msgid "9 choices" +msgstr "9 scelte" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:79 +msgid "Simple majority wins vcall" +msgstr "La semplice maggioranza vince il vcall" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:5 +msgid "Map Information" +msgstr "Informazioni mappa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "Full item placement" +msgstr "Posizionamento oggetti completo" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "MinstaGib only" +msgstr "Solo MinstaGib" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:78 +msgid "Title:" +msgstr "Titolo:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:84 +msgid "Author:" +msgstr "Autore:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:90 +msgid "Features:" +msgstr "Caratteristiche:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:95 +msgid "Game types:" +msgstr "Tipi di gioco:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:118 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:314 +msgid "Close" +msgstr "Chiudi" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:121 +msgid "MAP^Play" +msgstr "Gioca" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:7 +msgid "Mutators" +msgstr "Mutatori" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:33 +msgid "All Weapons Arena" +msgstr "Arena con tutte le armi" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:35 +msgid "Most Weapons Arena" +msgstr "Arena con la maggior parte delle armi" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:56 +#, c-format +msgid "%s Arena" +msgstr "Arena con %s" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:68 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:167 +msgid "Dodging" +msgstr "Schivamento" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:70 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:250 +msgid "MinstaGib" +msgstr "MinstaGib" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:253 +msgid "NIX" +msgstr "NIX" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:74 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:205 +msgid "Rocket Flying" +msgstr "Volando coi razzi" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:78 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:264 +msgid "No start weapons" +msgstr "Senza armi all'inizio" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:80 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:189 +msgid "Low gravity" +msgstr "Bassa gravità" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:170 +msgid "Cloaked" +msgstr "Invisibile" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:84 +msgid "Hook" +msgstr "Hook" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:86 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:173 +msgid "Midair" +msgstr "A mezz'aria" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:88 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:176 +msgid "Vampire" +msgstr "Vampiro" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:90 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:208 +msgid "Piñata" +msgstr "Piñata" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:92 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:211 +msgid "Weapons stay" +msgstr "Armi rimangono" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:94 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:180 +msgid "Blood loss" +msgstr "Perdita di sangue" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:96 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:202 +msgid "Jet pack" +msgstr "Jet pack" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:98 +msgid "MUT^None" +msgstr "MUT^Nessuno" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:164 +msgid "Gameplay mutators:" +msgstr "Mutatori di gioco:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:196 +msgid "Weapon & item mutators:" +msgstr "Mutatori di armi ed oggetti:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:199 +msgid "Grappling hook" +msgstr "Grappling hook" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:215 +msgid "Weapon arenas:" +msgstr "Arene di armi:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:218 +msgid "Regular (no arena)" +msgstr "Regolare (no arena)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:239 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:256 +msgid "with laser" +msgstr "con laser" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:247 +msgid "Special arenas:" +msgstr "Arene speciali:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:260 +msgid "Most weapons" +msgstr "Maggior parte delle armi" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:4 +msgid "Demo" +msgstr "Demo" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:28 +msgid "Record demos while playing" +msgstr "Registra demo durante le partite" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:32 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:28 +msgid "Filter:" +msgstr "Filtro:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:29 +#: qcsrc/menu/xonotic/dialog_settings_input.c:41 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:24 +msgid "Clear" +msgstr "Pulisci" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:43 +msgid "Timedemo" +msgstr "Timedemo" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:46 +msgid "DEMO^Play" +msgstr "Riproduci" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:4 +msgid "Join" +msgstr "Entra" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:36 +msgid "SRVS^Empty" +msgstr "SRVS^Vuoti" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:40 +msgid "SRVS^Full" +msgstr "SRVS^Pieni" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:44 +msgid "Pause" +msgstr "In pausa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:56 +msgid "Address:" +msgstr "Indirizzo:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:67 +msgid "Info..." +msgstr "Info..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:317 +msgid "Join!" +msgstr "Entra!" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:5 +msgid "Server Information" +msgstr "Informazioni del server" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:115 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:116 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:183 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:189 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:199 +msgid "N/A" +msgstr "N/D" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:158 +#, c-format +msgid "%d/%d, %d free player slots" +msgstr "%d/%d, %d slot liberi" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +#, c-format +msgid "%d modified settings" +msgstr "%d impostazioni modificate" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +msgid "Official settings" +msgstr "Impostazioni ufficiali" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:197 +msgid "N/A (can't connect)" +msgstr "N/D (impossibile connettersi)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:205 +msgid "not supported (can't connect)" +msgstr "non supportato (impossibile connettersi)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:207 +msgid "not supported (won't encrypt)" +msgstr "non supportato (non criptato)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:211 +msgid "supported (will encrypt)" +msgstr "supportato (criptato)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:213 +msgid "supported (won't encrypt)" +msgstr "supportato (non criptato)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:217 +msgid "requested (will encrypt)" +msgstr "richiesto (criptato)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:219 +msgid "requested (won't encrypt)" +msgstr "richiesto (non criptato)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:223 +msgid "required (can't connect)" +msgstr "richiesto (impossibile connettersi)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:225 +msgid "required (will encrypt)" +msgstr "richiesto (criptato)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:246 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:269 +msgid "Players:" +msgstr "Giocatori:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:254 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:38 +msgid "Type:" +msgstr "Tipo:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:259 +msgid "Map:" +msgstr "Mappa:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:264 +msgid "Gameplay:" +msgstr "Gameplay:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:274 +msgid "Bots:" +msgstr "Bot:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:279 +msgid "Mod:" +msgstr "Mod:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:284 +msgid "Version:" +msgstr "Versione:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:289 +msgid "Ping:" +msgstr "Ping:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:295 +msgid "CA:" +msgstr "CA:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:301 +msgid "Key:" +msgstr "Chiave:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:307 +msgid "Encryption:" +msgstr "Crittografia:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:63 +msgid "Model:" +msgstr "Modello:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:88 +msgid "Field of view:" +msgstr "Campo di vista:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:92 +msgid "View bobbing:" +msgstr "Ondeggiamento:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:96 +msgid "Zoom factor:" +msgstr "Fattore zoom:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:100 +msgid "Zoom speed:" +msgstr "Velocità zoom:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:103 +msgid "Weapon settings..." +msgstr "Impostazioni arma..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:110 +msgid "Crosshair:" +msgstr "Mirino:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:111 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:139 +msgid "Per weapon" +msgstr "Per singola arma" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:130 +msgid "Crosshair size:" +msgstr "Dimensioni mirino:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:134 +msgid "Crosshair alpha:" +msgstr "Opacità mirino:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:138 +msgid "Crosshair color:" +msgstr "Colore mirino:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:140 +msgid "By health" +msgstr "In base alla vita" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:143 +msgid "Custom" +msgstr "Personalizzato" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:148 +msgid "Enable center dot" +msgstr "Abilita puntino al centro" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:151 +msgid "Size:" +msgstr "Dimensioni:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:158 +msgid "Hit test:" +msgstr "Test colpi:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:159 +msgid "HTST^None" +msgstr "HTST^Nessuno" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:160 +msgid "TrueAim" +msgstr "TrueAim" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:161 +msgid "Enemies" +msgstr "Nemici" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:164 +msgid "Waypoints setup..." +msgstr "Setup dei waypoint..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:169 +msgid "Enter HUD editor" +msgstr "Apri HUD editor" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:174 +msgid "Force models:" +msgstr "Forza modelli:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:175 +msgid "MDL^None" +msgstr "MDL^Nessuno" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:176 +msgid "MDL^Custom" +msgstr "MDL^Personalizzato" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:177 +msgid "MDL^All" +msgstr "MDL^Tutti" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:180 +msgid "Disable gore effects" +msgstr "Disabilita effetti sangue" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:182 +msgid "Gibs:" +msgstr "Gib:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:184 +msgid "GIBS^None" +msgstr "GIBS^Nessuno" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:185 +msgid "GIBS^Few" +msgstr "GIBS^Pochi" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:186 +msgid "GIBS^Many" +msgstr "GIBS^Molti" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:187 +msgid "GIBS^Lots" +msgstr "GIBS^Parecchi" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:191 +msgid "Damage splash:" +msgstr "Schizzo del danno:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:195 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:173 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:194 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:30 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:41 +#: qcsrc/menu/xonotic/dialog_settings_video.c:109 +msgid "Apply immediately" +msgstr "Applica immediatamente" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:5 +msgid "Waypoints" +msgstr "Waypoint" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:23 +msgid "Show base waypoints" +msgstr "Mostra i waypoint della base" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:25 +msgid "Waypoint scale:" +msgstr "Grandezza dei waypoint:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:29 +msgid "Waypoint alpha:" +msgstr "Opacità dei waypoint" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:34 +msgid "Show names:" +msgstr "Mostra nomi:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:37 +msgid "Teammates" +msgstr "Compagni del team" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:38 +msgid "All players" +msgstr "Tutti i giocatori" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:6 +msgid "Weapon settings" +msgstr "Impostazioni arma" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:29 +msgid "Weapon priority list:" +msgstr "Lista priorità armi:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:34 +msgid "Up" +msgstr "Su" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:37 +msgid "Down" +msgstr "Giù" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:41 +msgid "Use priority list for weapon cycling" +msgstr "Usa la lista di priorità per ciclare le armi" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:43 +msgid "Auto switch weapons on pickup" +msgstr "Cambia automaticamente armi dopo raccolta" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:45 +msgid "Draw 1st person weapon model" +msgstr "Mostra modello arma in 1ª persona" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:55 +msgid "Flip view horizontally" +msgstr "Capovolgi la vista orizzontalmente" + +#: qcsrc/menu/xonotic/dialog_news.c:4 +msgid "News" +msgstr "Notizie" + +#: qcsrc/menu/xonotic/dialog_news.c:18 +msgid "http://www.xonotic.org/team/blog/" +msgstr "http://www.xonotic.org/team/blog/" + +#: qcsrc/menu/xonotic/dialog_quit.c:4 +msgid "Quit" +msgstr "Esci" + +#: qcsrc/menu/xonotic/dialog_quit.c:17 +msgid "Are you sure you want to quit?" +msgstr "Sei sicuro di voler uscire?" + +#: qcsrc/menu/xonotic/dialog_quit.c:20 +msgid "Yes" +msgstr "Sì" + +#: qcsrc/menu/xonotic/dialog_quit.c:21 +msgid "No" +msgstr "No" + +#: qcsrc/menu/xonotic/dialog_settings.c:4 +msgid "Settings" +msgstr "Impostazioni" + +#: qcsrc/menu/xonotic/dialog_settings.c:18 +#: qcsrc/menu/xonotic/dialog_settings_input.c:4 +msgid "Input" +msgstr "Comandi" + +#: qcsrc/menu/xonotic/dialog_settings.c:19 +#: qcsrc/menu/xonotic/dialog_settings_video.c:4 +msgid "Video" +msgstr "Video" + +#: qcsrc/menu/xonotic/dialog_settings.c:20 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:4 +msgid "Effects" +msgstr "Effetti" + +#: qcsrc/menu/xonotic/dialog_settings.c:21 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:4 +msgid "Audio" +msgstr "Audio" + +#: qcsrc/menu/xonotic/dialog_settings.c:22 +#: qcsrc/menu/xonotic/dialog_settings_network.c:4 +msgid "Network" +msgstr "Rete" + +#: qcsrc/menu/xonotic/dialog_settings.c:23 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:4 +msgid "Misc" +msgstr "Altro" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:27 +msgid "Master:" +msgstr "Master:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:33 +msgid "Music:" +msgstr "Musica:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:41 +msgid "VOL^Ambient:" +msgstr "VOL^Ambiente:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:48 +msgid "Info:" +msgstr "Info:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:55 +msgid "Items:" +msgstr "Oggetti:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:62 +msgid "Pain:" +msgstr "Dolore:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:69 +msgid "Player:" +msgstr "Giocatore:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:76 +msgid "Shots:" +msgstr "Spari:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:83 +msgid "Voice:" +msgstr "Voce:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:91 +msgid "Weapons:" +msgstr "Armi:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:98 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:156 +msgid "Frequency:" +msgstr "Frequenza:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:100 +msgid "8 kHz" +msgstr "8 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:101 +msgid "11.025 kHz" +msgstr "11.025 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:102 +msgid "16 kHz" +msgstr "16 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:103 +msgid "22.05 kHz" +msgstr "22.05 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:104 +msgid "24 kHz" +msgstr "24 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:105 +msgid "32 kHz" +msgstr "32 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:106 +msgid "44.1 kHz" +msgstr "44.1 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:107 +msgid "48 kHz" +msgstr "48 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:110 +msgid "Channels:" +msgstr "Canali:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:112 +msgid "Mono" +msgstr "Mono" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:113 +msgid "Stereo" +msgstr "Stereo" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:114 +msgid "2.1" +msgstr "2.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:115 +msgid "4" +msgstr "4" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:116 +msgid "5" +msgstr "5" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:117 +msgid "5.1" +msgstr "5.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:118 +msgid "6.1" +msgstr "6.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:119 +msgid "7.1" +msgstr "7.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:123 +msgid "Swap Stereo" +msgstr "Scambia canali stereo" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:127 +msgid "Headphone friendly mode" +msgstr "Modalità cuffie" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:131 +msgid "Spatial voices:" +msgstr "Voci spaziali:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:132 +msgid "VOCS^None" +msgstr "VOCS^Nessuna" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:133 +msgid "VOCS^Taunts" +msgstr "VOCS^Insulti" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:134 +msgid "VOCS^All" +msgstr "VOCS^Tutte" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:137 +msgid "Taunt range:" +msgstr "Range di insulti:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:140 +msgid "RNG^Very short" +msgstr "RNG^Molto ristretto" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:141 +msgid "RNG^Short" +msgstr "RNG^Ristretto" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:142 +msgid "RNG^Normal" +msgstr "RNG^Normale" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:143 +msgid "RNG^Long" +msgstr "RNG^Lungo" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:144 +msgid "RNG^Full" +msgstr "RNG^Pieno" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:151 +msgid "Automatic taunts" +msgstr "Insulti automatici" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:160 +msgid "Time warning:" +msgstr "Avvertimento di tempo:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:162 +msgid "WRN^None" +msgstr "WRN^Nessuno" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:163 +msgid "1 minute" +msgstr "1 minuto" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:164 +msgid "5 minutes" +msgstr "5 minuti" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:165 +msgid "WRN^Both" +msgstr "WNR^Entrambi" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:168 +msgid "Hit indicator" +msgstr "Indicatore di colpo" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:170 +msgid "Menu sounds" +msgstr "Suoni del menu" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:38 +msgid "Quality preset:" +msgstr "Preset qualità:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:41 +msgid "PRE^OMG!" +msgstr "PRE^Oh mio dio!" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:42 +msgid "PRE^Low" +msgstr "PRE^Bassa" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:43 +msgid "PRE^Medium" +msgstr "PRE^Media" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:44 +msgid "PRE^Normal" +msgstr "PRE^Normale" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:45 +msgid "PRE^High" +msgstr "PRE^Alta" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:46 +msgid "PRE^Ultra" +msgstr "PRE^Ultra" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:48 +msgid "PRE^Ultimate" +msgstr "PRE^Massima" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:52 +msgid "Geometry detail:" +msgstr "Dettagli geometrici:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:54 +msgid "DET^Lowest" +msgstr "DET^Molto bassi" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:55 +msgid "DET^Low" +msgstr "DET^Bassi" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:56 +msgid "DET^Normal" +msgstr "DET^Normali" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:57 +msgid "DET^Good" +msgstr "DET^Buoni" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:58 +msgid "DET^Best" +msgstr "DET^Ottimi" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:59 +msgid "DET^Insane" +msgstr "DET^Bestiali" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:62 +msgid "Antialiasing:" +msgstr "Antialiasing:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:64 +msgid "AA^Disabled" +msgstr "AA^Disabilitato" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:65 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:103 +msgid "2x" +msgstr "2x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:66 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:104 +msgid "4x" +msgstr "4x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:70 +msgid "Texture resolution:" +msgstr "Risoluzione texture:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:73 +msgid "RES^Leet" +msgstr "RES^Leet" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:74 +msgid "RES^Lowest" +msgstr "RES^Molto bassa" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:75 +msgid "RES^Low" +msgstr "RES^Bassa" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:76 +msgid "RES^Normal" +msgstr "RES^Normale" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:77 +msgid "RES^Good" +msgstr "RES^Buona" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:78 +msgid "RES^Best" +msgstr "RES^Ottima" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:91 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:94 +msgid "Avoid lossy texture compression" +msgstr "Evita compressione texture con perdita" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:100 +msgid "Anisotropy:" +msgstr "Anisotropia:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:102 +msgid "ANISO^Disabled" +msgstr "ANISO^Disabilitato" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:105 +msgid "8x" +msgstr "8x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:106 +msgid "16x" +msgstr "16x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:110 +msgid "Particle quality:" +msgstr "Qualità particelle:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:113 +msgid "Particle distance:" +msgstr "Distanza particelle:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:117 +msgid "Decals" +msgstr "Decal" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:118 +msgid "Decals on models" +msgstr "Decal sui modelli" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:122 +msgid "Distance:" +msgstr "Distanza:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:128 +msgid "Time:" +msgstr "Tempo:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:134 +msgid "Use lightmaps" +msgstr "Usa mappe di luce" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:135 +msgid "Deluxe mapping" +msgstr "Mappaggio Deluxe" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:137 +msgid "Gloss" +msgstr "Lucentezza" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:140 +msgid "Offset mapping" +msgstr "Mappaggio in offset" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:142 +msgid "Relief mapping" +msgstr "Mappaggio in rilievo" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:145 +msgid "Reflections:" +msgstr "Riflessioni:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:148 +msgid "Blurred" +msgstr "Sfocate" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:149 +msgid "REFL^Good" +msgstr "REFL^Buone" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:150 +msgid "Sharp" +msgstr "Nitide" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:155 +msgid "Show surfaces" +msgstr "Mostra superfici" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:157 +msgid "No dynamic lighting" +msgstr "Nessuna illuminazione dinamica" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:159 +msgid "Flash blend approximation" +msgstr "Approssimazione Flash blend" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:161 +msgid "Realtime dynamic lighting" +msgstr "Illuminazione dinamica in tempo reale" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:162 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:166 +msgid "Shadows" +msgstr "Ombre" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:165 +msgid "Realtime world lighting" +msgstr "Illuminazione globale in tempo reale" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:170 +msgid "Use normal maps" +msgstr "Usa mappe normali" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:172 +msgid "Soft shadows" +msgstr "Ombre morbide" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:175 +msgid "Coronas" +msgstr "Corone" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:176 +msgid "Use Occlusion Queries" +msgstr "Usa le Occlusion Queries" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:178 +msgid "Bloom" +msgstr "Bloom" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:180 +msgid "High Dynamic Range (HDR)" +msgstr "High Dynamic Range (HDR)" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:184 +msgid "Motion blur:" +msgstr "Sfocatura movimento:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:189 +msgid "Blur and sharpen postprocessing" +msgstr "Postprocessa per sfocatura e nitidezza" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:26 +msgid "Key bindings:" +msgstr "Associazione tasti (bind):" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:31 +msgid "Change key..." +msgstr "Cambia tasto..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:35 +msgid "Edit..." +msgstr "Modifica..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:46 +msgid "Sensitivity:" +msgstr "Sensibilità:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:51 +msgid "UI mouse speed:" +msgstr "Velocità UI mouse:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:55 +msgid "Mouse filter" +msgstr "Filtro mouse" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:57 +msgid "Invert mouse" +msgstr "Inverti mouse" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:60 +#: qcsrc/menu/xonotic/dialog_settings_input.c:62 +msgid "Use joystick input" +msgstr "Usa joystick" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:65 +#: qcsrc/menu/xonotic/dialog_settings_input.c:67 +msgid "Turn off OS mouse acceleration" +msgstr "Disattiva l'accelerazione mouse dell'OS" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:69 +msgid "\"enter console\" also closes" +msgstr "\"apri console\" chiude anche" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:5 +msgid "User defined key bind" +msgstr "Tasti \"bind\" definiti dall'utente" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:42 +msgid "Command when pressed:" +msgstr "Comando quando premuto:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:45 +msgid "Command when released:" +msgstr "Comando quando rilasciato:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:48 +msgid "Save" +msgstr "Salva" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:51 +msgid "Cancel" +msgstr "Annulla" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:26 +msgid "Menu skins:" +msgstr "Temi del menu:" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:47 +msgid "Show current time" +msgstr "Mostra orario corrente" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:49 +msgid "Show current date" +msgstr "Mostra data corrente" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:51 +msgid "Show frames per second" +msgstr "Mostra fotogrammi al secondo" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:53 +msgid "Minimize input latency" +msgstr "Minimizza latenza in entrata" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:5 +msgid "Advanced settings" +msgstr "Impostazioni avanzate" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:23 +msgid "Cvar filter:" +msgstr "Filtro delle cvar:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:34 +msgid "Setting:" +msgstr "Impostazioni:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:42 +msgid "Value:" +msgstr "Valore:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:56 +msgid "Description:" +msgstr "Descrizione:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:26 +msgid "Client-side movement prediction" +msgstr "Predizione del movimento lato client" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:30 +msgid "Show netgraph" +msgstr "Mostra grafico di rete" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:33 +msgid "Network speed:" +msgstr "Velocità rete:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:35 +msgid "56k" +msgstr "56k" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:36 +msgid "ISDN" +msgstr "ISDN" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:37 +msgid "Slow ADSL" +msgstr "ADSL lenta" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:38 +msgid "Fast ADSL" +msgstr "ADSL veloce" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:39 +msgid "Broadband" +msgstr "Banda larga" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:42 +msgid "Input packets/s:" +msgstr "Pacchetti/s in entrata:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:46 +msgid "HTTP downloads:" +msgstr "Download via HTTP:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:49 +msgid "Downloads:" +msgstr "N° di download:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:53 +msgid "Speed (kB/s):" +msgstr "Velocità (kB/s):" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:57 +msgid "Client UDP port:" +msgstr "Porta UDP del client:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:26 +msgid "Resolution:" +msgstr "Risoluzione:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:29 +msgid "Font/UI size:" +msgstr "Dimensioni caratteri:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:31 +msgid "SZ^Unreadable" +msgstr "SZ^Illeggibile" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:32 +msgid "SZ^Tiny" +msgstr "SZ^Minuscolo" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:33 +msgid "SZ^Little" +msgstr "SZ^Molto piccolo" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:34 +msgid "SZ^Small" +msgstr "SZ^Piccolo" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:35 +msgid "SZ^Medium" +msgstr "SZ^Medio" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:36 +msgid "SZ^Large" +msgstr "SZ^Largo" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:37 +msgid "SZ^Huge" +msgstr "SZ^Enorme" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:38 +msgid "SZ^Gigantic" +msgstr "SZ^Gigante" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:39 +msgid "SZ^Colossal" +msgstr "SZ^Colossale" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:42 +msgid "Color depth:" +msgstr "Profondità colore:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:45 +msgid "Full screen" +msgstr "Schermo intero" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:46 +msgid "Vertical Synchronization" +msgstr "Sincronizzazione verticale" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:49 +msgid "Use OpenGL 2.0 shaders (GLSL)" +msgstr "Usa gli shader OpenGL 2.0 (GLSL)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:52 +msgid "Use GLSL to handle color control" +msgstr "Usa GLSL per gestire il controllo del colore" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:56 +msgid "Vertex Buffer Objects (VBOs)" +msgstr "Vertex Buffer Objects (VBOs)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:59 +msgid "VBO^Off" +msgstr "VBO^Off" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:60 +msgid "Vertices, some Tris (compatible)" +msgstr "Vertici, alcuni Triangoli (compatibile)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:63 +msgid "Vertices" +msgstr "Vertici" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:64 +msgid "Vertices and Triangles" +msgstr "Vertici e Triangoli" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:67 +msgid "Depth first:" +msgstr "Profondità prima:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:69 +msgid "DF^Disabled" +msgstr "DF^Disabilitata" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:70 +msgid "DF^World" +msgstr "DF^Globale" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:71 +msgid "DF^All" +msgstr "DF^Tutto" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:75 +msgid "Disable multithreaded OpenGL" +msgstr "Disabilita il multithreading OpenGL" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:77 +msgid "Wait for GPU to finish each frame" +msgstr "Attendi che la GPU finisca di elaborare ogni frame" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:80 +msgid "Brightness:" +msgstr "Luminosità:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:83 +msgid "Contrast:" +msgstr "Contrasto:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:86 +msgid "Gamma:" +msgstr "Gamma:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:91 +msgid "Contrast boost:" +msgstr "Aumenta contrasto:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:96 +msgid "Saturation:" +msgstr "Saturazione:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:102 +msgid "LIT^Ambient:" +msgstr "LIT^Ambiente:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:105 +msgid "Intensity:" +msgstr "Intensità:" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:4 +msgid "Singleplayer" +msgstr "Giocatore singolo" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:127 +msgid "Instant action! (random map with bots)" +msgstr "Inizia ora! (mappa casuale con bot)" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:148 +msgid "Start Singleplayer!" +msgstr "Inizia modalità Giocatore Singolo!" + +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:4 +msgid "Winner" +msgstr "Vincitore" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:5 +msgid "Team Selection" +msgstr "Selezione team" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:41 +msgid "join 'best' team (auto-select)" +msgstr "entra nel 'miglior' team (auto-selezione)" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:45 +msgid "red" +msgstr "rosso" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:46 +msgid "blue" +msgstr "blu" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:47 +msgid "yellow" +msgstr "giallo" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:48 +msgid "pink" +msgstr "rosa" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:51 +msgid "spectate" +msgstr "spettatore" + +#: qcsrc/menu/xonotic/mainwindow.c:35 qcsrc/menu/xonotic/mainwindow.c:38 +msgid "Do not press this button again!" +msgstr "Non premere questo tasto di nuovo!" + +#: qcsrc/menu/xonotic/maplist.c:278 +msgid "" +"Huh? Can't play this (m is NULL). Refiltering so this won't happen again.\n" +msgstr "" +"Huh? Can't play this (m is NULL). Refiltering so this won't happen again.\n" + +#: qcsrc/menu/xonotic/maplist.c:286 +#, c-format +msgid "%s's Xonotic Server" +msgstr "Server Xonotic di %s" + +#: qcsrc/menu/xonotic/maplist.c:291 +msgid "" +"Huh? Can't play this (invalid game type). Refiltering so this won't happen " +"again.\n" +msgstr "" +"Huh? Can't play this (invalid game type). Refiltering so this won't happen " +"again.\n" + +#: qcsrc/menu/xonotic/playermodel.c:174 +msgid "<no model found>" +msgstr "<nessun modello trovato>" + +#: qcsrc/menu/xonotic/serverlist.c:185 +msgid "Remove" +msgstr "Rimuovi" + +#: qcsrc/menu/xonotic/serverlist.c:187 +msgid "Bookmark" +msgstr "Aggiungi tra i preferiti" + +#: qcsrc/menu/xonotic/serverlist.c:527 +msgid "Ping" +msgstr "Ping" + +#: qcsrc/menu/xonotic/serverlist.c:528 +msgid "Host name" +msgstr "Nome dell'host" + +#: qcsrc/menu/xonotic/serverlist.c:529 +msgid "Map" +msgstr "Mappa" + +#: qcsrc/menu/xonotic/serverlist.c:530 +msgid "Type" +msgstr "Tipo" + +#: qcsrc/menu/xonotic/serverlist.c:531 +msgid "Players" +msgstr "Giocatori" + +#: qcsrc/menu/xonotic/skinlist.c:105 +msgid "<TITLE>" +msgstr "<TITOLO>" + +#: qcsrc/menu/xonotic/skinlist.c:106 +msgid "<AUTHOR>" +msgstr "<AUTORE>" + +#: qcsrc/menu/xonotic/slider_decibels.c:50 +msgid "VOL^OFF" +msgstr "VOL^OFF" + +#: qcsrc/menu/xonotic/slider_decibels.c:52 +msgid "VOL^MAX" +msgstr "VOL^MAX" + +#: qcsrc/menu/xonotic/slider_decibels.c:53 +#, c-format +msgid "%s dB" +msgstr "%s dB" + +#: qcsrc/menu/xonotic/slider_resolution.c:65 +#, c-format +msgid "%dx%d" +msgstr "%dx%d" + +#: qcsrc/menu/xonotic/util.qc:270 +#, c-format +msgid "Received HTTP request data for an invalid id %d.\n" +msgstr "Ricevuta richiesta HTTP per un invalido id %d.\n" + +#: qcsrc/menu/xonotic/util.qc:285 +#, c-format +msgid "error receiving update notification: status is %d\n" +msgstr "" +"errore durante la notifica d'aggiornamento: lo stato è impostato su %d\n" + +#: qcsrc/menu/xonotic/util.qc:290 +msgid "error: received HTML instead of an update notification\n" +msgstr "errore: ricevuto HTML invece di una notifica d'aggiornamento\n" + +#: qcsrc/menu/xonotic/util.qc:295 +msgid "error: received carriage returns from update notification server\n" +msgstr "error: received carriage returns from update notification server\n" + +#: qcsrc/menu/xonotic/util.qc:316 +#, c-format +msgid "" +"Update can be downloaded at:\n" +"%s\n" +msgstr "" +"L'aggiornamento può essere scaricato da:\n" +"%s\n" + +#: qcsrc/menu/xonotic/util.qc:337 +msgid "Autogenerating mapinfo for newly added maps..." +msgstr "Autogenerando le mapinfo per le nuove mappe..." + +#: qcsrc/menu/xonotic/util.qc:367 +#, c-format +msgid "^1%s TEST BUILD" +msgstr "^1%s TEST BUILD" + +#: qcsrc/menu/xonotic/util.qc:432 +#, c-format +msgid "Update to %s now!" +msgstr "Aggiorna a %s ora!" + +#: qcsrc/menu/xonotic/util.qc:501 +msgid "" +"^1ERROR: Texture compression is required but not supported.\n" +"^1Expect visual problems.\n" +msgstr "" +"^1ERRORE: La compressione texture è richiesta ma non supportata.\n" +"^1Previsti problemi visuali.\n" + +#: qcsrc/menu/xonotic/util.qc:523 +msgid "Arena" +msgstr "Arena" + +#: qcsrc/menu/xonotic/util.qc:524 +msgid "Assault" +msgstr "Assalto" + +#: qcsrc/menu/xonotic/util.qc:525 +msgid "Capture The Flag" +msgstr "Capture The Flag" + +#: qcsrc/menu/xonotic/util.qc:526 +msgid "Clan Arena" +msgstr "Clan Arena" + +#: qcsrc/menu/xonotic/util.qc:527 +msgid "Deathmatch" +msgstr "Deathmatch" + +#: qcsrc/menu/xonotic/util.qc:528 +msgid "Domination" +msgstr "Dominazione" + +#: qcsrc/menu/xonotic/util.qc:529 +msgid "Freeze Tag" +msgstr "Freeze Tag" + +#: qcsrc/menu/xonotic/util.qc:530 +msgid "Keepaway" +msgstr "Keepaway" + +#: qcsrc/menu/xonotic/util.qc:531 +msgid "Key Hunt" +msgstr "Key Hunt" + +#: qcsrc/menu/xonotic/util.qc:532 +msgid "Last Man Standing" +msgstr "Last Man Standing" + +#: qcsrc/menu/xonotic/util.qc:533 +msgid "Nexball" +msgstr "Nexball" + +#: qcsrc/menu/xonotic/util.qc:534 +msgid "Onslaught" +msgstr "Onslaught" + +#: qcsrc/menu/xonotic/util.qc:535 +msgid "Race" +msgstr "Corsa" + +#: qcsrc/menu/xonotic/util.qc:536 +msgid "Race CTS" +msgstr "Corsa CTS" + +#: qcsrc/menu/xonotic/util.qc:537 +msgid "Runematch" +msgstr "Runematch" + +#: qcsrc/menu/xonotic/util.qc:538 +msgid "Team Deathmatch" +msgstr "Team Deathmatch" + +#: qcsrc/menu/xonotic/util.qc:557 +#, c-format +msgid "@!#%'n Tuba Throwing" +msgstr "@!#%'n Tuba Throwing" + +#: qcsrc/menu/xonotic/util.qc:577 qcsrc/menu/xonotic/util.qc:593 +#: qcsrc/menu/xonotic/util.qc:602 qcsrc/menu/xonotic/util.qc:610 +#: qcsrc/menu/xonotic/util.qc:622 +msgid "Default" +msgstr "Predefinito" + +#: qcsrc/menu/xonotic/util.qc:588 +msgid "Use default" +msgstr "Usa predefinito" + +#: qcsrc/menu/xonotic/util.qc:608 +msgid "Team Color:" +msgstr "Colore Team:" + +#: qcsrc/menu/xonotic/util.qh:47 +msgid "Enable panel" +msgstr "Abilita pannello" + +#: qcsrc/server/w_crylink.qc:2 +msgid "Crylink" +msgstr "Crylink" + +#: qcsrc/server/w_crylink.qc:666 +#, c-format +msgid "%s succeeded at self-destructing themself with the Crylink" +msgstr "%s è riuscito ad autodistruggersi col Crylink" + +#: qcsrc/server/w_crylink.qc:671 +#, c-format +msgid "%s could not hide from %s's Crylink" +msgstr "%s non s'è potuto nascondere dal Crylink di %s" + +#: qcsrc/server/w_crylink.qc:673 +#, c-format +msgid "%s was too close to %s's Crylink" +msgstr "%s era troppo vicino al Crylink di %s" + +#: qcsrc/server/w_crylink.qc:675 +#, c-format +msgid "%s took a close look at %s's Crylink" +msgstr "%s ha visto da vicino il Crylink di %s" + +#: qcsrc/server/w_electro.qc:2 +msgid "Electro" +msgstr "Electro" + +#: qcsrc/server/w_electro.qc:574 +#, c-format +msgid "%s could not remember where they put plasma" +msgstr "%s non s'è ricordato dove aveva messo il plasma" + +#: qcsrc/server/w_electro.qc:576 +#, c-format +msgid "%s played with plasma" +msgstr "%s ha giocato col plasma" + +#: qcsrc/server/w_electro.qc:583 +#, c-format +msgid "%s just noticed %s's blue ball" +msgstr "%s ha appena notato la palla blu di %s" + +#: qcsrc/server/w_electro.qc:585 +#, c-format +msgid "%s got in touch with %s's blue ball" +msgstr "%s è entrato in contatto con la palla blu di %s" + +#: qcsrc/server/w_electro.qc:590 +#, c-format +msgid "%s felt the electrifying air of %s's combo" +msgstr "%s ha sentito l'aria elettrificata della combo di %s" + +#: qcsrc/server/w_electro.qc:592 +#, c-format +msgid "%s got too close to %s's blue beam" +msgstr "%s s'è avvicinato troppo al raggio blu di %s" + +#: qcsrc/server/w_electro.qc:594 +#, c-format +msgid "%s was blasted by %s's blue beam" +msgstr "%s è stato fatto saltare in aria dal raggio blu di %s" + +#: qcsrc/server/w_fireball.qc:2 +msgid "Fireball" +msgstr "Fireball" + +#: qcsrc/server/w_fireball.qc:417 +#, c-format +msgid "%s forgot about some firemine" +msgstr "%s s'è dimenticato di alcune mine infuocate" + +#: qcsrc/server/w_fireball.qc:419 qcsrc/server/w_hlac.qc:240 +#, c-format +msgid "%s should have used a smaller gun" +msgstr "%s avrebbe dovuto usare un'arma più piccola" + +#: qcsrc/server/w_fireball.qc:426 +#, c-format +msgid "%s tried to catch %s's firemine" +msgstr "%s ha provato a catturare la mina infuocata di %s" + +#: qcsrc/server/w_fireball.qc:428 +#, c-format +msgid "%s fatefully ignored %s's firemine" +msgstr "%s ha fatalmente ignorato la mina infuocata di %s" + +#: qcsrc/server/w_fireball.qc:435 +#, c-format +msgid "%s could not hide from %s's fireball" +msgstr "%s non è riuscito a nascondersi dalla fireball di %s" + +#: qcsrc/server/w_fireball.qc:437 +#, c-format +msgid "%s saw the pretty lights of %s's fireball" +msgstr "%s ha visto le belle luci della fireball di %s" + +#: qcsrc/server/w_fireball.qc:440 +#, c-format +msgid "%s got too close to %s's fireball" +msgstr "%s s'è avvicinato troppo alla fireball di %s" + +#: qcsrc/server/w_fireball.qc:442 +#, c-format +msgid "%s tasted %s's fireball" +msgstr "%s ha assaggiato la fireball di %s" + +#: qcsrc/server/w_grenadelauncher.qc:2 +msgid "Mortar" +msgstr "Mortar" + +#: qcsrc/server/w_grenadelauncher.qc:383 +#, c-format +msgid "%s tried out his own grenade" +msgstr "%s ha provato da solo la propria granata" + +#: qcsrc/server/w_grenadelauncher.qc:385 +#, c-format +msgid "%s detonated" +msgstr "%s è detonato" + +#: qcsrc/server/w_grenadelauncher.qc:391 +#, c-format +msgid "%s didn't see %s's grenade" +msgstr "%s non ha visto la granata di %s" + +#: qcsrc/server/w_grenadelauncher.qc:393 +#, c-format +msgid "%s almost dodged %s's grenade" +msgstr "%s ha quasi schivato la granata di %s" + +#: qcsrc/server/w_grenadelauncher.qc:395 +#, c-format +msgid "%s ate %s's grenade" +msgstr "%s ha mangiato la granata di %s" + +#: qcsrc/server/w_hagar.qc:2 +msgid "Hagar" +msgstr "Hagar" + +#: qcsrc/server/w_hagar.qc:395 qcsrc/server/w_seeker.qc:655 +#, c-format +msgid "%s played with tiny rockets" +msgstr "%s ha giocato con piccoli razzi" + +#: qcsrc/server/w_hagar.qc:399 +#, c-format +msgid "%s hoped %s's missiles wouldn't bounce" +msgstr "%s ha sperato che i missili di %s non rimbalzassero" + +#: qcsrc/server/w_hagar.qc:401 qcsrc/server/w_seeker.qc:661 +#, c-format +msgid "%s was pummeled by %s" +msgstr "%s è stato preso a pugni da %s" + +#: qcsrc/server/w_hlac.qc:2 +msgid "Heavy Laser Assault Cannon" +msgstr "Heavy Laser Assault Cannon" + +#: qcsrc/server/w_hlac.qc:242 +#, c-format +msgid "%s was cut down by %s" +msgstr "%s è stato abbattuto da %s" + +#: qcsrc/server/w_hook.qc:2 +msgid "Grappling Hook" +msgstr "Grappling Hook" + +#: qcsrc/server/w_hook.qc:266 qcsrc/server/w_porto.qc:296 +#, c-format +msgid "%s did the impossible" +msgstr "%s ha fatto l'impossibile" + +#: qcsrc/server/w_hook.qc:268 +#, c-format +msgid "%s has run into %s's gravity bomb" +msgstr "%s si è imbattuto nella bomba di gravità di %s" + +#: qcsrc/server/w_laser.qc:2 +msgid "Laser" +msgstr "Laser" + +#: qcsrc/server/w_laser.qc:311 +#, c-format +msgid "%s lasered themself to hell" +msgstr "%s si è \"laserato\" all'inferno" + +#: qcsrc/server/w_laser.qc:315 +#, c-format +msgid "%s was cut in half by %s's gauntlet" +msgstr "%s è stato tagliato a metà dal guanto di %s" + +#: qcsrc/server/w_laser.qc:317 +#, c-format +msgid "%s was lasered to death by %s" +msgstr "%s è stato \"laserato\" a morte da %s" + +#: qcsrc/server/w_minelayer.qc:2 +msgid "Mine Layer" +msgstr "Mine Layer" + +#: qcsrc/server/w_minelayer.qc:523 qcsrc/server/w_rocketlauncher.qc:501 +#, c-format +msgid "%s exploded" +msgstr "%s è esploso" + +#: qcsrc/server/w_minelayer.qc:527 +#, c-format +msgid "%s got too close to %s's mine" +msgstr "%s s'è avvicinato troppo alla mina di %s" + +#: qcsrc/server/w_minelayer.qc:529 +#, c-format +msgid "%s almost dodged %s's mine" +msgstr "%s ha quasi schivato la mina di %s" + +#: qcsrc/server/w_minelayer.qc:531 +#, c-format +msgid "%s stepped on %s's mine" +msgstr "%s è passato sopra la mina di %s" + +#: qcsrc/server/w_minstanex.qc:2 +msgid "MinstaNex" +msgstr "MinstaNex" + +#: qcsrc/server/w_minstanex.qc:293 qcsrc/server/w_nex.qc:253 +#: qcsrc/server/w_shotgun.qc:215 qcsrc/server/w_uzi.qc:317 +#, c-format +msgid "%s is now thinking with portals" +msgstr "%s sta ora pensando con i portali" + +#: qcsrc/server/w_minstanex.qc:295 qcsrc/server/w_nex.qc:255 +#, c-format +msgid "%s has been vaporized by %s" +msgstr "%s è stato vaporizzato da %s" + +#: qcsrc/server/w_nex.qc:2 +msgid "Nex" +msgstr "Nex" + +#: qcsrc/server/w_porto.qc:2 +msgid "Port-O-Launch" +msgstr "Port-O-Launch" + +#: qcsrc/server/w_porto.qc:298 +#, c-format +msgid "%s felt %s doing the impossible to him" +msgstr "%s ha sentito %s fargli l'impossibile" + +#: qcsrc/server/w_rifle.qc:2 +msgid "Rifle" +msgstr "Fucile" + +#: qcsrc/server/w_rifle.qc:233 +#, c-format +msgid "%s shot themself automatically" +msgstr "%s si è sparato da solo automaticamente" + +#: qcsrc/server/w_rifle.qc:235 +#, c-format +msgid "%s sniped themself somehow" +msgstr "%s si è fucilato da solo in qualche modo" + +#: qcsrc/server/w_rifle.qc:242 +#, c-format +msgid "%s failed to hide from %s's bullet hail" +msgstr "%s non è riuscito a nascondersi dalla raffica di proiettili di %s" + +#: qcsrc/server/w_rifle.qc:244 +#, c-format +msgid "%s died in %s's bullet hail" +msgstr "%s è morto nella raffica di proiettili di %s" + +#: qcsrc/server/w_rifle.qc:251 +#, c-format +msgid "%s failed to hide from %s's rifle" +msgstr "%s non è riuscito a nascondersi dal fucile di %s" + +#: qcsrc/server/w_rifle.qc:256 +#, c-format +msgid "%s got hit in the head by %s" +msgstr "%s ha preso un colpo in testa da %s" + +#: qcsrc/server/w_rifle.qc:258 qcsrc/server/w_uzi.qc:321 +#, c-format +msgid "%s was sniped by %s" +msgstr "%s è stato fucilato da %s" + +#: qcsrc/server/w_rocketlauncher.qc:2 +msgid "Rocket Launcher" +msgstr "Rocket Launcher" + +#: qcsrc/server/w_rocketlauncher.qc:505 +#, c-format +msgid "%s got too close to %s's rocket" +msgstr "%s s'è avvicinato troppo al razzo di %s" + +#: qcsrc/server/w_rocketlauncher.qc:507 +#, c-format +msgid "%s almost dodged %s's rocket" +msgstr "%s ha quasi schivato il razzo di %s" + +#: qcsrc/server/w_rocketlauncher.qc:509 +#, c-format +msgid "%s ate %s's rocket" +msgstr "%s ha mangiato il razzo di %s" + +#: qcsrc/server/w_seeker.qc:2 +msgid "T.A.G. Seeker" +msgstr "T.A.G. Seeker" + +#: qcsrc/server/w_seeker.qc:659 +#, c-format +msgid "%s was tagged by %s" +msgstr "%s è stato contrassegnato da %s" + +#: qcsrc/server/w_shotgun.qc:2 +msgid "Shotgun" +msgstr "Shotgun" + +#: qcsrc/server/w_shotgun.qc:219 +#, c-format +msgid "%2$s ^7slapped %1$s ^7around a bit with a large ^2shotgun" +msgstr "%2$s ^7ha schiaffeggiato %1$s ^7un pò con un grosso ^2shotgun" + +#: qcsrc/server/w_shotgun.qc:221 +#, c-format +msgid "%s was gunned by %s" +msgstr "%s è stato sparato da %s" + +#: qcsrc/server/w_tuba.qc:2 +#, c-format +msgid "@!#%'n Tuba" +msgstr "@!#%'n Tuba" + +#: qcsrc/server/w_tuba.qc:252 +#, c-format +msgid "%s hurt his own ears with the @!#%%'n Tuba" +msgstr "%s s'è fatto male alle orecchie con la @!#%%'n Tuba" + +#: qcsrc/server/w_tuba.qc:256 +#, c-format +msgid "%s died of %s's great playing on the @!#%%'n Tuba" +msgstr "%s è morto nella gran esibizione di %s con la @!#%%'n Tuba" + +#: qcsrc/server/w_uzi.qc:2 +msgid "Machine Gun" +msgstr "Machine Gun" + +#: qcsrc/server/w_uzi.qc:323 +#, c-format +msgid "%s was riddled full of holes by %s" +msgstr "%s è stato riempito di buchi da %s" + +#~ msgid "Damage & water blur" +#~ msgstr "Sfocatura da danno & acqua:" + +#~ msgid "Powerup sharpen" +#~ msgstr "Powerup nitido" + +#~ msgid "Waypoint settings:" +#~ msgstr "Impostazioni dei waypoint" + +#~ msgid "" +#~ "Please answer a few initial questions to enhance the game experience." +#~ msgstr "" +#~ "Per favore rispondi a poche domande iniziali per migliorare l'esperienza " +#~ "di gioco." + +#~ msgid "%d/%d" +#~ msgstr "%d/%d" + +#~ msgid "Sniper Rifle" +#~ msgstr "Sniper Rifle" + +#~ msgid "Accelerometer scale:" +#~ msgstr "Scala accelerometro:" + +#~ msgid "Show accelerometer" +#~ msgstr "Mostra accelerometro" + +#~ msgid "qu/s (hidden)" +#~ msgstr "qu/s (nascosto)" + +#~ msgid "Speedometer" +#~ msgstr "Tachimetro" diff --git a/menu.dat.nl.po b/menu.dat.nl.po new file mode 100644 index 0000000000..0e2fb68101 --- /dev/null +++ b/menu.dat.nl.po @@ -0,0 +1,2932 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-09-02 07:51+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: qcsrc/common/mapinfo.qc:1092 qcsrc/menu/xonotic/skinlist.c:163 +#, c-format +msgid "%s: %s" +msgstr "%s: %s" + +#: qcsrc/menu/gamecommand.qc:47 +#, c-format +msgid "error: status is %d\n" +msgstr "error: status is %d\n" + +#: qcsrc/menu/gamecommand.qc:65 +msgid "Usage: menu_cmd command..., where possible commands are:\n" +msgstr "Gebruik: menu_cmd command..., waar mogelijke opdrachten zijn:\n" + +#: qcsrc/menu/gamecommand.qc:66 +msgid " sync - reloads all cvars on the current menu page\n" +msgstr " sync - alle cvars op de huidige menupagina worden opnieuw geladen\n" + +#: qcsrc/menu/gamecommand.qc:67 +msgid " directmenu ITEM - select a menu item as main item\n" +msgstr " directmenu ITEM - selecteer deel van menu als hoofddeel" + +#: qcsrc/menu/gamecommand.qc:193 +msgid "error creating curl handle\n" +msgstr "fout bij aanmaken curl handgreep\n" + +#: qcsrc/menu/gamecommand.qc:239 +msgid "Invalid command. For a list of supported commands, try menu_cmd help.\n" +msgstr "" +"Ongeldige opdracht. Voor een lijst met ondersteunde opdrachten, probeer " +"menu_cmd help.\n" + +#: qcsrc/menu/item/gecko.c:49 +msgid "Browser not initialized!" +msgstr "Browser is niet geinitialiseerd!" + +#: qcsrc/menu/item/label.c:63 +#, c-format +msgid "NOTE: label text %s too wide for label, condensed by factor %f\n" +msgstr "" +"ATTENTIE: tekst van het label is %s te wijd, word met een factor %f " +"verkleind\n" + +#: qcsrc/menu/item/listbox.c:300 +#, c-format +msgid "Item %d" +msgstr "Item %d" + +#: qcsrc/menu/item/slider.c:64 +#, c-format +msgid "%d (%s)" +msgstr "%d (%s)" + +#: qcsrc/menu/item/textslider.c:29 qcsrc/menu/item/textslider.c:31 +msgid "custom" +msgstr "aangepast" + +#: qcsrc/menu/menu.qc:29 +#, fuzzy, c-format +msgid "^4MQC Build information: ^1%s\n" +msgstr "^4MQC Versie informatie: %s\n" + +#: qcsrc/menu/xonotic/campaign.c:284 +#: qcsrc/menu/xonotic/dialog_singleplayer.c:134 +msgid "???" +msgstr "???" + +#: qcsrc/menu/xonotic/campaign.c:285 +#, c-format +msgid "Level %d: %s" +msgstr "Level %d: %s" + +#: qcsrc/menu/xonotic/cvarlist.c:85 +msgid "will be saved to config.cfg" +msgstr "word in config.cfg opgeslagen" + +#: qcsrc/menu/xonotic/cvarlist.c:87 +msgid "will not be saved" +msgstr "word niet opgeslagen" + +#: qcsrc/menu/xonotic/cvarlist.c:89 +msgid "private" +msgstr "privé " + +#: qcsrc/menu/xonotic/cvarlist.c:91 +msgid "engine setting" +msgstr "engine instelling" + +#: qcsrc/menu/xonotic/cvarlist.c:93 +msgid "read only" +msgstr "alleen lezen" + +#: qcsrc/menu/xonotic/dialog_credits.c:5 +msgid "Credits" +msgstr "Aftiteling" + +#: qcsrc/menu/xonotic/dialog_credits.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:269 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:41 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:57 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:61 +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:21 +msgid "OK" +msgstr "OK" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:4 +msgid "Welcome" +msgstr "Welkom" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:33 +msgid "" +"Welcome to Xonotic, please select your language preference and enter your " +"player name to get started. You can change these options later through the " +"menu system." +msgstr "" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:38 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:35 +msgid "Text language:" +msgstr "Taal van de tekst:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:47 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:40 +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:39 +msgid "Name:" +msgstr "Naam:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:69 +msgid "Save settings" +msgstr "Opslaginstellingen:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:4 +msgid "Ammo Panel" +msgstr "Ammunitie Paneel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:22 +msgid "Ammunition display:" +msgstr "Ammunitie venster:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:25 +msgid "Show only current ammo type" +msgstr "Laat alleen huidig ammunitietype zien" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:28 +msgid "Align icon:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:29 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:36 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:40 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:40 +msgid "Left" +msgstr "Links" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:38 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:41 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:41 +msgid "Right" +msgstr "Rechts" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:4 +msgid "Centerprint" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:23 +#, fuzzy +msgid "Message duration:" +msgstr "Verzadiging:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:27 +#, fuzzy +msgid "Fade time:" +msgstr "Post vervaagtijd:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:31 +#, fuzzy +msgid "Flip messages order" +msgstr "Notificatievolgorde omdraaien" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:33 +#, fuzzy +msgid "Text alignment:" +msgstr "Icoon positie:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:37 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:50 +msgid "Center" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:41 +#, fuzzy +msgid "Font scale:" +msgstr "Wegwijzer schaal:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:4 +msgid "Chat Panel" +msgstr "Chat Paneel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:22 +msgid "Chat entries:" +msgstr "Chat posts:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:25 +msgid "Chat size:" +msgstr "Chat grootte" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:29 +msgid "Chat lifetime:" +msgstr "Chat tijd:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:33 +msgid "Chat beep sound" +msgstr "Chat geluid" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:4 +msgid "Engine Info Panel" +msgstr "Engine Informatie Paneel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:22 +msgid "Engine info:" +msgstr "Engine Informatie:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:25 +msgid "Use an averaging algorithm for fps" +msgstr "Gebruik een middelend algoritme voor fps" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:4 +msgid "Health/Armor Panel" +msgstr "Health/Armor Paneel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:22 +msgid "Enable status bar" +msgstr "Activeer status balk" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:24 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:24 +msgid "Status bar alignment:" +msgstr "Statusbalk positie:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:42 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:42 +msgid "Inward" +msgstr "Binnenkant" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:43 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:43 +msgid "Outward" +msgstr "Buitenkant" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:37 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:37 +msgid "Icon alignment:" +msgstr "Icoon positie:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:45 +msgid "Flip health and armor positions" +msgstr "Keer health en armor posities om" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:4 +msgid "Info Messages Panel" +msgstr "Informatieberichten Paneel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:22 +msgid "Info messages:" +msgstr "Informatieberichten" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:25 +msgid "Flip align" +msgstr "Anders uitlijnen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_modicons.c:4 +msgid "Mod Icons Panel" +msgstr "Speliconen Paneel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:4 +msgid "Notification Panel" +msgstr "Notificatie Paneel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:22 +msgid "Notifications:" +msgstr "Notificaties:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:25 +msgid "Also print notifications to the console" +msgstr "Notificaties ook in de console printen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:28 +msgid "Flip notify order" +msgstr "Notificatievolgorde omdraaien" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:31 +msgid "Entry lifetime:" +msgstr "Post tijd:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:35 +msgid "Entry fadetime:" +msgstr "Post vervaagtijd:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:4 +#, fuzzy +msgid "Physics Panel" +msgstr "Chat Paneel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:21 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:21 +msgid "Panel disabled" +msgstr "Paneel uitgeschakeld" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:23 +#, fuzzy +msgid "Panel enabled" +msgstr "Paneel uitgeschakeld" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:24 +#, fuzzy +msgid "Panel enabled even observing" +msgstr "Paneel activeren tijdens observeren" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:25 +#, fuzzy +msgid "Panel enabled only in Race/CTS" +msgstr "Paneel actief in teammodus" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:31 +#, fuzzy +msgid "Status bar" +msgstr "Activeer status balk" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:48 +msgid "Left align" +msgstr "Links" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:34 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:52 +msgid "Right align" +msgstr "Rechts" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:35 +#, fuzzy +msgid "Inward align" +msgstr "Binnenkant" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:36 +#, fuzzy +msgid "Outward align" +msgstr "Buitenkant" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:40 +#, fuzzy +msgid "Flip speed/acceleration positions" +msgstr "Keer health en armor posities om" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:44 +#, fuzzy +msgid "Speed:" +msgstr "Snelheid (kB/s):" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:45 +msgid "Include vertical speed" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:56 +msgid "Speed unit:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:58 +msgid "qu/s" +msgstr "qu/s" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:59 +msgid "m/s" +msgstr "m/s" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:60 +msgid "km/h" +msgstr "km/h" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:61 +msgid "mph" +msgstr "mph" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:62 +msgid "knots" +msgstr "knopen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:64 +#, fuzzy +msgid "Show" +msgstr "Ammunitie tonen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:67 +#, fuzzy +msgid "Top speed" +msgstr "Zoom snelheid:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:73 +#, fuzzy +msgid "Acceleration:" +msgstr "Reflecties" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:74 +msgid "Include vertical acceleration" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:4 +msgid "Powerups Panel" +msgstr "Powerups paneel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:45 +msgid "Flip strength and shield positions" +msgstr "Keer kracht en schild posities om" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:4 +msgid "Pressed Keys Panel" +msgstr "Ingedrukte Toetsen Paneel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:22 +msgid "Panel enabled when spectating" +msgstr "Paneel activeren tijdens observeren" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:23 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:23 +msgid "Panel always enabled" +msgstr "Paneel altijd actief" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:30 +msgid "Forced aspect:" +msgstr "Aspect ratio:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_racetimer.c:4 +msgid "Race Timer Panel" +msgstr "Race Tijd Paneel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:4 +msgid "Radar Panel" +msgstr "Radar Paneel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:22 +msgid "Panel enabled in teamgames" +msgstr "Paneel actief in teammodus" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:29 +msgid "Radar:" +msgstr "Radar:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:32 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:43 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:154 +#: qcsrc/menu/xonotic/util.qc:600 +msgid "Alpha:" +msgstr "Alpha:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:36 +msgid "Rotation:" +msgstr "Rotatie:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:38 +msgid "Forward" +msgstr "Voorwaarts" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:39 +msgid "West" +msgstr "West" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:40 +msgid "South" +msgstr "Zuid" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:41 +msgid "East" +msgstr "Oost" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:42 +msgid "North" +msgstr "Noord" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:46 +msgid "Scale:" +msgstr "Schaal:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:50 +msgid "Zoom mode:" +msgstr "Zoom modus:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:52 +msgid "Zoomed in" +msgstr "Ingezoomd" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:53 +msgid "Zoomed out" +msgstr "Uitgezoomd" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:54 +msgid "Always zoomed" +msgstr "Altijd ingezoomd" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:55 +msgid "Never zoomed" +msgstr "Altijd uitgezoomd" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:4 +msgid "Score Panel" +msgstr "Score Paneel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:22 +msgid "Score:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:25 +msgid "Rankings:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:26 +#, fuzzy +msgid "Off" +msgstr "VBO^Uit" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:27 +msgid "And me" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:28 +msgid "Pure" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:4 +msgid "Timer Panel" +msgstr "Tijd Paneel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:22 +msgid "Timer:" +msgstr "Timer:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:25 +msgid "Show elapsed time" +msgstr "Laat verstreken tijd zien" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:4 +msgid "Vote Panel" +msgstr "Stem Paneel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:22 +msgid "Alpha after voting:" +msgstr "Alpha na stemmen:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:4 +msgid "Weapons Panel" +msgstr "Wapenpaneel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:24 +msgid "Fade out after:" +msgstr "Vervagen na:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:26 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:36 +msgid "Never" +msgstr "Nooit" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:28 +#, c-format +msgid "%ds" +msgstr "%ds" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:32 +msgid "Fade effect:" +msgstr "Vervagingseffect:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:35 +msgid "EF^None" +msgstr "EF^Geen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:36 +msgid "Slide" +msgstr "Schuiven" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:37 +msgid "Alpha" +msgstr "Alpha" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:38 +#, fuzzy +msgid "EF^Both" +msgstr "WRN^Beiden" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:42 +msgid "Weapon icons:" +msgstr "Wapeniconen:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:45 +msgid "Show weapon ID as:" +msgstr "Toon wapen-ID als:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:46 +msgid "SHOWAS^None" +msgstr "SHOWAS^Geen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:47 +msgid "Number" +msgstr "Nummer" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:48 +msgid "Bind" +msgstr "Binden" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:51 +msgid "Show Accuracy" +msgstr "Nauwkeurigheid tonen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:52 +msgid "Show Ammo" +msgstr "Ammunitie tonen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:55 +msgid "Ammo bar color:" +msgstr "Ammunitie balk kleur:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:61 +msgid "Ammo bar alpha:" +msgstr "Ammunitie alpha:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:4 +msgid "Panel HUD Setup" +msgstr "Paneel HUD Instellingen" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:21 +msgid "Panel background defaults:" +msgstr "Paneel achtergrond standaards:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:23 qcsrc/menu/xonotic/util.qc:575 +msgid "Background:" +msgstr "Achtergrond" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:25 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:37 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:52 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:91 qcsrc/menu/xonotic/util.qc:578 +#: qcsrc/menu/xonotic/util.qc:594 qcsrc/menu/xonotic/util.qc:611 +msgid "Disable" +msgstr "Uitschakelen" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:30 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:77 qcsrc/menu/xonotic/util.qc:583 +msgid "Color:" +msgstr "Kleur:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:35 qcsrc/menu/xonotic/util.qc:591 +msgid "Border size:" +msgstr "Grootte rand:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:50 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:89 +msgid "Team color:" +msgstr "Teamkleur:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:58 qcsrc/menu/xonotic/util.qc:617 +msgid "Test team color in configure mode" +msgstr "Test teamkleur in aanpassingsmodus" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:61 qcsrc/menu/xonotic/util.qc:620 +msgid "Padding:" +msgstr "Opvulling:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:68 +msgid "HUD Dock:" +msgstr "HUD Werf:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:70 +msgid "DOCK^Disabled" +msgstr "DOCK^Uitgeschakeld" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:71 +msgid "DOCK^Small" +msgstr "DOCK^Klein" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:72 +msgid "DOCK^Medium" +msgstr "DOCK^Gemiddeld" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:73 +msgid "DOCK^Large" +msgstr "DOCK^Groot" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:96 +msgid "Grid settings:" +msgstr "Raster instellingen" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:99 +msgid "Snap panels to grid" +msgstr "Lijn panelen uit met grid" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:102 +msgid "Grid size:" +msgstr "Raster grootte:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:103 +msgid "X:" +msgstr "X:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:109 +msgid "Y:" +msgstr "Y:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:117 +msgid "Exit setup" +msgstr "Beëindig panel HUD modus" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:4 +msgid "Multiplayer" +msgstr "Multiplayer" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:18 +msgid "Servers" +msgstr "Servers" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:19 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:5 +msgid "Create" +msgstr "Maak aan" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:20 +msgid "Demos" +msgstr "Demo’s" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:5 +msgid "Player Setup" +msgstr "Speler Instellingen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:34 +msgid "Game type:" +msgstr "Game modus" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:46 +msgid "Match settings:" +msgstr "Match instellingen:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:49 +msgid "Time limit:" +msgstr "Tijdslimiet:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:53 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:61 +msgid "Use map specified default" +msgstr "Gebruik map specificaties" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:56 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:155 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:156 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:157 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:161 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:162 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:163 +msgid "Point limit:" +msgstr "Punten limiet:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:64 +msgid "Player slots:" +msgstr "Aantal spelers:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:67 +msgid "Number of bots:" +msgstr "Aantal bots" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:71 +msgid "Bot skill:" +msgstr "Bot vaardigheid" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:74 +msgid "Botlike" +msgstr "Botlike" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:75 +msgid "Beginner" +msgstr "Beginner" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:76 +msgid "You will win" +msgstr "Je zal winnen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:77 +msgid "You can win" +msgstr "Je kan winnen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:78 +msgid "You might win" +msgstr "Je zou kunnen winnen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:79 +msgid "Advanced" +msgstr "Geavanceerd" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:80 +msgid "Expert" +msgstr "Expert" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:81 +msgid "Pro" +msgstr "Pro" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:82 +msgid "Assassin" +msgstr "Sluipmoordenaar" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:83 +msgid "Unhuman" +msgstr "Onmenselijk" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:84 +msgid "Godlike" +msgstr "Goddelijk" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:88 +msgid "Mutators..." +msgstr "Mutaties..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:97 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:57 +msgid "Advanced settings..." +msgstr "Geavanceerde instellingen..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:104 +msgid "Map list:" +msgstr "Map lijst:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:110 +msgid "Select all" +msgstr "Selecteer alles" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:113 +msgid "Select none" +msgstr "Selecteer niets" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:119 +msgid "Start Multiplayer!" +msgstr "Start Multiplayer!" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:154 +msgid "Capture limit:" +msgstr "Vlaggen limiet:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:158 +msgid "Lives:" +msgstr "Levens:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:159 +msgid "Laps:" +msgstr "Rondes:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:160 +msgid "Goals:" +msgstr "Goals:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:164 +msgid "Frag limit:" +msgstr "Frag limiet:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:6 +msgid "Advanced server settings" +msgstr "Geavanceerde server instellingen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:25 +msgid "Game settings:" +msgstr "Game instellingen:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:28 +msgid "Allow spectating" +msgstr "Observeren toestaan" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:31 +msgid "Spawn shield:" +msgstr "Spawn shild:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:36 +msgid "Game speed:" +msgstr "Snelheid:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:40 +msgid "Teamplay settings:" +msgstr "Team modus instellingen:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:43 +msgid "Friendly fire scale:" +msgstr "Friendly fire schaal:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:47 +msgid "Virtual friendly fire (effect only)" +msgstr "Virtuele friendly fire (alleen effect)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:50 +msgid "Friendly fire penalty:" +msgstr "Friendly fire straf" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:54 +msgid "Virtual penalty (effect only)" +msgstr "Virtuele straf (alleen effect)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:57 +msgid "Teams:" +msgstr "Teams:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:66 +msgid "Map voting:" +msgstr "Map stemmen:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:68 +msgid "No voting" +msgstr "Geen stemmen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:69 +msgid "2 choices" +msgstr "2 keuzes" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:70 +msgid "3 choices" +msgstr "3 keuzes" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:71 +msgid "4 choices" +msgstr "4 keuzes" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:72 +msgid "5 choices" +msgstr "5 keuzes" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:73 +msgid "6 choices" +msgstr "6 keuzes" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:74 +msgid "7 choices" +msgstr "7 keuzes" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:75 +msgid "8 choices" +msgstr "8 keuzes" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:76 +msgid "9 choices" +msgstr "9 keuzes" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:79 +msgid "Simple majority wins vcall" +msgstr "Simple meerderheid wint vcall" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:5 +msgid "Map Information" +msgstr "Map informatie" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "Full item placement" +msgstr "Volledige item distributie" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "MinstaGib only" +msgstr "Alleen MinstaGib" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:78 +msgid "Title:" +msgstr "Titel:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:84 +msgid "Author:" +msgstr "Auteur:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:90 +msgid "Features:" +msgstr "Bevat:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:95 +msgid "Game types:" +msgstr "Game modus:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:118 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:314 +msgid "Close" +msgstr "Dichtdoen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:121 +#, fuzzy +msgid "MAP^Play" +msgstr "Speel" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:7 +msgid "Mutators" +msgstr "Mutaties" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:33 +msgid "All Weapons Arena" +msgstr "Alle Wapens Arena" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:35 +msgid "Most Weapons Arena" +msgstr "Meeste Wapens Arena" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:56 +#, c-format +msgid "%s Arena" +msgstr "%s Arena" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:68 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:167 +msgid "Dodging" +msgstr "Ontwijken" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:70 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:250 +msgid "MinstaGib" +msgstr "MinstaGib" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:253 +msgid "NIX" +msgstr "NIX" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:74 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:205 +msgid "Rocket Flying" +msgstr "Raket Vliegen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:78 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:264 +msgid "No start weapons" +msgstr "Geen start wapens" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:80 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:189 +msgid "Low gravity" +msgstr "Lage zwaartekracht" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:170 +msgid "Cloaked" +msgstr "Onzichtbaarheid" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:84 +msgid "Hook" +msgstr "Haak" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:86 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:173 +msgid "Midair" +msgstr "In de lucht" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:88 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:176 +msgid "Vampire" +msgstr "Vampier" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:90 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:208 +msgid "Piñata" +msgstr "Piñata" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:92 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:211 +msgid "Weapons stay" +msgstr "Wapens blijven" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:94 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:180 +msgid "Blood loss" +msgstr "Bloedverlies" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:96 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:202 +msgid "Jet pack" +msgstr "Jet pack" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:98 +msgid "MUT^None" +msgstr "MUT^Geen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:164 +msgid "Gameplay mutators:" +msgstr "Gameplay mutaties:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:196 +msgid "Weapon & item mutators:" +msgstr "Wapen & item mutaties:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:199 +msgid "Grappling hook" +msgstr "Grappling hook" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:215 +msgid "Weapon arenas:" +msgstr "Wapen arena’s:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:218 +msgid "Regular (no arena)" +msgstr "Normaal (geen arena)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:239 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:256 +msgid "with laser" +msgstr "met lazer" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:247 +msgid "Special arenas:" +msgstr "Speciale arenas:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:260 +msgid "Most weapons" +msgstr "Meeste wapens" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:4 +msgid "Demo" +msgstr "Demo" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:28 +msgid "Record demos while playing" +msgstr "Demo’s opnemen tijdens het spelen:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:32 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:28 +msgid "Filter:" +msgstr "Filter:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:29 +#: qcsrc/menu/xonotic/dialog_settings_input.c:41 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:24 +msgid "Clear" +msgstr "Legen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:43 +msgid "Timedemo" +msgstr "Benchmark demo" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:46 +#, fuzzy +msgid "DEMO^Play" +msgstr "Speel" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:4 +msgid "Join" +msgstr "Meedoen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:36 +msgid "SRVS^Empty" +msgstr "SRVS^Leeg" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:40 +msgid "SRVS^Full" +msgstr "SRVS^Vol" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:44 +msgid "Pause" +msgstr "Pauze" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:56 +msgid "Address:" +msgstr "Adres:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:67 +msgid "Info..." +msgstr "Info..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:317 +msgid "Join!" +msgstr "Meedoen!" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:5 +msgid "Server Information" +msgstr "Server Informatie" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:115 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:116 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:183 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:189 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:199 +msgid "N/A" +msgstr "N/A" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:158 +#, c-format +msgid "%d/%d, %d free player slots" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +#, c-format +msgid "%d modified settings" +msgstr "%d gemodificeerde instellingen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +msgid "Official settings" +msgstr "Officiële configuratie" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:197 +msgid "N/A (can't connect)" +msgstr "N/A (kan geen verbinding maken)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:205 +msgid "not supported (can't connect)" +msgstr "niet ondersteund (kan geen verbinding maken)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:207 +msgid "not supported (won't encrypt)" +msgstr "niet ondersteund (zal niet versleutelen)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:211 +msgid "supported (will encrypt)" +msgstr "ondersteund (zal versleutelen)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:213 +msgid "supported (won't encrypt)" +msgstr "ondersteund (zal niet versleutelen)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:217 +msgid "requested (will encrypt)" +msgstr "verzocht (zal versleutelen)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:219 +msgid "requested (won't encrypt)" +msgstr "verzocht (zal niet versleutelen)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:223 +msgid "required (can't connect)" +msgstr "verplicht (kan geen verbinding maken)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:225 +msgid "required (will encrypt)" +msgstr "verplicht (zal versleutelen)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:246 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:269 +msgid "Players:" +msgstr "Spelers:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:254 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:38 +msgid "Type:" +msgstr "Type:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:259 +msgid "Map:" +msgstr "Map:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:264 +msgid "Gameplay:" +msgstr "Gameplay:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:274 +msgid "Bots:" +msgstr "Bots:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:279 +msgid "Mod:" +msgstr "Mod:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:284 +msgid "Version:" +msgstr "Versie:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:289 +msgid "Ping:" +msgstr "Ping:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:295 +msgid "CA:" +msgstr "CA:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:301 +msgid "Key:" +msgstr "Sleutel:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:307 +msgid "Encryption:" +msgstr "Versleuteling:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:63 +msgid "Model:" +msgstr "Personage:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:88 +msgid "Field of view:" +msgstr "Kijkhoek (FoV):" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:92 +msgid "View bobbing:" +msgstr "Schommelend zicht:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:96 +msgid "Zoom factor:" +msgstr "Zoom factor:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:100 +msgid "Zoom speed:" +msgstr "Zoom snelheid:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:103 +msgid "Weapon settings..." +msgstr "Wapen instellingen..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:110 +msgid "Crosshair:" +msgstr "Richtkruis:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:111 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:139 +msgid "Per weapon" +msgstr "Per wapen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:130 +msgid "Crosshair size:" +msgstr "Richtkruis grootte:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:134 +msgid "Crosshair alpha:" +msgstr "Richtkruis alpha:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:138 +msgid "Crosshair color:" +msgstr "Richtkruis kleur:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:140 +msgid "By health" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:143 +#, fuzzy +msgid "Custom" +msgstr "aangepast" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:148 +msgid "Enable center dot" +msgstr "Activeer middenpunt" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:151 +msgid "Size:" +msgstr "Grootte" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:158 +msgid "Hit test:" +msgstr "Tref test:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:159 +msgid "HTST^None" +msgstr "HTST^Geen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:160 +msgid "TrueAim" +msgstr "Echt mikken" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:161 +msgid "Enemies" +msgstr "Tegenstanders" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:164 +msgid "Waypoints setup..." +msgstr "Wegwijzers instellingen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:169 +msgid "Enter HUD editor" +msgstr "Ga naar HUD editor" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:174 +msgid "Force models:" +msgstr "Forceer modellen:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:175 +msgid "MDL^None" +msgstr "MDL^Geen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:176 +msgid "MDL^Custom" +msgstr "MDL^Aangepast" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:177 +msgid "MDL^All" +msgstr "MDL^Alle" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:180 +msgid "Disable gore effects" +msgstr "Schakel bloederigheid uit" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:182 +msgid "Gibs:" +msgstr "Gibs:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:184 +msgid "GIBS^None" +msgstr "GIBS^Geen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:185 +msgid "GIBS^Few" +msgstr "GIBS^Weinig" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:186 +msgid "GIBS^Many" +msgstr "GIBS^Veel" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:187 +msgid "GIBS^Lots" +msgstr "GIBS^Erg veel" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:191 +msgid "Damage splash:" +msgstr "Pijn spatten:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:195 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:173 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:194 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:30 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:41 +#: qcsrc/menu/xonotic/dialog_settings_video.c:109 +msgid "Apply immediately" +msgstr "Meteen toepassen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:5 +msgid "Waypoints" +msgstr "Wegwijzers" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:23 +msgid "Show base waypoints" +msgstr "Laat wegwijzers zien voor de basis" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:25 +msgid "Waypoint scale:" +msgstr "Wegwijzer schaal:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:29 +msgid "Waypoint alpha:" +msgstr "Wegwijzer alpha:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:34 +msgid "Show names:" +msgstr "Laat namen zien:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:37 +msgid "Teammates" +msgstr "Teammaten" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:38 +msgid "All players" +msgstr "Alle spelers" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:6 +msgid "Weapon settings" +msgstr "Wapen instellingen" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:29 +msgid "Weapon priority list:" +msgstr "Wapen prioriteit lijst:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:34 +msgid "Up" +msgstr "Omhoog" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:37 +msgid "Down" +msgstr "Omlaag" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:41 +msgid "Use priority list for weapon cycling" +msgstr "Gebruik de prioriteit lijst voor het wisselen van wapens " + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:43 +msgid "Auto switch weapons on pickup" +msgstr "Automatisch wapens wisselen bij oppakken" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:45 +msgid "Draw 1st person weapon model" +msgstr "Wapen positie" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:55 +msgid "Flip view horizontally" +msgstr "Spiegel zicht horizontaal" + +#: qcsrc/menu/xonotic/dialog_news.c:4 +msgid "News" +msgstr "Nieuws" + +#: qcsrc/menu/xonotic/dialog_news.c:18 +msgid "http://www.xonotic.org/team/blog/" +msgstr "http://www.xonotic.org/team/blog/" + +#: qcsrc/menu/xonotic/dialog_quit.c:4 +msgid "Quit" +msgstr "Afsluiten" + +#: qcsrc/menu/xonotic/dialog_quit.c:17 +msgid "Are you sure you want to quit?" +msgstr "Weet je zeker dat je wil afsluiten?" + +#: qcsrc/menu/xonotic/dialog_quit.c:20 +msgid "Yes" +msgstr "Ja" + +#: qcsrc/menu/xonotic/dialog_quit.c:21 +msgid "No" +msgstr "Nee" + +#: qcsrc/menu/xonotic/dialog_settings.c:4 +msgid "Settings" +msgstr "Instellingen" + +#: qcsrc/menu/xonotic/dialog_settings.c:18 +#: qcsrc/menu/xonotic/dialog_settings_input.c:4 +msgid "Input" +msgstr "Input" + +#: qcsrc/menu/xonotic/dialog_settings.c:19 +#: qcsrc/menu/xonotic/dialog_settings_video.c:4 +msgid "Video" +msgstr "Video" + +#: qcsrc/menu/xonotic/dialog_settings.c:20 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:4 +msgid "Effects" +msgstr "Effecten" + +#: qcsrc/menu/xonotic/dialog_settings.c:21 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:4 +msgid "Audio" +msgstr "Geluid" + +#: qcsrc/menu/xonotic/dialog_settings.c:22 +#: qcsrc/menu/xonotic/dialog_settings_network.c:4 +msgid "Network" +msgstr "Netwerk" + +#: qcsrc/menu/xonotic/dialog_settings.c:23 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:4 +msgid "Misc" +msgstr "Misc" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:27 +msgid "Master:" +msgstr "Volume:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:33 +msgid "Music:" +msgstr "Muziek:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:41 +msgid "VOL^Ambient:" +msgstr "VOL^Achtergrond:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:48 +msgid "Info:" +msgstr "Info:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:55 +msgid "Items:" +msgstr "Items:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:62 +msgid "Pain:" +msgstr "Pijn:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:69 +msgid "Player:" +msgstr "Speler:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:76 +msgid "Shots:" +msgstr "Schoten:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:83 +msgid "Voice:" +msgstr "Spraak:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:91 +msgid "Weapons:" +msgstr "Wapens:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:98 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:156 +msgid "Frequency:" +msgstr "Frequentie:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:100 +msgid "8 kHz" +msgstr "8 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:101 +msgid "11.025 kHz" +msgstr "11.025 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:102 +msgid "16 kHz" +msgstr "16 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:103 +msgid "22.05 kHz" +msgstr "22.05 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:104 +msgid "24 kHz" +msgstr "24 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:105 +msgid "32 kHz" +msgstr "32 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:106 +msgid "44.1 kHz" +msgstr "44.1 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:107 +msgid "48 kHz" +msgstr "48 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:110 +msgid "Channels:" +msgstr "Kanalen:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:112 +msgid "Mono" +msgstr "Mono" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:113 +msgid "Stereo" +msgstr "Stereo" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:114 +msgid "2.1" +msgstr "2.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:115 +msgid "4" +msgstr "4" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:116 +msgid "5" +msgstr "5" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:117 +msgid "5.1" +msgstr "5.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:118 +msgid "6.1" +msgstr "6.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:119 +msgid "7.1" +msgstr "7.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:123 +msgid "Swap Stereo" +msgstr "Stereo omwisselen" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:127 +msgid "Headphone friendly mode" +msgstr "Koptelefoon modus" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:131 +msgid "Spatial voices:" +msgstr "Ruimtelijke stemmen:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:132 +msgid "VOCS^None" +msgstr "VOCS^Geen" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:133 +msgid "VOCS^Taunts" +msgstr "VOCS^Honen" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:134 +msgid "VOCS^All" +msgstr "VOCS^Alles" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:137 +msgid "Taunt range:" +msgstr "Hoon afstand:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:140 +msgid "RNG^Very short" +msgstr "RNG^Erg kort" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:141 +msgid "RNG^Short" +msgstr "RNG^Kort" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:142 +msgid "RNG^Normal" +msgstr "RNG^Normaal" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:143 +msgid "RNG^Long" +msgstr "RNG^Lang" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:144 +msgid "RNG^Full" +msgstr "RNG^Vol" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:151 +msgid "Automatic taunts" +msgstr "Automatisch honen" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:160 +msgid "Time warning:" +msgstr "Tijd notificatie:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:162 +msgid "WRN^None" +msgstr "WRN^Geen" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:163 +msgid "1 minute" +msgstr "1 minuut" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:164 +msgid "5 minutes" +msgstr "5 minuten" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:165 +msgid "WRN^Both" +msgstr "WRN^Beiden" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:168 +msgid "Hit indicator" +msgstr "Tref indicator" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:170 +msgid "Menu sounds" +msgstr "Menu geluiden" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:38 +msgid "Quality preset:" +msgstr "Kwaliteit voorinstellingen:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:41 +msgid "PRE^OMG!" +msgstr "PRE^" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:42 +msgid "PRE^Low" +msgstr "PRE^Laag" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:43 +msgid "PRE^Medium" +msgstr "PRE^Middel" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:44 +msgid "PRE^Normal" +msgstr "PRE^Normaal" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:45 +msgid "PRE^High" +msgstr "PRE^Hoog" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:46 +msgid "PRE^Ultra" +msgstr "PRE^Ultra" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:48 +msgid "PRE^Ultimate" +msgstr "PRE^Uitstekend" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:52 +msgid "Geometry detail:" +msgstr "Geometrie detail:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:54 +msgid "DET^Lowest" +msgstr "DET^Laagste" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:55 +msgid "DET^Low" +msgstr "DET^Laag" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:56 +msgid "DET^Normal" +msgstr "DET^Normaal" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:57 +msgid "DET^Good" +msgstr "DET^Goed" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:58 +msgid "DET^Best" +msgstr "DET^Beste" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:59 +msgid "DET^Insane" +msgstr "DET^Geweldig" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:62 +msgid "Antialiasing:" +msgstr "Antialiasing:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:64 +msgid "AA^Disabled" +msgstr "AA^Uitgeschakeld" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:65 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:103 +msgid "2x" +msgstr "2x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:66 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:104 +msgid "4x" +msgstr "4x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:70 +msgid "Texture resolution:" +msgstr "Textuur resolutie:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:73 +msgid "RES^Leet" +msgstr "RES^" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:74 +msgid "RES^Lowest" +msgstr "RES^Laagste" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:75 +msgid "RES^Low" +msgstr "RES^Laag" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:76 +msgid "RES^Normal" +msgstr "RES^Normaal" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:77 +msgid "RES^Good" +msgstr "RES^Goed" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:78 +msgid "RES^Best" +msgstr "RES^Beste" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:91 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:94 +msgid "Avoid lossy texture compression" +msgstr "Voorkom textuur compressie met kwaliteitsverlies" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:100 +msgid "Anisotropy:" +msgstr "Anisotropie" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:102 +msgid "ANISO^Disabled" +msgstr "ANISO^Uitgeschakeld" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:105 +msgid "8x" +msgstr "8x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:106 +msgid "16x" +msgstr "16x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:110 +msgid "Particle quality:" +msgstr "Deeltjes kwaliteit" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:113 +msgid "Particle distance:" +msgstr "Deeltjes afstand" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:117 +msgid "Decals" +msgstr "Decals" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:118 +msgid "Decals on models" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:122 +msgid "Distance:" +msgstr "Afstand:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:128 +msgid "Time:" +msgstr "Tijd:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:134 +msgid "Use lightmaps" +msgstr "Gebuik " + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:135 +msgid "Deluxe mapping" +msgstr "Deluxe mapping" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:137 +msgid "Gloss" +msgstr "Glans" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:140 +msgid "Offset mapping" +msgstr "Offset mapping" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:142 +msgid "Relief mapping" +msgstr "Relief mapping" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:145 +msgid "Reflections:" +msgstr "Reflecties" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:148 +msgid "Blurred" +msgstr "Vervaagd" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:149 +msgid "REFL^Good" +msgstr "REFL^Goed" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:150 +msgid "Sharp" +msgstr "Scherp" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:155 +msgid "Show surfaces" +msgstr "Laat oppervlaktes zien" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:157 +msgid "No dynamic lighting" +msgstr "Geen dynamische verlichting" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:159 +msgid "Flash blend approximation" +msgstr "Flash blend approximation" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:161 +msgid "Realtime dynamic lighting" +msgstr "Real-time dynamische verlichting" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:162 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:166 +msgid "Shadows" +msgstr "Schaduwen" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:165 +msgid "Realtime world lighting" +msgstr "Real-time wereld verlichting" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:170 +msgid "Use normal maps" +msgstr "Gebruik normal maps" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:172 +msgid "Soft shadows" +msgstr "Zachte schaduwen" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:175 +msgid "Coronas" +msgstr "Coronas" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:176 +msgid "Use Occlusion Queries" +msgstr "Gebruik Occlusion Queries" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:178 +msgid "Bloom" +msgstr "Bloom" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:180 +msgid "High Dynamic Range (HDR)" +msgstr "Hoog dynamisch bereik (HDR)" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:184 +msgid "Motion blur:" +msgstr "Bewegingsonscherpte:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:189 +msgid "Blur and sharpen postprocessing" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:26 +msgid "Key bindings:" +msgstr "Toetsen:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:31 +msgid "Change key..." +msgstr "Verander toets..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:35 +msgid "Edit..." +msgstr "Aanpassen..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:46 +msgid "Sensitivity:" +msgstr "Gevoeligheid:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:51 +msgid "UI mouse speed:" +msgstr "UI muis snelheid:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:55 +msgid "Mouse filter" +msgstr "Muis filter" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:57 +msgid "Invert mouse" +msgstr "Invert muis" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:60 +#: qcsrc/menu/xonotic/dialog_settings_input.c:62 +msgid "Use joystick input" +msgstr "Gebruik joystick input" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:65 +#: qcsrc/menu/xonotic/dialog_settings_input.c:67 +msgid "Turn off OS mouse acceleration" +msgstr "Gebruik joystick input" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:69 +msgid "\"enter console\" also closes" +msgstr "\"console activeren\" sluit deze ook weer" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:5 +msgid "User defined key bind" +msgstr "Keybind van gebruiker" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:42 +msgid "Command when pressed:" +msgstr "Opdracht bij drukken:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:45 +msgid "Command when released:" +msgstr "Opdracht bij loslaten:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:48 +msgid "Save" +msgstr "Opslaan" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:51 +msgid "Cancel" +msgstr "Annuleren" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:26 +msgid "Menu skins:" +msgstr "Menu thema’s:" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:47 +msgid "Show current time" +msgstr "Laat huidige tijd zien" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:49 +msgid "Show current date" +msgstr "Laat huidige datum zien" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:51 +msgid "Show frames per second" +msgstr "Laat frames per seconde zien" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:53 +msgid "Minimize input latency" +msgstr "Minimaliseer input latentie" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:5 +msgid "Advanced settings" +msgstr "Geavanceerde instellingen" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:23 +msgid "Cvar filter:" +msgstr "Cvar filter:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:34 +msgid "Setting:" +msgstr "Cvar" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:42 +msgid "Value:" +msgstr "Waarde:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:56 +msgid "Description:" +msgstr "Omschrijving:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:26 +msgid "Client-side movement prediction" +msgstr "Client beweging voorspelling" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:30 +msgid "Show netgraph" +msgstr "Netwerk grafiek tonen" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:33 +msgid "Network speed:" +msgstr "Netwerk snelheid:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:35 +msgid "56k" +msgstr "56k" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:36 +msgid "ISDN" +msgstr "ISDN" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:37 +msgid "Slow ADSL" +msgstr "Langzaam ADSL" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:38 +msgid "Fast ADSL" +msgstr "Snel ADSL" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:39 +msgid "Broadband" +msgstr "Breedband" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:42 +msgid "Input packets/s:" +msgstr "Inkomende pakketten/s" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:46 +msgid "HTTP downloads:" +msgstr "HTTP downloads:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:49 +msgid "Downloads:" +msgstr "Downloads:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:53 +msgid "Speed (kB/s):" +msgstr "Snelheid (kB/s):" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:57 +msgid "Client UDP port:" +msgstr "Client UDP poort:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:26 +msgid "Resolution:" +msgstr "Resolutie:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:29 +msgid "Font/UI size:" +msgstr "Tekst/UI afmetingen:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:31 +msgid "SZ^Unreadable" +msgstr "SZ^Onleesbaar" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:32 +msgid "SZ^Tiny" +msgstr "SZ^Minuscuul" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:33 +msgid "SZ^Little" +msgstr "SZ^Miniem" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:34 +msgid "SZ^Small" +msgstr "SZ^Klein" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:35 +msgid "SZ^Medium" +msgstr "SZ^Gemiddeld" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:36 +msgid "SZ^Large" +msgstr "SZ^Aanzienlijk" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:37 +msgid "SZ^Huge" +msgstr "SZ^Groot" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:38 +msgid "SZ^Gigantic" +msgstr "SZ^Gigantisch" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:39 +msgid "SZ^Colossal" +msgstr "SZ^Kolossaal" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:42 +msgid "Color depth:" +msgstr "Kleurdiepte:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:45 +msgid "Full screen" +msgstr "Volledig scherm" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:46 +msgid "Vertical Synchronization" +msgstr "Verticale synchronisatie" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:49 +msgid "Use OpenGL 2.0 shaders (GLSL)" +msgstr "Gebruik OpenGL 2.0 shaders (GLSL)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:52 +msgid "Use GLSL to handle color control" +msgstr "Gebruik GLSL voor gamma correctie" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:56 +msgid "Vertex Buffer Objects (VBOs)" +msgstr "Vertex Buffer Objecten (VBOs)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:59 +msgid "VBO^Off" +msgstr "VBO^Uit" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:60 +msgid "Vertices, some Tris (compatible)" +msgstr "Vertices, sommige Tris (compatibel)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:63 +msgid "Vertices" +msgstr "Vertices" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:64 +msgid "Vertices and Triangles" +msgstr "Vertices en Tris" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:67 +msgid "Depth first:" +msgstr "Diepte eerst:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:69 +msgid "DF^Disabled" +msgstr "DF^Uitgeschakeld" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:70 +msgid "DF^World" +msgstr "DF^Wereld" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:71 +msgid "DF^All" +msgstr "DF^Alles" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:75 +msgid "Disable multithreaded OpenGL" +msgstr "Schakel multithreaded OpenGL uit" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:77 +msgid "Wait for GPU to finish each frame" +msgstr "Wacht op GPU voor elk frame" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:80 +msgid "Brightness:" +msgstr "Helderheid:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:83 +msgid "Contrast:" +msgstr "Contrast:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:86 +msgid "Gamma:" +msgstr "Gamma:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:91 +msgid "Contrast boost:" +msgstr "Verhoog contrast:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:96 +msgid "Saturation:" +msgstr "Verzadiging:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:102 +msgid "LIT^Ambient:" +msgstr "LIT^Omgevingslicht" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:105 +msgid "Intensity:" +msgstr "Intensiteit:" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:4 +msgid "Singleplayer" +msgstr "Singleplayer" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:127 +msgid "Instant action! (random map with bots)" +msgstr "Instant actie! (random map met bots)" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:148 +msgid "Start Singleplayer!" +msgstr "Start Singleplayer!" + +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:4 +msgid "Winner" +msgstr "Winnaar" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:5 +msgid "Team Selection" +msgstr "Team Selectie" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:41 +msgid "join 'best' team (auto-select)" +msgstr "aansluiten bij het ‘beste’ team (autoselect)" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:45 +msgid "red" +msgstr "rood" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:46 +msgid "blue" +msgstr "blauw" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:47 +msgid "yellow" +msgstr "geel" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:48 +msgid "pink" +msgstr "roze" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:51 +msgid "spectate" +msgstr "observeren" + +#: qcsrc/menu/xonotic/mainwindow.c:35 qcsrc/menu/xonotic/mainwindow.c:38 +msgid "Do not press this button again!" +msgstr "Druk deze knop niet meer in!" + +#: qcsrc/menu/xonotic/maplist.c:278 +msgid "" +"Huh? Can't play this (m is NULL). Refiltering so this won't happen again.\n" +msgstr "" +"He? Kan (m is NULL) niet spelen. Opnieuw filteren zodat dit niet weer " +"gebeurt.\n" + +#: qcsrc/menu/xonotic/maplist.c:286 +#, c-format +msgid "%s's Xonotic Server" +msgstr "%s zijn Xonotic Server" + +#: qcsrc/menu/xonotic/maplist.c:291 +msgid "" +"Huh? Can't play this (invalid game type). Refiltering so this won't happen " +"again.\n" +msgstr "" +"He? Kan (ongeldige spel modus) niet spelen. Opnieuw filteren zodat dit niet " +"weer gebeurt.\n" + +#: qcsrc/menu/xonotic/playermodel.c:174 +msgid "<no model found>" +msgstr "<geen model gevonden>" + +#: qcsrc/menu/xonotic/serverlist.c:185 +msgid "Remove" +msgstr "Verwijderen" + +#: qcsrc/menu/xonotic/serverlist.c:187 +msgid "Bookmark" +msgstr "Bookmark" + +#: qcsrc/menu/xonotic/serverlist.c:527 +msgid "Ping" +msgstr "Ping" + +#: qcsrc/menu/xonotic/serverlist.c:528 +msgid "Host name" +msgstr "Server naam" + +#: qcsrc/menu/xonotic/serverlist.c:529 +msgid "Map" +msgstr "Map" + +#: qcsrc/menu/xonotic/serverlist.c:530 +msgid "Type" +msgstr "Type" + +#: qcsrc/menu/xonotic/serverlist.c:531 +msgid "Players" +msgstr "Spelers" + +#: qcsrc/menu/xonotic/skinlist.c:105 +msgid "<TITLE>" +msgstr "<TITEL>" + +#: qcsrc/menu/xonotic/skinlist.c:106 +msgid "<AUTHOR>" +msgstr "<AUTEUR>" + +#: qcsrc/menu/xonotic/slider_decibels.c:50 +msgid "VOL^OFF" +msgstr "VOL^UIT" + +#: qcsrc/menu/xonotic/slider_decibels.c:52 +msgid "VOL^MAX" +msgstr "OL^MAX" + +#: qcsrc/menu/xonotic/slider_decibels.c:53 +#, c-format +msgid "%s dB" +msgstr "%s dB" + +#: qcsrc/menu/xonotic/slider_resolution.c:65 +#, c-format +msgid "%dx%d" +msgstr "%dx%d" + +#: qcsrc/menu/xonotic/util.qc:270 +#, c-format +msgid "Received HTTP request data for an invalid id %d.\n" +msgstr "HTTP verzoek ontvangen voor ongeldig id %d.\n" + +#: qcsrc/menu/xonotic/util.qc:285 +#, c-format +msgid "error receiving update notification: status is %d\n" +msgstr "fout bij ontvangen update melding: status is %d\n" + +#: qcsrc/menu/xonotic/util.qc:290 +msgid "error: received HTML instead of an update notification\n" +msgstr "fout: HTML ontvangen in plaats van update melding\n" + +#: qcsrc/menu/xonotic/util.qc:295 +msgid "error: received carriage returns from update notification server\n" +msgstr "fout: enters ontvangen van update meldingsserver" + +#: qcsrc/menu/xonotic/util.qc:316 +#, c-format +msgid "" +"Update can be downloaded at:\n" +"%s\n" +msgstr "" +"Update kan gedownload worden bij:\n" +"%s\n" + +#: qcsrc/menu/xonotic/util.qc:337 +msgid "Autogenerating mapinfo for newly added maps..." +msgstr "Automatisch map info aanmaken voor nieuwe maps..." + +#: qcsrc/menu/xonotic/util.qc:367 +#, c-format +msgid "^1%s TEST BUILD" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:432 +#, c-format +msgid "Update to %s now!" +msgstr "Update nu naar %s!" + +#: qcsrc/menu/xonotic/util.qc:501 +msgid "" +"^1ERROR: Texture compression is required but not supported.\n" +"^1Expect visual problems.\n" +msgstr "" +"^1ERROR: Textuurcompressie is nodig maar niet ondersteund.\n" +"^1Verwacht grafische problemen.\n" + +#: qcsrc/menu/xonotic/util.qc:523 +msgid "Arena" +msgstr "Arena" + +#: qcsrc/menu/xonotic/util.qc:524 +msgid "Assault" +msgstr "Assault" + +#: qcsrc/menu/xonotic/util.qc:525 +msgid "Capture The Flag" +msgstr "Capture The Flag" + +#: qcsrc/menu/xonotic/util.qc:526 +msgid "Clan Arena" +msgstr "Clan Arena" + +#: qcsrc/menu/xonotic/util.qc:527 +msgid "Deathmatch" +msgstr "Deathmatch" + +#: qcsrc/menu/xonotic/util.qc:528 +msgid "Domination" +msgstr "Domination" + +#: qcsrc/menu/xonotic/util.qc:529 +msgid "Freeze Tag" +msgstr "Freeze Tag" + +#: qcsrc/menu/xonotic/util.qc:530 +msgid "Keepaway" +msgstr "Keepaway" + +#: qcsrc/menu/xonotic/util.qc:531 +msgid "Key Hunt" +msgstr "Key Hunt" + +#: qcsrc/menu/xonotic/util.qc:532 +msgid "Last Man Standing" +msgstr "Last Man Standing" + +#: qcsrc/menu/xonotic/util.qc:533 +msgid "Nexball" +msgstr "Nexball" + +#: qcsrc/menu/xonotic/util.qc:534 +msgid "Onslaught" +msgstr "Onslaught" + +#: qcsrc/menu/xonotic/util.qc:535 +msgid "Race" +msgstr "Race" + +#: qcsrc/menu/xonotic/util.qc:536 +msgid "Race CTS" +msgstr "Race CTS" + +#: qcsrc/menu/xonotic/util.qc:537 +msgid "Runematch" +msgstr "Runematch" + +#: qcsrc/menu/xonotic/util.qc:538 +msgid "Team Deathmatch" +msgstr "Team Deathmatch" + +#: qcsrc/menu/xonotic/util.qc:557 +#, c-format +msgid "@!#%'n Tuba Throwing" +msgstr "@!#%'n Tuba Smijten" + +#: qcsrc/menu/xonotic/util.qc:577 qcsrc/menu/xonotic/util.qc:593 +#: qcsrc/menu/xonotic/util.qc:602 qcsrc/menu/xonotic/util.qc:610 +#: qcsrc/menu/xonotic/util.qc:622 +msgid "Default" +msgstr "Standaard" + +#: qcsrc/menu/xonotic/util.qc:588 +msgid "Use default" +msgstr "Gebruik standaard" + +#: qcsrc/menu/xonotic/util.qc:608 +msgid "Team Color:" +msgstr "Team Kleur:" + +#: qcsrc/menu/xonotic/util.qh:47 +msgid "Enable panel" +msgstr "Activeer paneel" + +#: qcsrc/server/w_crylink.qc:2 +msgid "Crylink" +msgstr "Crylink" + +#: qcsrc/server/w_crylink.qc:666 +#, c-format +msgid "%s succeeded at self-destructing themself with the Crylink" +msgstr "" + +#: qcsrc/server/w_crylink.qc:671 +#, c-format +msgid "%s could not hide from %s's Crylink" +msgstr "" + +#: qcsrc/server/w_crylink.qc:673 +#, c-format +msgid "%s was too close to %s's Crylink" +msgstr "" + +#: qcsrc/server/w_crylink.qc:675 +#, c-format +msgid "%s took a close look at %s's Crylink" +msgstr "" + +#: qcsrc/server/w_electro.qc:2 +msgid "Electro" +msgstr "Electro" + +#: qcsrc/server/w_electro.qc:574 +#, c-format +msgid "%s could not remember where they put plasma" +msgstr "" + +#: qcsrc/server/w_electro.qc:576 +#, c-format +msgid "%s played with plasma" +msgstr "" + +#: qcsrc/server/w_electro.qc:583 +#, c-format +msgid "%s just noticed %s's blue ball" +msgstr "" + +#: qcsrc/server/w_electro.qc:585 +#, c-format +msgid "%s got in touch with %s's blue ball" +msgstr "" + +#: qcsrc/server/w_electro.qc:590 +#, c-format +msgid "%s felt the electrifying air of %s's combo" +msgstr "" + +#: qcsrc/server/w_electro.qc:592 +#, c-format +msgid "%s got too close to %s's blue beam" +msgstr "" + +#: qcsrc/server/w_electro.qc:594 +#, c-format +msgid "%s was blasted by %s's blue beam" +msgstr "" + +#: qcsrc/server/w_fireball.qc:2 +msgid "Fireball" +msgstr "Fireball" + +#: qcsrc/server/w_fireball.qc:417 +#, c-format +msgid "%s forgot about some firemine" +msgstr "" + +#: qcsrc/server/w_fireball.qc:419 qcsrc/server/w_hlac.qc:240 +#, c-format +msgid "%s should have used a smaller gun" +msgstr "" + +#: qcsrc/server/w_fireball.qc:426 +#, c-format +msgid "%s tried to catch %s's firemine" +msgstr "" + +#: qcsrc/server/w_fireball.qc:428 +#, c-format +msgid "%s fatefully ignored %s's firemine" +msgstr "" + +#: qcsrc/server/w_fireball.qc:435 +#, c-format +msgid "%s could not hide from %s's fireball" +msgstr "" + +#: qcsrc/server/w_fireball.qc:437 +#, c-format +msgid "%s saw the pretty lights of %s's fireball" +msgstr "" + +#: qcsrc/server/w_fireball.qc:440 +#, c-format +msgid "%s got too close to %s's fireball" +msgstr "" + +#: qcsrc/server/w_fireball.qc:442 +#, c-format +msgid "%s tasted %s's fireball" +msgstr "" + +#: qcsrc/server/w_grenadelauncher.qc:2 +msgid "Mortar" +msgstr "Mortar" + +#: qcsrc/server/w_grenadelauncher.qc:383 +#, c-format +msgid "%s tried out his own grenade" +msgstr "" + +#: qcsrc/server/w_grenadelauncher.qc:385 +#, c-format +msgid "%s detonated" +msgstr "" + +#: qcsrc/server/w_grenadelauncher.qc:391 +#, c-format +msgid "%s didn't see %s's grenade" +msgstr "" + +#: qcsrc/server/w_grenadelauncher.qc:393 +#, c-format +msgid "%s almost dodged %s's grenade" +msgstr "" + +#: qcsrc/server/w_grenadelauncher.qc:395 +#, c-format +msgid "%s ate %s's grenade" +msgstr "" + +#: qcsrc/server/w_hagar.qc:2 +msgid "Hagar" +msgstr "Hagar" + +#: qcsrc/server/w_hagar.qc:395 qcsrc/server/w_seeker.qc:655 +#, c-format +msgid "%s played with tiny rockets" +msgstr "" + +#: qcsrc/server/w_hagar.qc:399 +#, c-format +msgid "%s hoped %s's missiles wouldn't bounce" +msgstr "" + +#: qcsrc/server/w_hagar.qc:401 qcsrc/server/w_seeker.qc:661 +#, c-format +msgid "%s was pummeled by %s" +msgstr "" + +#: qcsrc/server/w_hlac.qc:2 +msgid "Heavy Laser Assault Cannon" +msgstr "Heavy Laser Assault Cannon" + +#: qcsrc/server/w_hlac.qc:242 +#, c-format +msgid "%s was cut down by %s" +msgstr "" + +#: qcsrc/server/w_hook.qc:2 +msgid "Grappling Hook" +msgstr "Grappling Hook" + +#: qcsrc/server/w_hook.qc:266 qcsrc/server/w_porto.qc:296 +#, c-format +msgid "%s did the impossible" +msgstr "" + +#: qcsrc/server/w_hook.qc:268 +#, c-format +msgid "%s has run into %s's gravity bomb" +msgstr "" + +#: qcsrc/server/w_laser.qc:2 +msgid "Laser" +msgstr "Laser" + +#: qcsrc/server/w_laser.qc:311 +#, c-format +msgid "%s lasered themself to hell" +msgstr "" + +#: qcsrc/server/w_laser.qc:315 +#, c-format +msgid "%s was cut in half by %s's gauntlet" +msgstr "" + +#: qcsrc/server/w_laser.qc:317 +#, c-format +msgid "%s was lasered to death by %s" +msgstr "" + +#: qcsrc/server/w_minelayer.qc:2 +msgid "Mine Layer" +msgstr "Mine Layer" + +#: qcsrc/server/w_minelayer.qc:523 qcsrc/server/w_rocketlauncher.qc:501 +#, c-format +msgid "%s exploded" +msgstr "" + +#: qcsrc/server/w_minelayer.qc:527 +#, c-format +msgid "%s got too close to %s's mine" +msgstr "" + +#: qcsrc/server/w_minelayer.qc:529 +#, c-format +msgid "%s almost dodged %s's mine" +msgstr "" + +#: qcsrc/server/w_minelayer.qc:531 +#, c-format +msgid "%s stepped on %s's mine" +msgstr "" + +#: qcsrc/server/w_minstanex.qc:2 +msgid "MinstaNex" +msgstr "MinstaNex" + +#: qcsrc/server/w_minstanex.qc:293 qcsrc/server/w_nex.qc:253 +#: qcsrc/server/w_shotgun.qc:215 qcsrc/server/w_uzi.qc:317 +#, c-format +msgid "%s is now thinking with portals" +msgstr "" + +#: qcsrc/server/w_minstanex.qc:295 qcsrc/server/w_nex.qc:255 +#, c-format +msgid "%s has been vaporized by %s" +msgstr "" + +#: qcsrc/server/w_nex.qc:2 +msgid "Nex" +msgstr "Nex" + +#: qcsrc/server/w_porto.qc:2 +msgid "Port-O-Launch" +msgstr "Port-O-Launch" + +#: qcsrc/server/w_porto.qc:298 +#, c-format +msgid "%s felt %s doing the impossible to him" +msgstr "" + +#: qcsrc/server/w_rifle.qc:2 +msgid "Rifle" +msgstr "" + +#: qcsrc/server/w_rifle.qc:233 +#, c-format +msgid "%s shot themself automatically" +msgstr "" + +#: qcsrc/server/w_rifle.qc:235 +#, c-format +msgid "%s sniped themself somehow" +msgstr "" + +#: qcsrc/server/w_rifle.qc:242 +#, c-format +msgid "%s failed to hide from %s's bullet hail" +msgstr "" + +#: qcsrc/server/w_rifle.qc:244 +#, c-format +msgid "%s died in %s's bullet hail" +msgstr "" + +#: qcsrc/server/w_rifle.qc:251 +#, c-format +msgid "%s failed to hide from %s's rifle" +msgstr "" + +#: qcsrc/server/w_rifle.qc:256 +#, c-format +msgid "%s got hit in the head by %s" +msgstr "" + +#: qcsrc/server/w_rifle.qc:258 qcsrc/server/w_uzi.qc:321 +#, c-format +msgid "%s was sniped by %s" +msgstr "" + +#: qcsrc/server/w_rocketlauncher.qc:2 +msgid "Rocket Launcher" +msgstr "Rocket Launcher" + +#: qcsrc/server/w_rocketlauncher.qc:505 +#, c-format +msgid "%s got too close to %s's rocket" +msgstr "" + +#: qcsrc/server/w_rocketlauncher.qc:507 +#, c-format +msgid "%s almost dodged %s's rocket" +msgstr "" + +#: qcsrc/server/w_rocketlauncher.qc:509 +#, c-format +msgid "%s ate %s's rocket" +msgstr "" + +#: qcsrc/server/w_seeker.qc:2 +msgid "T.A.G. Seeker" +msgstr "T.A.G. Seeker" + +#: qcsrc/server/w_seeker.qc:659 +#, c-format +msgid "%s was tagged by %s" +msgstr "" + +#: qcsrc/server/w_shotgun.qc:2 +msgid "Shotgun" +msgstr "Shotgun" + +#: qcsrc/server/w_shotgun.qc:219 +#, c-format +msgid "%2$s ^7slapped %1$s ^7around a bit with a large ^2shotgun" +msgstr "" + +#: qcsrc/server/w_shotgun.qc:221 +#, c-format +msgid "%s was gunned by %s" +msgstr "" + +#: qcsrc/server/w_tuba.qc:2 +#, c-format +msgid "@!#%'n Tuba" +msgstr "@!#%'n Tuba" + +#: qcsrc/server/w_tuba.qc:252 +#, c-format +msgid "%s hurt his own ears with the @!#%%'n Tuba" +msgstr "" + +#: qcsrc/server/w_tuba.qc:256 +#, c-format +msgid "%s died of %s's great playing on the @!#%%'n Tuba" +msgstr "" + +#: qcsrc/server/w_uzi.qc:2 +msgid "Machine Gun" +msgstr "Machine Gun" + +#: qcsrc/server/w_uzi.qc:323 +#, c-format +msgid "%s was riddled full of holes by %s" +msgstr "" + +#, fuzzy +#~ msgid "Damage & water blur" +#~ msgstr "Schadeonscherpte" + +#, fuzzy +#~ msgid "Powerup sharpen" +#~ msgstr "Powerups paneel" + +#~ msgid "Speedometer" +#~ msgstr "Snelheidsmeter" + +#~ msgid "qu/s (hidden)" +#~ msgstr "qu/s (verborgen)" + +#~ msgid "Show accelerometer" +#~ msgstr "Laat versnellingsmeter zien" + +#~ msgid "Accelerometer scale:" +#~ msgstr "Versnellingsmeter schaal" + +#~ msgid "Sniper Rifle" +#~ msgstr "Sniper Rifle" + +#~ msgid "Waypoint settings:" +#~ msgstr "Wegwijzer instellingen" + +#~ msgid "%d/%d" +#~ msgstr "%d/%d" diff --git a/menu.dat.pot b/menu.dat.pot new file mode 100644 index 0000000000..f300f549fa --- /dev/null +++ b/menu.dat.pot @@ -0,0 +1,2744 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-12-25 22:57+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:4 +msgid "Welcome" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:33 +msgid "" +"Welcome to Xonotic, please select your language preference and enter your " +"player name to get started. You can change these options later through the " +"menu system." +msgstr "" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:38 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:35 +msgid "Text language:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:47 +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:39 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:40 +msgid "Name:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:69 +msgid "Save settings" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:4 +msgid "Ammo Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:22 +msgid "Ammunition display:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:25 +msgid "Show only current ammo type" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:28 +msgid "Align icon:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:29 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:40 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:40 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:36 +msgid "Left" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:41 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:41 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:38 +msgid "Right" +msgstr "" + +#: qcsrc/menu/xonotic/mainwindow.c:35 qcsrc/menu/xonotic/mainwindow.c:38 +msgid "Do not press this button again!" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:276 +#, c-format +msgid "Received HTTP request data for an invalid id %d.\n" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:291 +#, c-format +msgid "error receiving update notification: status is %d\n" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:296 +msgid "error: received HTML instead of an update notification\n" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:301 +msgid "error: received carriage returns from update notification server\n" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:322 +#, c-format +msgid "" +"Update can be downloaded at:\n" +"%s\n" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:351 +msgid "Autogenerating mapinfo for newly added maps..." +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:381 +#, c-format +msgid "^1%s TEST BUILD" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:439 +#, c-format +msgid "Update to %s now!" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:524 +msgid "" +"^1ERROR: Texture compression is required but not supported.\n" +"^1Expect visual problems.\n" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:546 +msgid "Arena" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:547 +msgid "Assault" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:548 +msgid "Capture The Flag" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:549 +msgid "Clan Arena" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:550 +msgid "Deathmatch" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:551 +msgid "Domination" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:552 +msgid "Freeze Tag" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:553 +msgid "Keepaway" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:554 +msgid "Key Hunt" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:555 +msgid "Last Man Standing" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:556 +msgid "Nexball" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:557 +msgid "Onslaught" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:558 +msgid "Race" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:559 +msgid "Race CTS" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:560 +msgid "Runematch" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:561 +msgid "Team Deathmatch" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:580 +#, c-format +msgid "@!#%'n Tuba Throwing" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:598 qcsrc/menu/xonotic/dialog_hudsetup_exit.c:23 +msgid "Background:" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:600 qcsrc/menu/xonotic/util.qc:616 +#: qcsrc/menu/xonotic/util.qc:625 qcsrc/menu/xonotic/util.qc:633 +#: qcsrc/menu/xonotic/util.qc:645 +msgid "Default" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:601 qcsrc/menu/xonotic/util.qc:617 +#: qcsrc/menu/xonotic/util.qc:634 qcsrc/menu/xonotic/dialog_hudsetup_exit.c:25 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:37 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:52 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:91 +msgid "Disable" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:606 qcsrc/menu/xonotic/dialog_hudsetup_exit.c:30 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:77 +msgid "Color:" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:611 +msgid "Use default" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:614 qcsrc/menu/xonotic/dialog_hudsetup_exit.c:35 +msgid "Border size:" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:623 qcsrc/menu/xonotic/dialog_hudsetup_exit.c:43 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:82 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:32 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:156 +msgid "Alpha:" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:631 +msgid "Team Color:" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:640 qcsrc/menu/xonotic/dialog_hudsetup_exit.c:58 +msgid "Test team color in configure mode" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:643 qcsrc/menu/xonotic/dialog_hudsetup_exit.c:61 +msgid "Padding:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:4 +#: qcsrc/menu/xonotic/dialog_settings.c:19 +msgid "Video" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:26 +msgid "Resolution:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:29 +msgid "Font/UI size:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:31 +msgid "SZ^Unreadable" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:32 +msgid "SZ^Tiny" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:33 +msgid "SZ^Little" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:34 +msgid "SZ^Small" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:35 +msgid "SZ^Medium" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:36 +msgid "SZ^Large" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:37 +msgid "SZ^Huge" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:38 +msgid "SZ^Gigantic" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:39 +msgid "SZ^Colossal" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:42 +msgid "Color depth:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:45 +msgid "Full screen" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:46 +msgid "Vertical Synchronization" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:48 +msgid "Use OpenGL 2.0 shaders (GLSL)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:51 +msgid "Use GLSL to handle color control" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:55 +msgid "Vertex Buffer Objects (VBOs)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:58 +msgid "VBO^Off" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:59 +msgid "Vertices, some Tris (compatible)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:62 +msgid "Vertices" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:63 +msgid "Vertices and Triangles" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:66 +msgid "Depth first:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:68 +msgid "DF^Disabled" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:69 +msgid "DF^World" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:70 +msgid "DF^All" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:73 +msgid "Wait for GPU to finish each frame" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:76 +msgid "Brightness:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:79 +msgid "Contrast:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:82 +msgid "Gamma:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:87 +msgid "Contrast boost:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:92 +msgid "Saturation:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:98 +msgid "LIT^Ambient:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:101 +msgid "Intensity:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:105 +#: qcsrc/menu/xonotic/dialog_settings_input.c:74 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:175 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:30 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:41 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:195 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:197 +msgid "Apply immediately" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:5 +msgid "Advanced settings" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:23 +msgid "Cvar filter:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:24 +#: qcsrc/menu/xonotic/dialog_settings_input.c:41 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:29 +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:33 +msgid "Clear" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:34 +msgid "Setting:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:38 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:257 +msgid "Type:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:42 +msgid "Value:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:56 +msgid "Description:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:61 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:57 +#: qcsrc/menu/xonotic/dialog_credits.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:35 +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:89 +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:277 +msgid "OK" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:4 +msgid "Powerups Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:22 +msgid "Enable status bar" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:24 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:24 +msgid "Status bar alignment:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:42 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:42 +msgid "Inward" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:43 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:43 +msgid "Outward" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:37 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:37 +msgid "Icon alignment:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:45 +msgid "Flip strength and shield positions" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:4 +msgid "Physics Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:21 +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:21 +msgid "Panel disabled" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:23 +msgid "Panel enabled" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:24 +msgid "Panel enabled even observing" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:25 +msgid "Panel enabled only in Race/CTS" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:31 +msgid "Status bar" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:48 +msgid "Left align" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:34 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:52 +msgid "Right align" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:35 +msgid "Inward align" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:36 +msgid "Outward align" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:40 +msgid "Flip speed/acceleration positions" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:44 +msgid "Speed:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:45 +msgid "Include vertical speed" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:56 +msgid "Speed unit:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:58 +msgid "qu/s" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:59 +msgid "m/s" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:60 +msgid "km/h" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:61 +msgid "mph" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:62 +msgid "knots" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:64 +msgid "Show" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:67 +msgid "Top speed" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:73 +msgid "Acceleration:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:74 +msgid "Include vertical acceleration" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:6 +msgid "Weapon settings" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:29 +msgid "Weapon priority list:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:34 +msgid "Up" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:37 +msgid "Down" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:41 +msgid "Use priority list for weapon cycling" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:43 +msgid "Auto switch weapons on pickup" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:45 +msgid "Draw 1st person weapon model" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:50 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:37 +msgid "Center" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:55 +msgid "Flip view horizontally" +msgstr "" + +#: qcsrc/menu/xonotic/serverlist.c:185 +msgid "Remove" +msgstr "" + +#: qcsrc/menu/xonotic/serverlist.c:187 +msgid "Bookmark" +msgstr "" + +#: qcsrc/menu/xonotic/serverlist.c:548 +msgid "Ping" +msgstr "" + +#: qcsrc/menu/xonotic/serverlist.c:549 +msgid "Host name" +msgstr "" + +#: qcsrc/menu/xonotic/serverlist.c:550 +msgid "Map" +msgstr "" + +#: qcsrc/menu/xonotic/serverlist.c:551 +msgid "Type" +msgstr "" + +#: qcsrc/menu/xonotic/serverlist.c:552 +msgid "Players" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:5 +msgid "User defined key bind" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:42 +msgid "Command when pressed:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:45 +msgid "Command when released:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:48 +msgid "Save" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:51 +msgid "Cancel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:4 +msgid "Score Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:22 +msgid "Score:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:25 +msgid "Rankings:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:26 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:60 +msgid "Off" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:27 +msgid "And me" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:28 +msgid "Pure" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:4 +#: qcsrc/menu/xonotic/dialog_settings.c:18 +msgid "Input" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:26 +msgid "Key bindings:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:31 +msgid "Change key..." +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:35 +msgid "Edit..." +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:46 +msgid "Sensitivity:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:51 +msgid "UI mouse speed:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:55 +msgid "Mouse filter" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:57 +msgid "Invert mouse" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:60 +#: qcsrc/menu/xonotic/dialog_settings_input.c:62 +msgid "Use joystick input" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:65 +#: qcsrc/menu/xonotic/dialog_settings_input.c:67 +msgid "Turn off OS mouse acceleration" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:69 +msgid "\"enter console\" also closes" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:72 +msgid "Holding jump key keeps jumping" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:4 +msgid "Vote Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:22 +msgid "Alpha after voting:" +msgstr "" + +#: qcsrc/menu/xonotic/slider_decibels.c:50 +msgid "VOL^OFF" +msgstr "" + +#: qcsrc/menu/xonotic/slider_decibels.c:52 +msgid "VOL^MAX" +msgstr "" + +#: qcsrc/menu/xonotic/slider_decibels.c:53 +#, c-format +msgid "%s dB" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_news.c:4 +msgid "News" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_news.c:18 +msgid "http://www.xonotic.org/team/blog/" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_quit.c:4 +msgid "Quit" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_quit.c:17 +msgid "Are you sure you want to quit?" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_quit.c:20 +msgid "Yes" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_quit.c:21 +msgid "No" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_modicons.c:4 +msgid "Mod Icons Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:4 +msgid "Panel HUD Setup" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:21 +msgid "Panel background defaults:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:50 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:89 +msgid "Team color:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:68 +msgid "HUD Dock:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:70 +msgid "DOCK^Disabled" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:71 +msgid "DOCK^Small" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:72 +msgid "DOCK^Medium" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:73 +msgid "DOCK^Large" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:96 +msgid "Grid settings:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:99 +msgid "Snap panels to grid" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:102 +msgid "Grid size:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:103 +msgid "X:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:109 +msgid "Y:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:117 +msgid "Exit setup" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:4 +msgid "Radar Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:22 +msgid "Panel enabled in teamgames" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:23 +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:23 +msgid "Panel always enabled" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:29 +msgid "Radar:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:36 +msgid "Rotation:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:38 +msgid "Forward" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:39 +msgid "West" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:40 +msgid "South" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:41 +msgid "East" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:42 +msgid "North" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:46 +msgid "Scale:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:50 +msgid "Zoom mode:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:52 +msgid "Zoomed in" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:53 +msgid "Zoomed out" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:54 +msgid "Always zoomed" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:55 +msgid "Never zoomed" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:4 +#: qcsrc/menu/xonotic/dialog_settings.c:21 +msgid "Audio" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:27 +msgid "Master:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:33 +msgid "Music:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:41 +msgid "VOL^Ambient:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:48 +msgid "Info:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:55 +msgid "Items:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:62 +msgid "Pain:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:69 +msgid "Player:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:76 +msgid "Shots:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:83 +msgid "Voice:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:91 +msgid "Weapons:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:98 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:158 +msgid "Frequency:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:100 +msgid "8 kHz" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:101 +msgid "11.025 kHz" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:102 +msgid "16 kHz" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:103 +msgid "22.05 kHz" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:104 +msgid "24 kHz" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:105 +msgid "32 kHz" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:106 +msgid "44.1 kHz" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:107 +msgid "48 kHz" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:110 +msgid "Channels:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:112 +msgid "Mono" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:113 +msgid "Stereo" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:114 +msgid "2.1" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:115 +msgid "4" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:116 +msgid "5" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:117 +msgid "5.1" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:118 +msgid "6.1" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:119 +msgid "7.1" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:123 +msgid "Swap Stereo" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:127 +msgid "Headphone friendly mode" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:131 +msgid "New style sound attenuation" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:133 +msgid "Spatial voices:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:134 +msgid "VOCS^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:135 +msgid "VOCS^Taunts" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:136 +msgid "VOCS^All" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:139 +msgid "Taunt range:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:142 +msgid "RNG^Very short" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:143 +msgid "RNG^Short" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:144 +msgid "RNG^Normal" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:145 +msgid "RNG^Long" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:146 +msgid "RNG^Full" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:153 +msgid "Automatic taunts" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:162 +msgid "Time warning:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:164 +msgid "WRN^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:165 +msgid "1 minute" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:166 +msgid "5 minutes" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:167 +msgid "WRN^Both" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:170 +msgid "Hit indicator" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:172 +msgid "Menu sounds" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_credits.c:5 +msgid "Credits" +msgstr "" + +#: qcsrc/menu/xonotic/slider_resolution.c:65 +#, c-format +msgid "%dx%d" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:6 +msgid "Advanced server settings" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:25 +msgid "Game settings:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:28 +msgid "Allow spectating" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:31 +msgid "Spawn shield:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:36 +msgid "Game speed:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:40 +msgid "Teamplay settings:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:43 +msgid "Friendly fire scale:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:47 +msgid "Virtual friendly fire (effect only)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:50 +msgid "Friendly fire penalty:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:54 +msgid "Virtual penalty (effect only)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:57 +msgid "Teams:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:66 +msgid "Map voting:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:68 +msgid "No voting" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:69 +msgid "2 choices" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:70 +msgid "3 choices" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:71 +msgid "4 choices" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:72 +msgid "5 choices" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:73 +msgid "6 choices" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:74 +msgid "7 choices" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:75 +msgid "8 choices" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:76 +msgid "9 choices" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:79 +msgid "Simple majority wins vcall" +msgstr "" + +#: qcsrc/menu/xonotic/skinlist.c:105 +msgid "<TITLE>" +msgstr "" + +#: qcsrc/menu/xonotic/skinlist.c:106 +msgid "<AUTHOR>" +msgstr "" + +#: qcsrc/menu/xonotic/skinlist.c:163 qcsrc/common/mapinfo.qc:1097 +#, c-format +msgid "%s: %s" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:4 +msgid "Join" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:28 +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:32 +msgid "Filter:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:36 +msgid "SRVS^Empty" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:40 +msgid "SRVS^Full" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:44 +msgid "Pause" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:56 +msgid "Address:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:67 +msgid "Info..." +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:320 +msgid "Join!" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:4 +msgid "Weapons Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:24 +msgid "Fade out after:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:26 +msgid "Never" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:28 +#, c-format +msgid "%ds" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:32 +msgid "Fade effect:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:35 +msgid "EF^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:36 +msgid "Slide" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:37 +msgid "Alpha" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:38 +msgid "EF^Both" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:42 +msgid "Weapon icons:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:45 +msgid "Show only owned weapons" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:48 +msgid "Show weapon ID as:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:49 +msgid "SHOWAS^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:50 +msgid "Number" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:51 +msgid "Bind" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:54 +msgid "Show Accuracy" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:55 +msgid "Show Ammo" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:58 +msgid "Ammo bar color:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:64 +msgid "Ammo bar alpha:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:4 +msgid "Singleplayer" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:116 +msgid "Instant action! (random map with bots)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:123 +#: qcsrc/menu/xonotic/campaign.c:284 +msgid "???" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:137 +msgid "Start Singleplayer!" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:5 +msgid "Map Information" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "Full item placement" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "MinstaGib only" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:78 +msgid "Title:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:84 +msgid "Author:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:90 +msgid "Features:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:95 +msgid "Game types:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:118 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:317 +msgid "Close" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:121 +msgid "MAP^Play" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:4 +msgid "Timer Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:22 +msgid "Timer:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:25 +msgid "Show elapsed time" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings.c:4 +msgid "Settings" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings.c:20 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:4 +msgid "Effects" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings.c:22 +#: qcsrc/menu/xonotic/dialog_settings_network.c:4 +msgid "Network" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings.c:23 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:4 +msgid "Misc" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:4 +msgid "Multiplayer" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:18 +msgid "Servers" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:19 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:5 +msgid "Create" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:20 +msgid "Demos" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:5 +msgid "Player Setup" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:4 +msgid "Pressed Keys Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:22 +msgid "Panel enabled when spectating" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:30 +msgid "Forced aspect:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:34 +msgid "Game type:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:46 +msgid "Match settings:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:49 +msgid "Time limit:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:53 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:61 +msgid "Use map specified default" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:56 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:155 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:156 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:157 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:161 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:162 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:163 +msgid "Point limit:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:64 +msgid "Player slots:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:67 +msgid "Number of bots:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:71 +msgid "Bot skill:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:74 +msgid "Botlike" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:75 +msgid "Beginner" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:76 +msgid "You will win" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:77 +msgid "You can win" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:78 +msgid "You might win" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:79 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:62 +msgid "Advanced" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:80 +msgid "Expert" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:81 +msgid "Pro" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:82 +msgid "Assassin" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:83 +msgid "Unhuman" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:84 +msgid "Godlike" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:88 +msgid "Mutators..." +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:97 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:68 +msgid "Advanced settings..." +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:104 +msgid "Map list:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:110 +msgid "Select all" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:113 +msgid "Select none" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:119 +msgid "Start Multiplayer!" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:154 +msgid "Capture limit:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:158 +msgid "Lives:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:159 +msgid "Laps:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:160 +msgid "Goals:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:164 +msgid "Frag limit:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:5 +msgid "Waypoints" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:23 +msgid "Show base waypoints" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:25 +msgid "Waypoint scale:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:29 +msgid "Waypoint alpha:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:33 +msgid "Show names above players" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:4 +msgid "Health/Armor Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:45 +msgid "Flip health and armor positions" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:26 +msgid "Menu skins:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:47 +msgid "Show current time" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:49 +msgid "Show current date" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:51 +msgid "Show frames per second" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:53 +msgid "Minimize input latency" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:59 +msgid "Menu Tooltips:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:61 +msgid "Standard" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:26 +msgid "Client-side movement prediction" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:30 +msgid "Show netgraph" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:33 +msgid "Network speed:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:35 +msgid "56k" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:36 +msgid "ISDN" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:37 +msgid "Slow ADSL" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:38 +msgid "Fast ADSL" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:39 +msgid "Broadband" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:42 +msgid "Input packets/s:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:46 +msgid "HTTP downloads:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:49 +msgid "Downloads:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:53 +msgid "Speed (kB/s):" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:57 +msgid "Client UDP port:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:4 +msgid "Engine Info Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:22 +msgid "Engine info:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:25 +msgid "Use an averaging algorithm for fps" +msgstr "" + +#: qcsrc/menu/xonotic/campaign.c:285 +#, c-format +msgid "Level %d: %s" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:5 +msgid "Server Information" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:115 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:116 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:186 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:192 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:202 +msgid "N/A" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:161 +#, c-format +msgid "%d/%d, %d free player slots" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:175 +msgid "Official settings" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:175 +#, c-format +msgid "%d modified settings" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:200 +msgid "N/A (can't connect)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:208 +msgid "not supported (can't connect)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:210 +msgid "not supported (won't encrypt)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:214 +msgid "supported (will encrypt)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:216 +msgid "supported (won't encrypt)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:220 +msgid "requested (will encrypt)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:222 +msgid "requested (won't encrypt)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:226 +msgid "required (can't connect)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:228 +msgid "required (will encrypt)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:249 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:272 +msgid "Players:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:262 +msgid "Map:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:267 +msgid "Gameplay:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:277 +msgid "Bots:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:282 +msgid "Mod:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:287 +msgid "Version:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:292 +msgid "Ping:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:298 +msgid "CA:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:304 +msgid "Key:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:310 +msgid "Encryption:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:38 +msgid "Quality preset:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:41 +msgid "PRE^OMG!" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:42 +msgid "PRE^Low" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:43 +msgid "PRE^Medium" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:44 +msgid "PRE^Normal" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:45 +msgid "PRE^High" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:46 +msgid "PRE^Ultra" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:48 +msgid "PRE^Ultimate" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:52 +msgid "Geometry detail:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:54 +msgid "DET^Lowest" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:55 +msgid "DET^Low" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:56 +msgid "DET^Normal" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:57 +msgid "DET^Good" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:58 +msgid "DET^Best" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:59 +msgid "DET^Insane" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:62 +msgid "Antialiasing:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:64 +msgid "AA^Disabled" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:65 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:106 +msgid "2x" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:66 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:107 +msgid "4x" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:70 +msgid "High-quality frame buffer" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:73 +msgid "Texture resolution:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:76 +msgid "RES^Leet" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:77 +msgid "RES^Lowest" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:78 +msgid "RES^Low" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:79 +msgid "RES^Normal" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:80 +msgid "RES^Good" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:81 +msgid "RES^Best" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:94 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:97 +msgid "Avoid lossy texture compression" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:103 +msgid "Anisotropy:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:105 +msgid "ANISO^Disabled" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:108 +msgid "8x" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:109 +msgid "16x" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:113 +msgid "Particle quality:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:116 +msgid "Particle distance:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:120 +msgid "Decals" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:121 +msgid "Decals on models" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:125 +msgid "Distance:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:131 +msgid "Time:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:137 +msgid "Use lightmaps" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:138 +msgid "Deluxe mapping" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:140 +msgid "Gloss" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:143 +msgid "Offset mapping" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:145 +msgid "Relief mapping" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:148 +msgid "Reflections:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:151 +msgid "Blurred" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:152 +msgid "REFL^Good" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:153 +msgid "Sharp" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:158 +msgid "Show surfaces" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:160 +msgid "No dynamic lighting" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:162 +msgid "Flash blend approximation" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:164 +msgid "Realtime dynamic lighting" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:165 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:169 +msgid "Shadows" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:168 +msgid "Realtime world lighting" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:173 +msgid "Use normal maps" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:175 +msgid "Soft shadows" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:178 +msgid "Coronas" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:179 +msgid "Use Occlusion Queries" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:181 +msgid "High Dynamic Range (HDR)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:185 +msgid "Motion blur:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:190 +msgid "Blur and sharpen postprocessing" +msgstr "" + +#: qcsrc/menu/xonotic/cvarlist.c:85 +msgid "will be saved to config.cfg" +msgstr "" + +#: qcsrc/menu/xonotic/cvarlist.c:87 +msgid "will not be saved" +msgstr "" + +#: qcsrc/menu/xonotic/cvarlist.c:89 +msgid "private" +msgstr "" + +#: qcsrc/menu/xonotic/cvarlist.c:91 +msgid "engine setting" +msgstr "" + +#: qcsrc/menu/xonotic/cvarlist.c:93 +msgid "read only" +msgstr "" + +#: qcsrc/menu/xonotic/playermodel.c:174 +msgid "<no model found>" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:4 +msgid "Chat Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:22 +msgid "Chat entries:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:25 +msgid "Chat size:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:29 +msgid "Chat lifetime:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:33 +msgid "Chat beep sound" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_racetimer.c:4 +msgid "Race Timer Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:4 +msgid "Sandbox Tools" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:19 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:63 +msgid "Model:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:24 +msgid "Spawn" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:25 +msgid "Remove *" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:27 +msgid "Copy *" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:28 +msgid "Paste" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:30 +msgid "Bone:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:35 +msgid "Set * as child" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:36 +msgid "Attach to *" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:38 +msgid "Detach from *" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:41 +msgid "Visual object properties for *:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:43 +msgid "Set skin:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:45 +msgid "Set alpha:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:48 +msgid "Set color main:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:50 +msgid "Set color glow:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:54 +msgid "Set frame:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:58 +msgid "Physical object properties for *:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:60 +msgid "Set material:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:66 +msgid "Set solidity:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:67 +msgid "Non-solid" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:68 +msgid "Solid" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:69 +msgid "Set physics:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:70 +msgid "Static" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:71 +msgid "Movable" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:72 +msgid "Physical" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:74 +msgid "Set scale:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:76 +msgid "Set force:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:80 +msgid "Claim *" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:82 +msgid "* object info" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:83 +msgid "* mesh info" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:84 +msgid "* attachment info" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:85 +msgid "Show help" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_sandboxtools.c:86 +msgid "* is the object you are facing" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:87 +msgid "Force player models to mine" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:90 +msgid "Field of view:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:94 +msgid "View bobbing:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:98 +msgid "Zoom factor:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:102 +msgid "Zoom speed:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:105 +msgid "Weapon settings..." +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:112 +msgid "Crosshair:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:113 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:141 +msgid "Per weapon" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:132 +msgid "Crosshair size:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:136 +msgid "Crosshair alpha:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:140 +msgid "Crosshair color:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:142 +msgid "By health" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:145 +msgid "Custom" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:150 +msgid "Enable center dot" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:153 +msgid "Size:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:160 +msgid "Hit test:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:161 +msgid "HTST^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:162 +msgid "TrueAim" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:163 +msgid "Enemies" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:166 +msgid "Waypoints setup..." +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:171 +msgid "Enter HUD editor" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:176 +msgid "Force models:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:177 +msgid "MDL^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:178 +msgid "MDL^Custom" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:179 +msgid "MDL^All" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:182 +msgid "Disable gore effects" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:184 +msgid "Gibs:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:186 +msgid "GIBS^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:187 +msgid "GIBS^Few" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:188 +msgid "GIBS^Many" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:189 +msgid "GIBS^Lots" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:193 +msgid "Damage splash:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:4 +msgid "Notification Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:22 +msgid "Notifications:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:25 +msgid "Also print notifications to the console" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:28 +msgid "Flip notify order" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:31 +msgid "Entry lifetime:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:35 +msgid "Entry fadetime:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:4 +msgid "Centerprint" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:23 +msgid "Message duration:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:27 +msgid "Fade time:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:31 +msgid "Flip messages order" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:33 +msgid "Text alignment:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:41 +msgid "Font scale:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:4 +msgid "Demo" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:28 +msgid "Record demos while playing" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:43 +msgid "Timedemo" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:46 +msgid "DEMO^Play" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:4 +msgid "Winner" +msgstr "" + +#: qcsrc/menu/xonotic/maplist.c:278 +msgid "" +"Huh? Can't play this (m is NULL). Refiltering so this won't happen again.\n" +msgstr "" + +#: qcsrc/menu/xonotic/maplist.c:286 +#, c-format +msgid "%s's Xonotic Server" +msgstr "" + +#: qcsrc/menu/xonotic/maplist.c:291 +msgid "" +"Huh? Can't play this (invalid game type). Refiltering so this won't happen " +"again.\n" +msgstr "" + +#: qcsrc/menu/xonotic/util.qh:48 +msgid "Enable panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:4 +msgid "Info Messages Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:22 +msgid "Info messages:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:25 +msgid "Flip align" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:5 +msgid "Team Selection" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:41 +msgid "join 'best' team (auto-select)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:45 +msgid "red" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:46 +msgid "blue" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:47 +msgid "yellow" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:48 +msgid "pink" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:51 +msgid "spectate" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:7 +msgid "Mutators" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:33 +msgid "All Weapons Arena" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:35 +msgid "Most Weapons Arena" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:56 +#, c-format +msgid "%s Arena" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:68 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:173 +msgid "Dodging" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:70 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:258 +msgid "MinstaGib" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:261 +msgid "NIX" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:74 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:213 +msgid "Rocket Flying" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:76 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:210 +msgid "Invincible Projectiles" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:80 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:272 +msgid "No start weapons" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:195 +msgid "Low gravity" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:84 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:176 +msgid "Cloaked" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:86 +msgid "Hook" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:88 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:179 +msgid "Midair" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:90 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:182 +msgid "Vampire" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:92 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:216 +msgid "Piñata" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:94 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:219 +msgid "Weapons stay" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:96 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:186 +msgid "Blood loss" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:98 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:207 +msgid "Jet pack" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:100 +msgid "No powerups" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:102 +msgid "Powerups" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:104 +msgid "MUT^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:170 +msgid "Gameplay mutators:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:201 +msgid "Weapon & item mutators:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:204 +msgid "Grappling hook" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:223 +msgid "Weapon arenas:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:226 +msgid "Regular (no arena)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:247 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:264 +msgid "with laser" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:255 +msgid "Special arenas:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:268 +msgid "Most weapons" +msgstr "" + +#: qcsrc/menu/gamecommand.qc:47 +#, c-format +msgid "error: status is %d\n" +msgstr "" + +#: qcsrc/menu/gamecommand.qc:70 +msgid "Usage: menu_cmd command..., where possible commands are:\n" +msgstr "" + +#: qcsrc/menu/gamecommand.qc:71 +msgid " sync - reloads all cvars on the current menu page\n" +msgstr "" + +#: qcsrc/menu/gamecommand.qc:72 +msgid " directmenu ITEM - select a menu item as main item\n" +msgstr "" + +#: qcsrc/menu/gamecommand.qc:185 +msgid "error creating curl handle\n" +msgstr "" + +#: qcsrc/menu/gamecommand.qc:192 +msgid "Invalid command. For a list of supported commands, try menu_cmd help.\n" +msgstr "" + +#: qcsrc/menu/menu.qc:37 +#, c-format +msgid "^4MQC Build information: ^1%s\n" +msgstr "" + +#: qcsrc/menu/item/textslider.c:29 qcsrc/menu/item/textslider.c:31 +msgid "custom" +msgstr "" + +#: qcsrc/menu/item/slider.c:64 +#, c-format +msgid "%d (%s)" +msgstr "" + +#: qcsrc/menu/item/label.c:63 +#, c-format +msgid "NOTE: label text %s too wide for label, condensed by factor %f\n" +msgstr "" + +#: qcsrc/menu/item/listbox.c:300 +#, c-format +msgid "Item %d" +msgstr "" + +#: qcsrc/menu/item/gecko.c:49 +msgid "Browser not initialized!" +msgstr "" + +#: weapons.qc.tmp:1 +msgid "Crylink" +msgstr "" + +#: weapons.qc.tmp:2 +msgid "Heavy Laser Assault Cannon" +msgstr "" + +#: weapons.qc.tmp:3 +msgid "MinstaNex" +msgstr "" + +#: weapons.qc.tmp:4 +msgid "Mortar" +msgstr "" + +#: weapons.qc.tmp:5 +msgid "Laser" +msgstr "" + +#: weapons.qc.tmp:6 +msgid "Nex" +msgstr "" + +#: weapons.qc.tmp:7 +msgid "Grappling Hook" +msgstr "" + +#: weapons.qc.tmp:8 +msgid "Rocket Launcher" +msgstr "" + +#: weapons.qc.tmp:9 +msgid "Port-O-Launch" +msgstr "" + +#: weapons.qc.tmp:10 +msgid "Electro" +msgstr "" + +#: weapons.qc.tmp:11 +msgid "Hagar" +msgstr "" + +#: weapons.qc.tmp:12 +msgid "Shotgun" +msgstr "" + +#: weapons.qc.tmp:13 +#, c-format +msgid "@!#%'n Tuba" +msgstr "" + +#: weapons.qc.tmp:14 +msgid "Mine Layer" +msgstr "" + +#: weapons.qc.tmp:15 +msgid "Rifle" +msgstr "" + +#: weapons.qc.tmp:16 +msgid "Machine Gun" +msgstr "" + +#: weapons.qc.tmp:17 +msgid "Fireball" +msgstr "" + +#: weapons.qc.tmp:18 +msgid "T.A.G. Seeker" +msgstr "" diff --git a/menu.dat.pt.po b/menu.dat.pt.po new file mode 100644 index 0000000000..a043dc30bb --- /dev/null +++ b/menu.dat.pt.po @@ -0,0 +1,2885 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Xontoic 0.1preview\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-09-02 07:51+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Ricardo 'Hellgardia' Silva <ricardo.mccs@gmail.com>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: Portuguese\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: qcsrc/common/mapinfo.qc:1092 qcsrc/menu/xonotic/skinlist.c:163 +#, c-format +msgid "%s: %s" +msgstr "%s: %s" + +#: qcsrc/menu/gamecommand.qc:47 +#, c-format +msgid "error: status is %d\n" +msgstr "erro: o estado é &d\n" + +#: qcsrc/menu/gamecommand.qc:65 +msgid "Usage: menu_cmd command..., where possible commands are:\n" +msgstr "Uso: menu_cmd command..., onde estão possíveis comandos:\n" + +#: qcsrc/menu/gamecommand.qc:66 +msgid " sync - reloads all cvars on the current menu page\n" +msgstr " sync - recarrega todas as cvars no menu actual" + +#: qcsrc/menu/gamecommand.qc:67 +msgid " directmenu ITEM - select a menu item as main item\n" +msgstr " directmenu ITEM - selecciona um item do menu como o principal\n" + +#: qcsrc/menu/gamecommand.qc:193 +msgid "error creating curl handle\n" +msgstr "erro a criar curl handle" + +#: qcsrc/menu/gamecommand.qc:239 +msgid "Invalid command. For a list of supported commands, try menu_cmd help.\n" +msgstr "" +"Comando inválido. Para uma lista de comandos suportados, escrever menu_cmd " +"help.\n" + +#: qcsrc/menu/item/gecko.c:49 +msgid "Browser not initialized!" +msgstr "Browser não inicializado!" + +#: qcsrc/menu/item/label.c:63 +#, c-format +msgid "NOTE: label text %s too wide for label, condensed by factor %f\n" +msgstr "" +"NOTA: marca texto %s demasiado larga para etiqueta, condensada por factor " +"%f\n" + +#: qcsrc/menu/item/listbox.c:300 +#, c-format +msgid "Item %d" +msgstr "Item %d" + +#: qcsrc/menu/item/slider.c:64 +#, c-format +msgid "%d (%s)" +msgstr "%d (%s)" + +#: qcsrc/menu/item/textslider.c:29 qcsrc/menu/item/textslider.c:31 +msgid "custom" +msgstr "modificado" + +#: qcsrc/menu/menu.qc:29 +#, c-format +msgid "^4MQC Build information: ^1%s\n" +msgstr "^4MQC Informação da Build %s\n" + +#: qcsrc/menu/xonotic/campaign.c:284 +#: qcsrc/menu/xonotic/dialog_singleplayer.c:134 +msgid "???" +msgstr "???" + +#: qcsrc/menu/xonotic/campaign.c:285 +#, c-format +msgid "Level %d: %s" +msgstr "Nível %d: %s" + +#: qcsrc/menu/xonotic/cvarlist.c:85 +msgid "will be saved to config.cfg" +msgstr "vai ser guardado para config.cfg" + +#: qcsrc/menu/xonotic/cvarlist.c:87 +msgid "will not be saved" +msgstr "não será guardado" + +#: qcsrc/menu/xonotic/cvarlist.c:89 +msgid "private" +msgstr "privado" + +#: qcsrc/menu/xonotic/cvarlist.c:91 +msgid "engine setting" +msgstr "definição do motor" + +#: qcsrc/menu/xonotic/cvarlist.c:93 +msgid "read only" +msgstr "apenas ler" + +#: qcsrc/menu/xonotic/dialog_credits.c:5 +msgid "Credits" +msgstr "Créditos" + +#: qcsrc/menu/xonotic/dialog_credits.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:269 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:41 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:57 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:61 +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:21 +msgid "OK" +msgstr "OK" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:4 +msgid "Welcome" +msgstr "Bem-Vindo" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:33 +msgid "" +"Welcome to Xonotic, please select your language preference and enter your " +"player name to get started. You can change these options later through the " +"menu system." +msgstr "" +"Bem-vindo ao Xonotic, por favor escolhe a linguagem de preferência e insere " +"o nick para começar. Pode mudar as opções mais tarde nas opções." + +#: qcsrc/menu/xonotic/dialog_firstrun.c:38 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:35 +msgid "Text language:" +msgstr "Linguagem do texto:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:47 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:40 +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:39 +msgid "Name:" +msgstr "Nome:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:69 +msgid "Save settings" +msgstr "Guardar Definições" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:4 +msgid "Ammo Panel" +msgstr "Painel de munições" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:22 +msgid "Ammunition display:" +msgstr "Mostrar munições:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:25 +msgid "Show only current ammo type" +msgstr "Mostrar apenas o tipo de munição actual" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:28 +msgid "Align icon:" +msgstr "Alinhar icones" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:29 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:36 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:40 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:40 +msgid "Left" +msgstr "Esquerda" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:38 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:41 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:41 +msgid "Right" +msgstr "Direita" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:4 +msgid "Centerprint" +msgstr "Centro" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:23 +msgid "Message duration:" +msgstr "Duração da mensagem:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:27 +msgid "Fade time:" +msgstr "Desaparecimento de cada entrada:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:31 +msgid "Flip messages order" +msgstr "Trocar ordem de notificações" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:33 +msgid "Text alignment:" +msgstr "Alinhamento do Texto" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:37 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:50 +msgid "Center" +msgstr "Centro" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:41 +msgid "Font scale:" +msgstr "Tamanho de letra:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:4 +msgid "Chat Panel" +msgstr "Painel de Conversa" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:22 +msgid "Chat entries:" +msgstr "Entradas na Conversa:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:25 +msgid "Chat size:" +msgstr "Tamanho da Conversa:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:29 +msgid "Chat lifetime:" +msgstr "Tempo de vida da Conversa:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:33 +msgid "Chat beep sound" +msgstr "Som de aviso de Conversa" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:4 +msgid "Engine Info Panel" +msgstr "Painel de Informação do Motor" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:22 +msgid "Engine info:" +msgstr "Informação do Motor:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:25 +msgid "Use an averaging algorithm for fps" +msgstr "Usar um algorítmo médio para os fps" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:4 +msgid "Health/Armor Panel" +msgstr "Painel Vida/Armadura" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:22 +msgid "Enable status bar" +msgstr "Activar barra de estado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:24 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:24 +msgid "Status bar alignment:" +msgstr "Alinhar barra de estado:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:42 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:42 +msgid "Inward" +msgstr "Para Dentro" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:43 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:43 +msgid "Outward" +msgstr "Para Fora" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:37 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:37 +msgid "Icon alignment:" +msgstr "Alinhamento dos Icones" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:45 +msgid "Flip health and armor positions" +msgstr "Trocar posição da vida e armadura" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:4 +msgid "Info Messages Panel" +msgstr "Painel de Info de Mensagens" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:22 +msgid "Info messages:" +msgstr "Informação de mensagens:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:25 +msgid "Flip align" +msgstr "Trocar alinhamento" + +#: qcsrc/menu/xonotic/dialog_hudpanel_modicons.c:4 +msgid "Mod Icons Panel" +msgstr "Painel dos Icones de Mod" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:4 +msgid "Notification Panel" +msgstr "Painel de Notificações" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:22 +msgid "Notifications:" +msgstr "Notificações:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:25 +msgid "Also print notifications to the console" +msgstr "Imprimir notificações na consola também" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:28 +msgid "Flip notify order" +msgstr "Trocar ordem de notificações" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:31 +msgid "Entry lifetime:" +msgstr "Tempo de vida de cada entrada:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:35 +msgid "Entry fadetime:" +msgstr "Desaparecimento de cada entrada:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:4 +msgid "Physics Panel" +msgstr "Painel de Física" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:21 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:21 +msgid "Panel disabled" +msgstr "Painel desactivado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:23 +msgid "Panel enabled" +msgstr "Painel activado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:24 +msgid "Panel enabled even observing" +msgstr "Painel activado quando espectador" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:25 +msgid "Panel enabled only in Race/CTS" +msgstr "Painel activo apenas em jogos de Corrida/CTS" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:31 +msgid "Status bar" +msgstr "Barra de estado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:48 +msgid "Left align" +msgstr "Alinhamento à esquerda" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:34 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:52 +msgid "Right align" +msgstr "Alinhamento à direita" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:35 +msgid "Inward align" +msgstr "Para Dentro" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:36 +msgid "Outward align" +msgstr "Para Fora" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:40 +msgid "Flip speed/acceleration positions" +msgstr "Trocar posição da velocidade e aceleração" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:44 +msgid "Speed:" +msgstr "Velocidade:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:45 +msgid "Include vertical speed" +msgstr "Incluir velocidade vertical" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:56 +msgid "Speed unit:" +msgstr "Unidade de velocidade:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:58 +msgid "qu/s" +msgstr "qu/s" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:59 +msgid "m/s" +msgstr "m/s" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:60 +msgid "km/h" +msgstr "km/h" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:61 +msgid "mph" +msgstr "mph" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:62 +msgid "knots" +msgstr "nós" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:64 +msgid "Show" +msgstr "Mostrar" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:67 +msgid "Top speed" +msgstr "Velocidade Máxima:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:73 +msgid "Acceleration:" +msgstr "Aceleração:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:74 +msgid "Include vertical acceleration" +msgstr "Incluir aceleração vertical" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:4 +msgid "Powerups Panel" +msgstr "Painel de Powerups" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:45 +msgid "Flip strength and shield positions" +msgstr "Trocar posição do escudo e da força" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:4 +msgid "Pressed Keys Panel" +msgstr "Painel das Teclas Pressionadas" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:22 +msgid "Panel enabled when spectating" +msgstr "Painel activado quando espectador" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:23 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:23 +msgid "Panel always enabled" +msgstr "Painel sempre activado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:30 +msgid "Forced aspect:" +msgstr "Forçar aspecto:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_racetimer.c:4 +msgid "Race Timer Panel" +msgstr "Painel do Cronómetro de Corrida" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:4 +msgid "Radar Panel" +msgstr "Painel do Radar" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:22 +msgid "Panel enabled in teamgames" +msgstr "Painel activo em jogos de equipa" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:29 +msgid "Radar:" +msgstr "Radar:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:32 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:43 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:154 +#: qcsrc/menu/xonotic/util.qc:600 +msgid "Alpha:" +msgstr "Alfa:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:36 +msgid "Rotation:" +msgstr "Rotação:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:38 +msgid "Forward" +msgstr "Para a frente" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:39 +msgid "West" +msgstr "Para oeste" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:40 +msgid "South" +msgstr "Para sul" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:41 +msgid "East" +msgstr "Para este" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:42 +msgid "North" +msgstr "Para norte" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:46 +msgid "Scale:" +msgstr "Escala:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:50 +msgid "Zoom mode:" +msgstr "Modo de ampliação:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:52 +msgid "Zoomed in" +msgstr "Ampliado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:53 +msgid "Zoomed out" +msgstr "Não-Ampliado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:54 +msgid "Always zoomed" +msgstr "Sempre ampliado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:55 +msgid "Never zoomed" +msgstr "Nunca ampliado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:4 +msgid "Score Panel" +msgstr "Painel de Pontos" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:22 +msgid "Score:" +msgstr "Pontuação:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:25 +msgid "Rankings:" +msgstr "Tabela Classficativa:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:26 +msgid "Off" +msgstr "Desligado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:27 +msgid "And me" +msgstr "E eu" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:28 +msgid "Pure" +msgstr "Puro" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:4 +msgid "Timer Panel" +msgstr "Painel Temporizador" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:22 +msgid "Timer:" +msgstr "Temporizador:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:25 +msgid "Show elapsed time" +msgstr "Mostrar tempo passado" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:4 +msgid "Vote Panel" +msgstr "Painel de votos" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:22 +msgid "Alpha after voting:" +msgstr "Alfa após votagem:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:4 +msgid "Weapons Panel" +msgstr "Painel das Armas" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:24 +msgid "Fade out after:" +msgstr "Desaparecer após:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:26 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:36 +msgid "Never" +msgstr "Nunca" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:28 +#, c-format +msgid "%ds" +msgstr "%ds" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:32 +msgid "Fade effect:" +msgstr "Efeito de desaparecimento" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:35 +msgid "EF^None" +msgstr "Nenhum" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:36 +msgid "Slide" +msgstr "Deslocador" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:37 +msgid "Alpha" +msgstr "Alfa" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:38 +msgid "EF^Both" +msgstr "Ambos" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:42 +msgid "Weapon icons:" +msgstr "Icones das armas" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:45 +msgid "Show weapon ID as:" +msgstr "Mostra o ID da arma como:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:46 +msgid "SHOWAS^None" +msgstr "Nenhum" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:47 +msgid "Number" +msgstr "Número" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:48 +msgid "Bind" +msgstr "Ligar" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:51 +msgid "Show Accuracy" +msgstr "Mostrar Pontaria" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:52 +msgid "Show Ammo" +msgstr "Mostrar Munições" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:55 +msgid "Ammo bar color:" +msgstr "Cor da barra de munições:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:61 +msgid "Ammo bar alpha:" +msgstr "Cor da barra alfa:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:4 +msgid "Panel HUD Setup" +msgstr "Configuração do painel do HUD" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:21 +msgid "Panel background defaults:" +msgstr "Fundo do painel por defeito:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:23 qcsrc/menu/xonotic/util.qc:575 +msgid "Background:" +msgstr "Fundo:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:25 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:37 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:52 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:91 qcsrc/menu/xonotic/util.qc:578 +#: qcsrc/menu/xonotic/util.qc:594 qcsrc/menu/xonotic/util.qc:611 +msgid "Disable" +msgstr "Desactivar" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:30 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:77 qcsrc/menu/xonotic/util.qc:583 +msgid "Color:" +msgstr "Cor:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:35 qcsrc/menu/xonotic/util.qc:591 +msgid "Border size:" +msgstr "Tamanho do limite:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:50 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:89 +msgid "Team color:" +msgstr "Cor da Equipa:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:58 qcsrc/menu/xonotic/util.qc:617 +msgid "Test team color in configure mode" +msgstr "Testa cor da equipa no modo de configuração" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:61 qcsrc/menu/xonotic/util.qc:620 +msgid "Padding:" +msgstr "Padding:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:68 +msgid "HUD Dock:" +msgstr "Local do HUD:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:70 +msgid "DOCK^Disabled" +msgstr "Desligado" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:71 +msgid "DOCK^Small" +msgstr "Pequena" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:72 +msgid "DOCK^Medium" +msgstr "Média" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:73 +msgid "DOCK^Large" +msgstr "Grande" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:96 +msgid "Grid settings:" +msgstr "Definições da Rede:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:99 +msgid "Snap panels to grid" +msgstr "Fixar paineis à Rede" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:102 +msgid "Grid size:" +msgstr "Tamanho da Rede:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:103 +msgid "X:" +msgstr "X:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:109 +msgid "Y:" +msgstr "Y:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:117 +msgid "Exit setup" +msgstr "Sair da configuração" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:4 +msgid "Multiplayer" +msgstr "Multi-jogador" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:18 +msgid "Servers" +msgstr "Servidores" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:19 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:5 +msgid "Create" +msgstr "Criar" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:20 +msgid "Demos" +msgstr "Demos" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:5 +msgid "Player Setup" +msgstr "Configuração do Jogador" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:34 +msgid "Game type:" +msgstr "Tipo de jogo:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:46 +msgid "Match settings:" +msgstr "Definições de jogo:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:49 +msgid "Time limit:" +msgstr "Tempo limite:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:53 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:61 +msgid "Use map specified default" +msgstr "Usar definição específica do mapa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:56 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:155 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:156 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:157 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:161 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:162 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:163 +msgid "Point limit:" +msgstr "Limite de pontos:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:64 +msgid "Player slots:" +msgstr "Slots para Jogadores:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:67 +msgid "Number of bots:" +msgstr "Número de jogadores controlados pelo computador:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:71 +msgid "Bot skill:" +msgstr "Nível de dificuldade:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:74 +msgid "Botlike" +msgstr "Bot" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:75 +msgid "Beginner" +msgstr "Iniciado" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:76 +msgid "You will win" +msgstr "Vais ganhar" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:77 +msgid "You can win" +msgstr "Podes ganhar" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:78 +msgid "You might win" +msgstr "Talvez ganhes" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:79 +msgid "Advanced" +msgstr "Avançado" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:80 +msgid "Expert" +msgstr "Perito" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:81 +msgid "Pro" +msgstr "Profissional" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:82 +msgid "Assassin" +msgstr "Assassino" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:83 +msgid "Unhuman" +msgstr "Desumano" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:84 +msgid "Godlike" +msgstr "Divinal" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:88 +msgid "Mutators..." +msgstr "Mutators..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:97 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:57 +msgid "Advanced settings..." +msgstr "Definições avançadas..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:104 +msgid "Map list:" +msgstr "Lista de mapas:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:110 +msgid "Select all" +msgstr "Seleccionar todos" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:113 +msgid "Select none" +msgstr "Seleccionar nenhum" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:119 +msgid "Start Multiplayer!" +msgstr "Começar Multijogador!" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:154 +msgid "Capture limit:" +msgstr "Limite de capturas:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:158 +msgid "Lives:" +msgstr "Vidas:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:159 +msgid "Laps:" +msgstr "Voltas:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:160 +msgid "Goals:" +msgstr "Golos:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:164 +msgid "Frag limit:" +msgstr "Limite de Frags:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:6 +msgid "Advanced server settings" +msgstr "Definições avançadas do servidor" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:25 +msgid "Game settings:" +msgstr "Definições de Jogo:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:28 +msgid "Allow spectating" +msgstr "Permitir espectador" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:31 +msgid "Spawn shield:" +msgstr "Protecção de Spawn:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:36 +msgid "Game speed:" +msgstr "Velocidade do jogo:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:40 +msgid "Teamplay settings:" +msgstr "Definições de Jogo de Equipa:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:43 +msgid "Friendly fire scale:" +msgstr "Escala de Dano nos aliados:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:47 +msgid "Virtual friendly fire (effect only)" +msgstr "Dano nos Aliados Virtual (Apenas o efeito)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:50 +msgid "Friendly fire penalty:" +msgstr "Penalização por Dano nos Aliados:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:54 +msgid "Virtual penalty (effect only)" +msgstr "Penalidade Virtual (Apenas o efeito)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:57 +msgid "Teams:" +msgstr "Equipas:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:66 +msgid "Map voting:" +msgstr "Votação de mapa:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:68 +msgid "No voting" +msgstr "Sem votação" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:69 +msgid "2 choices" +msgstr "2 escolhas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:70 +msgid "3 choices" +msgstr "3 escolhas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:71 +msgid "4 choices" +msgstr "4 escolhas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:72 +msgid "5 choices" +msgstr "5 escolhas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:73 +msgid "6 choices" +msgstr "6 escolhas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:74 +msgid "7 choices" +msgstr "7 escolhas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:75 +msgid "8 choices" +msgstr "8 escolhas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:76 +msgid "9 choices" +msgstr "9 escolhas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:79 +msgid "Simple majority wins vcall" +msgstr "Maioria ganha vcall" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:5 +msgid "Map Information" +msgstr "Informação do Mapa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "Full item placement" +msgstr "Colocação total dos items" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "MinstaGib only" +msgstr "Apenas MinstaGib" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:78 +msgid "Title:" +msgstr "Título:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:84 +msgid "Author:" +msgstr "Autor:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:90 +msgid "Features:" +msgstr "Características:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:95 +msgid "Game types:" +msgstr "Modos de jogo:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:118 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:314 +msgid "Close" +msgstr "Fechar" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:121 +msgid "MAP^Play" +msgstr "Jogar" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:7 +msgid "Mutators" +msgstr "Mutators" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:33 +msgid "All Weapons Arena" +msgstr "Arena com Todas as Armas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:35 +msgid "Most Weapons Arena" +msgstr "Arena com Maior Parte das Armas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:56 +#, c-format +msgid "%s Arena" +msgstr "%s Arena" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:68 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:167 +msgid "Dodging" +msgstr "Desvio" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:70 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:250 +msgid "MinstaGib" +msgstr "MinstaGib" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:253 +msgid "NIX" +msgstr "NIX" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:74 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:205 +msgid "Rocket Flying" +msgstr "Voar com Rockets" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:78 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:264 +msgid "No start weapons" +msgstr "Sem armas iniciais" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:80 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:189 +msgid "Low gravity" +msgstr "Pouca gravidade" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:170 +msgid "Cloaked" +msgstr "Escondido" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:84 +msgid "Hook" +msgstr "Gancho" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:86 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:173 +msgid "Midair" +msgstr "A meio do ar" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:88 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:176 +msgid "Vampire" +msgstr "Vampiro" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:90 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:208 +msgid "Piñata" +msgstr "Piñata" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:92 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:211 +msgid "Weapons stay" +msgstr "Armas ficam" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:94 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:180 +msgid "Blood loss" +msgstr "Perda de sangue" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:96 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:202 +msgid "Jet pack" +msgstr "Jetpack" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:98 +msgid "MUT^None" +msgstr "Nenhum" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:164 +msgid "Gameplay mutators:" +msgstr "Mutators de jogabilidade" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:196 +msgid "Weapon & item mutators:" +msgstr "Mutators de armas e items" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:199 +msgid "Grappling hook" +msgstr "Gancho de trepar" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:215 +msgid "Weapon arenas:" +msgstr "Arenas de Armas:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:218 +msgid "Regular (no arena)" +msgstr "Regular (não arena específica)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:239 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:256 +msgid "with laser" +msgstr "com laser" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:247 +msgid "Special arenas:" +msgstr "Arenas Especiais:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:260 +msgid "Most weapons" +msgstr "Maior parte das Armas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:4 +msgid "Demo" +msgstr "Demo" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:28 +msgid "Record demos while playing" +msgstr "Gravar demos enquanto joga" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:32 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:28 +msgid "Filter:" +msgstr "Filtrar:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:29 +#: qcsrc/menu/xonotic/dialog_settings_input.c:41 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:24 +msgid "Clear" +msgstr "Limpar" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:43 +msgid "Timedemo" +msgstr "Demo temporizado" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:46 +#, fuzzy +msgid "DEMO^Play" +msgstr "Jogar" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:4 +msgid "Join" +msgstr "Juntar" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:36 +msgid "SRVS^Empty" +msgstr "Vazio" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:40 +msgid "SRVS^Full" +msgstr "Total" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:44 +msgid "Pause" +msgstr "Pausar" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:56 +msgid "Address:" +msgstr "Endereço:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:67 +msgid "Info..." +msgstr "Informação..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:317 +msgid "Join!" +msgstr "Juntar!" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:5 +msgid "Server Information" +msgstr "Informação do Servidor" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:115 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:116 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:183 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:189 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:199 +msgid "N/A" +msgstr "N/A" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:158 +#, c-format +msgid "%d/%d, %d free player slots" +msgstr "%d/%d, %d slots disponíveis" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +#, c-format +msgid "%d modified settings" +msgstr "%d definições modificadas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +msgid "Official settings" +msgstr "Definições oficiais" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:197 +msgid "N/A (can't connect)" +msgstr "N/A (não conseguiu ligar)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:205 +msgid "not supported (can't connect)" +msgstr "não é suportado (não conseguiu ligar)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:207 +msgid "not supported (won't encrypt)" +msgstr "não suportado (não encripta)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:211 +msgid "supported (will encrypt)" +msgstr "suportado (vai encriptar)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:213 +msgid "supported (won't encrypt)" +msgstr "suportado (não encripta)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:217 +msgid "requested (will encrypt)" +msgstr "pedido (encripta)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:219 +msgid "requested (won't encrypt)" +msgstr "pedido (não encripta)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:223 +msgid "required (can't connect)" +msgstr "necessário (não consegue ligar)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:225 +msgid "required (will encrypt)" +msgstr "necessário (encripta)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:246 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:269 +msgid "Players:" +msgstr "Jogadores:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:254 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:38 +msgid "Type:" +msgstr "Tipo:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:259 +msgid "Map:" +msgstr "Mapa:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:264 +msgid "Gameplay:" +msgstr "Jogabilidade:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:274 +msgid "Bots:" +msgstr "Jogadores controlados pelo computador:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:279 +msgid "Mod:" +msgstr "Mod:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:284 +msgid "Version:" +msgstr "Versão:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:289 +msgid "Ping:" +msgstr "Ping:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:295 +msgid "CA:" +msgstr "CA:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:301 +msgid "Key:" +msgstr "Chave:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:307 +msgid "Encryption:" +msgstr "Encriptação:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:63 +msgid "Model:" +msgstr "Modelo:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:88 +msgid "Field of view:" +msgstr "Campo de visão:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:92 +msgid "View bobbing:" +msgstr "Ver tremor:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:96 +msgid "Zoom factor:" +msgstr "Factor de Ampliação (ZOOM):" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:100 +msgid "Zoom speed:" +msgstr "Velocidade de Ampliação (ZOOM):" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:103 +msgid "Weapon settings..." +msgstr "Definições das Armas..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:110 +msgid "Crosshair:" +msgstr "Mira:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:111 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:139 +msgid "Per weapon" +msgstr "Por arma" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:130 +msgid "Crosshair size:" +msgstr "Tamanho da mira:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:134 +msgid "Crosshair alpha:" +msgstr "Alfa da mira:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:138 +msgid "Crosshair color:" +msgstr "Cor da mira:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:140 +msgid "By health" +msgstr "Por vida" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:143 +msgid "Custom" +msgstr "modificado" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:148 +msgid "Enable center dot" +msgstr "Activar ponto central" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:151 +msgid "Size:" +msgstr "Tamanho:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:158 +msgid "Hit test:" +msgstr "Teste de Tiro:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:159 +msgid "HTST^None" +msgstr "Nenhum" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:160 +msgid "TrueAim" +msgstr "PontariaCerta" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:161 +msgid "Enemies" +msgstr "Inimigos" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:164 +msgid "Waypoints setup..." +msgstr "Configurar caminhos..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:169 +msgid "Enter HUD editor" +msgstr "Entrar no editor do HUD" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:174 +msgid "Force models:" +msgstr "Forçar modelos:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:175 +msgid "MDL^None" +msgstr "Nenhum" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:176 +msgid "MDL^Custom" +msgstr "Modificado" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:177 +msgid "MDL^All" +msgstr "Todos" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:180 +msgid "Disable gore effects" +msgstr "Desactivar sangue/violencia" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:182 +msgid "Gibs:" +msgstr "Tripas:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:184 +msgid "GIBS^None" +msgstr "Nenhum" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:185 +msgid "GIBS^Few" +msgstr "Poucas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:186 +msgid "GIBS^Many" +msgstr "Muitas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:187 +msgid "GIBS^Lots" +msgstr "Imensas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:191 +msgid "Damage splash:" +msgstr "Dano Colateral:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:195 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:173 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:194 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:30 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:41 +#: qcsrc/menu/xonotic/dialog_settings_video.c:109 +msgid "Apply immediately" +msgstr "Aplicar imediatamente" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:5 +msgid "Waypoints" +msgstr "Caminhos" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:23 +msgid "Show base waypoints" +msgstr "Mostrar caminhos base" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:25 +msgid "Waypoint scale:" +msgstr "Escala dos Caminhos:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:29 +msgid "Waypoint alpha:" +msgstr "Caminhos alfa:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:34 +msgid "Show names:" +msgstr "Mostrar nomes:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:37 +msgid "Teammates" +msgstr "Companheiros de Equipa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:38 +msgid "All players" +msgstr "Todos os jogadores" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:6 +msgid "Weapon settings" +msgstr "Definições de Armas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:29 +msgid "Weapon priority list:" +msgstr "Prioridade das Armas:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:34 +msgid "Up" +msgstr "Cima" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:37 +msgid "Down" +msgstr "Baixo" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:41 +msgid "Use priority list for weapon cycling" +msgstr "Usar lista de prioridades para ciclo entre as armas" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:43 +msgid "Auto switch weapons on pickup" +msgstr "Mudar armas automaticamente ao apanhar do chão" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:45 +msgid "Draw 1st person weapon model" +msgstr "Desenhar modelo da arma na 1a pessoa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:55 +msgid "Flip view horizontally" +msgstr "Trocar vista horizontal" + +#: qcsrc/menu/xonotic/dialog_news.c:4 +msgid "News" +msgstr "Novidades" + +#: qcsrc/menu/xonotic/dialog_news.c:18 +msgid "http://www.xonotic.org/team/blog/" +msgstr "http://www.xonotic.org/team/blog/" + +#: qcsrc/menu/xonotic/dialog_quit.c:4 +msgid "Quit" +msgstr "Sair" + +#: qcsrc/menu/xonotic/dialog_quit.c:17 +msgid "Are you sure you want to quit?" +msgstr "Tens a certeza que queres sair?" + +#: qcsrc/menu/xonotic/dialog_quit.c:20 +msgid "Yes" +msgstr "Sim" + +#: qcsrc/menu/xonotic/dialog_quit.c:21 +msgid "No" +msgstr "Não" + +#: qcsrc/menu/xonotic/dialog_settings.c:4 +msgid "Settings" +msgstr "Definições" + +#: qcsrc/menu/xonotic/dialog_settings.c:18 +#: qcsrc/menu/xonotic/dialog_settings_input.c:4 +msgid "Input" +msgstr "Input" + +#: qcsrc/menu/xonotic/dialog_settings.c:19 +#: qcsrc/menu/xonotic/dialog_settings_video.c:4 +msgid "Video" +msgstr "Vídeo" + +#: qcsrc/menu/xonotic/dialog_settings.c:20 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:4 +msgid "Effects" +msgstr "Efeitos" + +#: qcsrc/menu/xonotic/dialog_settings.c:21 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:4 +msgid "Audio" +msgstr "Som" + +#: qcsrc/menu/xonotic/dialog_settings.c:22 +#: qcsrc/menu/xonotic/dialog_settings_network.c:4 +msgid "Network" +msgstr "Rede" + +#: qcsrc/menu/xonotic/dialog_settings.c:23 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:4 +msgid "Misc" +msgstr "Misc" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:27 +msgid "Master:" +msgstr "Principal:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:33 +msgid "Music:" +msgstr "Música:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:41 +msgid "VOL^Ambient:" +msgstr "Som Ambiente:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:48 +msgid "Info:" +msgstr "Informação:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:55 +msgid "Items:" +msgstr "Items:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:62 +msgid "Pain:" +msgstr "Dor:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:69 +msgid "Player:" +msgstr "Jogador:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:76 +msgid "Shots:" +msgstr "Tiros:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:83 +msgid "Voice:" +msgstr "Voz:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:91 +msgid "Weapons:" +msgstr "Armas:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:98 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:156 +msgid "Frequency:" +msgstr "Frequência:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:100 +msgid "8 kHz" +msgstr "8 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:101 +msgid "11.025 kHz" +msgstr "11.025 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:102 +msgid "16 kHz" +msgstr "16 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:103 +msgid "22.05 kHz" +msgstr "22.05 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:104 +msgid "24 kHz" +msgstr "24 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:105 +msgid "32 kHz" +msgstr "32 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:106 +msgid "44.1 kHz" +msgstr "44.1 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:107 +msgid "48 kHz" +msgstr "48 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:110 +msgid "Channels:" +msgstr "Canais:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:112 +msgid "Mono" +msgstr "Mono" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:113 +msgid "Stereo" +msgstr "Stereo" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:114 +msgid "2.1" +msgstr "2.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:115 +msgid "4" +msgstr "4" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:116 +msgid "5" +msgstr "5" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:117 +msgid "5.1" +msgstr "5.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:118 +msgid "6.1" +msgstr "6.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:119 +msgid "7.1" +msgstr "7.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:123 +msgid "Swap Stereo" +msgstr "Trocar Stereo" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:127 +msgid "Headphone friendly mode" +msgstr "Modo de Headphones" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:131 +msgid "Spatial voices:" +msgstr "Vozes espaciais:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:132 +msgid "VOCS^None" +msgstr "Nenhum" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:133 +msgid "VOCS^Taunts" +msgstr "Taunts" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:134 +msgid "VOCS^All" +msgstr "Todos" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:137 +msgid "Taunt range:" +msgstr "Nível dos taunts:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:140 +msgid "RNG^Very short" +msgstr "Muito baixo" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:141 +msgid "RNG^Short" +msgstr "Baixo" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:142 +msgid "RNG^Normal" +msgstr "Normal" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:143 +msgid "RNG^Long" +msgstr "Alto" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:144 +msgid "RNG^Full" +msgstr "Total" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:151 +msgid "Automatic taunts" +msgstr "Taunts Automáticos" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:160 +msgid "Time warning:" +msgstr "Aviso de tempo:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:162 +msgid "WRN^None" +msgstr "Nenhum" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:163 +msgid "1 minute" +msgstr "1 minuto" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:164 +msgid "5 minutes" +msgstr "5 minutos" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:165 +msgid "WRN^Both" +msgstr "Ambos" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:168 +msgid "Hit indicator" +msgstr "Indicador de tiro acertado" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:170 +msgid "Menu sounds" +msgstr "Sons do menu" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:38 +msgid "Quality preset:" +msgstr "Predefinição de Qualidade:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:41 +msgid "PRE^OMG!" +msgstr "OMG!" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:42 +msgid "PRE^Low" +msgstr "Baixa" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:43 +msgid "PRE^Medium" +msgstr "Média" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:44 +msgid "PRE^Normal" +msgstr "Normal" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:45 +msgid "PRE^High" +msgstr "Alta" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:46 +msgid "PRE^Ultra" +msgstr "Ultra" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:48 +msgid "PRE^Ultimate" +msgstr "Máxima" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:52 +msgid "Geometry detail:" +msgstr "Detalhes geométricos:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:54 +msgid "DET^Lowest" +msgstr "Mínimo" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:55 +msgid "DET^Low" +msgstr "Baixa" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:56 +msgid "DET^Normal" +msgstr "Normal" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:57 +msgid "DET^Good" +msgstr "Bom" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:58 +msgid "DET^Best" +msgstr "Melhores" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:59 +msgid "DET^Insane" +msgstr "Máximo" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:62 +msgid "Antialiasing:" +msgstr "Antialiasing:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:64 +msgid "AA^Disabled" +msgstr "Desligado" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:65 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:103 +msgid "2x" +msgstr "2 passagens" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:66 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:104 +msgid "4x" +msgstr "4 passagens" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:70 +msgid "Texture resolution:" +msgstr "Resolução das texturas:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:73 +msgid "RES^Leet" +msgstr "Leet" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:74 +msgid "RES^Lowest" +msgstr "Mínimo" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:75 +msgid "RES^Low" +msgstr "Baixa" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:76 +msgid "RES^Normal" +msgstr "Normal" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:77 +msgid "RES^Good" +msgstr "Bom" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:78 +msgid "RES^Best" +msgstr "Melhores" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:91 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:94 +msgid "Avoid lossy texture compression" +msgstr "Evitar compressão de Texturas" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:100 +msgid "Anisotropy:" +msgstr "Filtro Anisotrópico:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:102 +msgid "ANISO^Disabled" +msgstr "Desligado" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:105 +msgid "8x" +msgstr "8x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:106 +msgid "16x" +msgstr "16x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:110 +msgid "Particle quality:" +msgstr "Qualidade das Partículas:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:113 +msgid "Particle distance:" +msgstr "Distancia visível das Partículas:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:117 +msgid "Decals" +msgstr "Símbolos" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:118 +msgid "Decals on models" +msgstr "Marcas nos modelos" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:122 +msgid "Distance:" +msgstr "Distância:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:128 +msgid "Time:" +msgstr "Tempo:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:134 +msgid "Use lightmaps" +msgstr "Usar lightmaps" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:135 +msgid "Deluxe mapping" +msgstr "Mapeamento Deluxe" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:137 +msgid "Gloss" +msgstr "Lustro" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:140 +msgid "Offset mapping" +msgstr "Mapeamento Offset" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:142 +msgid "Relief mapping" +msgstr "Mapeamento Relief" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:145 +msgid "Reflections:" +msgstr "Reflexos:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:148 +msgid "Blurred" +msgstr "Grau de Blur" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:149 +msgid "REFL^Good" +msgstr "Bom" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:150 +msgid "Sharp" +msgstr "Grau de Definição" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:155 +msgid "Show surfaces" +msgstr "Mostrar superfícies" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:157 +msgid "No dynamic lighting" +msgstr "Iluminação dinâmica desligada" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:159 +msgid "Flash blend approximation" +msgstr "Aproximação Flash Blend" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:161 +msgid "Realtime dynamic lighting" +msgstr "Iluminação dinâmica em tempo real" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:162 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:166 +msgid "Shadows" +msgstr "Sombras" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:165 +msgid "Realtime world lighting" +msgstr "Iluminação do mundo em tempo real" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:170 +msgid "Use normal maps" +msgstr "Usar mapas normais" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:172 +msgid "Soft shadows" +msgstr "Sombras Suaves" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:175 +msgid "Coronas" +msgstr "Coronas" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:176 +msgid "Use Occlusion Queries" +msgstr "Usar Consultas Oclusão" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:178 +msgid "Bloom" +msgstr "Bloom" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:180 +msgid "High Dynamic Range (HDR)" +msgstr "High Dynamic Range (HDR)" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:184 +msgid "Motion blur:" +msgstr "Distorção por movimento:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:189 +msgid "Blur and sharpen postprocessing" +msgstr "Blur e postprocessing" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:26 +msgid "Key bindings:" +msgstr "Bindings de Teclas" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:31 +msgid "Change key..." +msgstr "Mudar tecla..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:35 +msgid "Edit..." +msgstr "Editar..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:46 +msgid "Sensitivity:" +msgstr "Sensibilidade:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:51 +msgid "UI mouse speed:" +msgstr "Velocidade do rato:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:55 +msgid "Mouse filter" +msgstr "Filtro do Rato" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:57 +msgid "Invert mouse" +msgstr "Inverter Rato" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:60 +#: qcsrc/menu/xonotic/dialog_settings_input.c:62 +msgid "Use joystick input" +msgstr "Usar input do joystick" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:65 +#: qcsrc/menu/xonotic/dialog_settings_input.c:67 +msgid "Turn off OS mouse acceleration" +msgstr "Desligar aceleração de Rato do SO" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:69 +msgid "\"enter console\" also closes" +msgstr "\"entrar na consola\" também fecha" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:5 +msgid "User defined key bind" +msgstr "Keybinds definidas pelo utilizador" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:42 +msgid "Command when pressed:" +msgstr "Comando quando carregado:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:45 +msgid "Command when released:" +msgstr "Comando quando largado:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:48 +msgid "Save" +msgstr "Guardar" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:51 +msgid "Cancel" +msgstr "Cancelar" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:26 +msgid "Menu skins:" +msgstr "Skins de Menu:" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:47 +msgid "Show current time" +msgstr "Mostrar tempo corrente" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:49 +msgid "Show current date" +msgstr "Mostrar data corrente" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:51 +msgid "Show frames per second" +msgstr "Mostrar Frames por Segundo" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:53 +msgid "Minimize input latency" +msgstr "Minimizar latência de entrada" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:5 +msgid "Advanced settings" +msgstr "Definições avançadas" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:23 +msgid "Cvar filter:" +msgstr "Filtro de Cvar" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:34 +msgid "Setting:" +msgstr "Definição:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:42 +msgid "Value:" +msgstr "Valor:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:56 +msgid "Description:" +msgstr "Descrição:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:26 +msgid "Client-side movement prediction" +msgstr "Previsão de movimento pelo Cliente" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:30 +msgid "Show netgraph" +msgstr "Mostrar gráfico-net" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:33 +msgid "Network speed:" +msgstr "Velocidade da Rede:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:35 +msgid "56k" +msgstr "56k" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:36 +msgid "ISDN" +msgstr "ISDN" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:37 +msgid "Slow ADSL" +msgstr "ADSL Lenta" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:38 +msgid "Fast ADSL" +msgstr "ADSL Rápida" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:39 +msgid "Broadband" +msgstr "Banda-larga" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:42 +msgid "Input packets/s:" +msgstr "Pacotes Entrada /s" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:46 +msgid "HTTP downloads:" +msgstr "Transferências via HTTP:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:49 +msgid "Downloads:" +msgstr "Transferências:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:53 +msgid "Speed (kB/s):" +msgstr "Velocidade (kB/s):" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:57 +msgid "Client UDP port:" +msgstr "Port UDP do Cliente:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:26 +msgid "Resolution:" +msgstr "Resolução:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:29 +msgid "Font/UI size:" +msgstr "Font/UI - tamanho:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:31 +msgid "SZ^Unreadable" +msgstr "Ilegível" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:32 +msgid "SZ^Tiny" +msgstr "Minuscula" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:33 +msgid "SZ^Little" +msgstr "Muito Pequena" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:34 +msgid "SZ^Small" +msgstr "Pequena" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:35 +msgid "SZ^Medium" +msgstr "Média" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:36 +msgid "SZ^Large" +msgstr "Grande" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:37 +msgid "SZ^Huge" +msgstr "Enorme" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:38 +msgid "SZ^Gigantic" +msgstr "Gigante" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:39 +msgid "SZ^Colossal" +msgstr "Colossal" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:42 +msgid "Color depth:" +msgstr "Profundidade da cor:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:45 +msgid "Full screen" +msgstr "Ecrã Inteiro" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:46 +msgid "Vertical Synchronization" +msgstr "Sincronização Vertical" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:49 +msgid "Use OpenGL 2.0 shaders (GLSL)" +msgstr "Usar shaders OpenGL2.0 (GLSL)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:52 +msgid "Use GLSL to handle color control" +msgstr "Usar GLSL para o controlo de cores" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:56 +msgid "Vertex Buffer Objects (VBOs)" +msgstr "Objectos Vertex Buffers (VBOs)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:59 +msgid "VBO^Off" +msgstr "Desligado" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:60 +msgid "Vertices, some Tris (compatible)" +msgstr "Vértices, alguns Triângulos (compatível)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:63 +msgid "Vertices" +msgstr "Vértices" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:64 +msgid "Vertices and Triangles" +msgstr "Vértices e Triângulos" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:67 +msgid "Depth first:" +msgstr "Profundidade primeiro:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:69 +msgid "DF^Disabled" +msgstr "Desligado" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:70 +msgid "DF^World" +msgstr "Mundo" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:71 +msgid "DF^All" +msgstr "Todos" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:75 +msgid "Disable multithreaded OpenGL" +msgstr "Desactivar OpenGL em múltiplos threads" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:77 +msgid "Wait for GPU to finish each frame" +msgstr "Esperar que a placa gráfica termine cada frame" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:80 +msgid "Brightness:" +msgstr "Brilho:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:83 +msgid "Contrast:" +msgstr "Contraste:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:86 +msgid "Gamma:" +msgstr "Gamma:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:91 +msgid "Contrast boost:" +msgstr "Contraste - Boost" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:96 +msgid "Saturation:" +msgstr "Saturação da Cor:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:102 +msgid "LIT^Ambient:" +msgstr "Som Ambiente:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:105 +msgid "Intensity:" +msgstr "Intensidade:" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:4 +msgid "Singleplayer" +msgstr "Um Jogador" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:127 +msgid "Instant action! (random map with bots)" +msgstr "Acção Instantânea! (Mapa ao acaso contra o computador)" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:148 +msgid "Start Singleplayer!" +msgstr "Começar Um só Jogador!" + +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:4 +msgid "Winner" +msgstr "Vencedor" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:5 +msgid "Team Selection" +msgstr "Selecção de Equipa" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:41 +msgid "join 'best' team (auto-select)" +msgstr "juntar 'melhor' equipa (selecção automática)" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:45 +msgid "red" +msgstr "vermelha" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:46 +msgid "blue" +msgstr "azul" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:47 +msgid "yellow" +msgstr "amarela" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:48 +msgid "pink" +msgstr "rosa" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:51 +msgid "spectate" +msgstr "espectador" + +#: qcsrc/menu/xonotic/mainwindow.c:35 qcsrc/menu/xonotic/mainwindow.c:38 +msgid "Do not press this button again!" +msgstr "Não voltar a carregar neste botão!" + +#: qcsrc/menu/xonotic/maplist.c:278 +msgid "" +"Huh? Can't play this (m is NULL). Refiltering so this won't happen again.\n" +msgstr "" +"Huh? Não posso jogar isto (m é NULL). Voltando a filtrar de maneira a que " +"isto não se repitanovamente.\n" + +#: qcsrc/menu/xonotic/maplist.c:286 +#, c-format +msgid "%s's Xonotic Server" +msgstr "Servidor de Xonotic do %s" + +#: qcsrc/menu/xonotic/maplist.c:291 +msgid "" +"Huh? Can't play this (invalid game type). Refiltering so this won't happen " +"again.\n" +msgstr "" +"Huh? Não posso jogar isto (tipo de jogo inválido). Voltando a filtrar de " +"maneira a que isto não se repitanovamente.\n" + +#: qcsrc/menu/xonotic/playermodel.c:174 +msgid "<no model found>" +msgstr "<nenhum modelo encontrado>" + +#: qcsrc/menu/xonotic/serverlist.c:185 +msgid "Remove" +msgstr "Remover" + +#: qcsrc/menu/xonotic/serverlist.c:187 +msgid "Bookmark" +msgstr "Marcar" + +#: qcsrc/menu/xonotic/serverlist.c:527 +msgid "Ping" +msgstr "Ping" + +#: qcsrc/menu/xonotic/serverlist.c:528 +msgid "Host name" +msgstr "Nome do Host" + +#: qcsrc/menu/xonotic/serverlist.c:529 +msgid "Map" +msgstr "Mapa" + +#: qcsrc/menu/xonotic/serverlist.c:530 +msgid "Type" +msgstr "Tipo" + +#: qcsrc/menu/xonotic/serverlist.c:531 +msgid "Players" +msgstr "Jogadores" + +#: qcsrc/menu/xonotic/skinlist.c:105 +msgid "<TITLE>" +msgstr "<TÍTULO>" + +#: qcsrc/menu/xonotic/skinlist.c:106 +msgid "<AUTHOR>" +msgstr "<AUTOR>" + +#: qcsrc/menu/xonotic/slider_decibels.c:50 +msgid "VOL^OFF" +msgstr "DESLIGADO" + +#: qcsrc/menu/xonotic/slider_decibels.c:52 +msgid "VOL^MAX" +msgstr "MÀX" + +#: qcsrc/menu/xonotic/slider_decibels.c:53 +#, c-format +msgid "%s dB" +msgstr "%s dB" + +#: qcsrc/menu/xonotic/slider_resolution.c:65 +#, c-format +msgid "%dx%d" +msgstr "%dx%d" + +#: qcsrc/menu/xonotic/util.qc:270 +#, c-format +msgid "Received HTTP request data for an invalid id %d.\n" +msgstr "Recebido um pedido HTTP de um id inválido %d. \n" + +#: qcsrc/menu/xonotic/util.qc:285 +#, c-format +msgid "error receiving update notification: status is %d\n" +msgstr "erro ao receber notificação: o estado e %d\n" + +#: qcsrc/menu/xonotic/util.qc:290 +msgid "error: received HTML instead of an update notification\n" +msgstr "erro: recebido HTML em vez de notificação de actualização\n" + +#: qcsrc/menu/xonotic/util.qc:295 +msgid "error: received carriage returns from update notification server\n" +msgstr "" +"erro: recebido 'carriage return' de um servidor de notificação de " +"actualização\n" + +#: qcsrc/menu/xonotic/util.qc:316 +#, c-format +msgid "" +"Update can be downloaded at:\n" +"%s\n" +msgstr "" +"Actualização pode ser transferida em:\n" +"%s\n" + +#: qcsrc/menu/xonotic/util.qc:337 +msgid "Autogenerating mapinfo for newly added maps..." +msgstr "Informação de mapas auto-gerada para novos mapas..." + +#: qcsrc/menu/xonotic/util.qc:367 +#, c-format +msgid "^1%s TEST BUILD" +msgstr "^1%s VERSAO DE TESTE" + +#: qcsrc/menu/xonotic/util.qc:432 +#, c-format +msgid "Update to %s now!" +msgstr "Actualize para %s agora!" + +#: qcsrc/menu/xonotic/util.qc:501 +msgid "" +"^1ERROR: Texture compression is required but not supported.\n" +"^1Expect visual problems.\n" +msgstr "" +"^1ERRO: A compressão de texturas é necessária mas não é suportada.\n" +"^1Possíveis problemas visuais.\n" + +#: qcsrc/menu/xonotic/util.qc:523 +msgid "Arena" +msgstr "Arena" + +#: qcsrc/menu/xonotic/util.qc:524 +msgid "Assault" +msgstr "Assalto" + +#: qcsrc/menu/xonotic/util.qc:525 +msgid "Capture The Flag" +msgstr "Captura a Bandeira" + +#: qcsrc/menu/xonotic/util.qc:526 +msgid "Clan Arena" +msgstr "Clan Arena" + +#: qcsrc/menu/xonotic/util.qc:527 +msgid "Deathmatch" +msgstr "Combate até à Morte" + +#: qcsrc/menu/xonotic/util.qc:528 +msgid "Domination" +msgstr "Domínio" + +#: qcsrc/menu/xonotic/util.qc:529 +msgid "Freeze Tag" +msgstr "Freeze Tag" + +#: qcsrc/menu/xonotic/util.qc:530 +msgid "Keepaway" +msgstr "Keepaway" + +#: qcsrc/menu/xonotic/util.qc:531 +msgid "Key Hunt" +msgstr "Procura da Chave" + +#: qcsrc/menu/xonotic/util.qc:532 +msgid "Last Man Standing" +msgstr "O Ultimo a Cair" + +#: qcsrc/menu/xonotic/util.qc:533 +msgid "Nexball" +msgstr "Nexball" + +#: qcsrc/menu/xonotic/util.qc:534 +msgid "Onslaught" +msgstr "Investida" + +#: qcsrc/menu/xonotic/util.qc:535 +msgid "Race" +msgstr "Corrida" + +#: qcsrc/menu/xonotic/util.qc:536 +msgid "Race CTS" +msgstr "Corrida CTS" + +#: qcsrc/menu/xonotic/util.qc:537 +msgid "Runematch" +msgstr "Luta de Runas" + +#: qcsrc/menu/xonotic/util.qc:538 +msgid "Team Deathmatch" +msgstr "Combate até à Morte por Equipas" + +#: qcsrc/menu/xonotic/util.qc:557 +#, c-format +msgid "@!#%'n Tuba Throwing" +msgstr "@!#%'n Tuba Throwing" + +#: qcsrc/menu/xonotic/util.qc:577 qcsrc/menu/xonotic/util.qc:593 +#: qcsrc/menu/xonotic/util.qc:602 qcsrc/menu/xonotic/util.qc:610 +#: qcsrc/menu/xonotic/util.qc:622 +msgid "Default" +msgstr "Por Defeito" + +#: qcsrc/menu/xonotic/util.qc:588 +msgid "Use default" +msgstr "Usar defeito" + +#: qcsrc/menu/xonotic/util.qc:608 +msgid "Team Color:" +msgstr "Cor da Equipa:" + +#: qcsrc/menu/xonotic/util.qh:47 +msgid "Enable panel" +msgstr "Actival painel" + +#: qcsrc/server/w_crylink.qc:2 +msgid "Crylink" +msgstr "Crylink" + +#: qcsrc/server/w_crylink.qc:666 +#, c-format +msgid "%s succeeded at self-destructing themself with the Crylink" +msgstr "%s conseguiu auto-destruir-se com a Crylink" + +#: qcsrc/server/w_crylink.qc:671 +#, c-format +msgid "%s could not hide from %s's Crylink" +msgstr "%s não se conseguiu esconder da Crylink do %s" + +#: qcsrc/server/w_crylink.qc:673 +#, c-format +msgid "%s was too close to %s's Crylink" +msgstr "%s estava demasiado perto da Crylink do %s" + +#: qcsrc/server/w_crylink.qc:675 +#, c-format +msgid "%s took a close look at %s's Crylink" +msgstr "%s pode ver de perto a Crylink do %s" + +#: qcsrc/server/w_electro.qc:2 +msgid "Electro" +msgstr "Electro" + +#: qcsrc/server/w_electro.qc:574 +#, c-format +msgid "%s could not remember where they put plasma" +msgstr "%s não se conseguiu lembrar onde pôs a plasma" + +#: qcsrc/server/w_electro.qc:576 +#, c-format +msgid "%s played with plasma" +msgstr "%s brincou com plasma" + +#: qcsrc/server/w_electro.qc:583 +#, c-format +msgid "%s just noticed %s's blue ball" +msgstr "%s acabou de reparar na bola azul de %s" + +#: qcsrc/server/w_electro.qc:585 +#, c-format +msgid "%s got in touch with %s's blue ball" +msgstr "%s esteve em contacto com a bola azul de %s" + +#: qcsrc/server/w_electro.qc:590 +#, c-format +msgid "%s felt the electrifying air of %s's combo" +msgstr "%s sentiu o ar electrizante do combo de %s" + +#: qcsrc/server/w_electro.qc:592 +#, c-format +msgid "%s got too close to %s's blue beam" +msgstr "%s estava perto demais do raio azul de %s" + +#: qcsrc/server/w_electro.qc:594 +#, c-format +msgid "%s was blasted by %s's blue beam" +msgstr "%s foi atingido pelo raio azul de %s" + +#: qcsrc/server/w_fireball.qc:2 +msgid "Fireball" +msgstr "Fireball" + +#: qcsrc/server/w_fireball.qc:417 +#, c-format +msgid "%s forgot about some firemine" +msgstr "%s esqueceu-se das minas" + +#: qcsrc/server/w_fireball.qc:419 qcsrc/server/w_hlac.qc:240 +#, c-format +msgid "%s should have used a smaller gun" +msgstr "%s devia ter usado uma arma mais pequena" + +#: qcsrc/server/w_fireball.qc:426 +#, c-format +msgid "%s tried to catch %s's firemine" +msgstr "%s tentou apanhar a mina de %s" + +#: qcsrc/server/w_fireball.qc:428 +#, c-format +msgid "%s fatefully ignored %s's firemine" +msgstr "%s ignorou fatalmente a mina de %s" + +#: qcsrc/server/w_fireball.qc:435 +#, c-format +msgid "%s could not hide from %s's fireball" +msgstr "%s não se conseguiu esconder da bola de fogo de %s" + +#: qcsrc/server/w_fireball.qc:437 +#, c-format +msgid "%s saw the pretty lights of %s's fireball" +msgstr "%s viu a bela luminosidade da bola de fogo de %s" + +#: qcsrc/server/w_fireball.qc:440 +#, c-format +msgid "%s got too close to %s's fireball" +msgstr "%s estava demasiado perto da bola de fogo de %s" + +#: qcsrc/server/w_fireball.qc:442 +#, c-format +msgid "%s tasted %s's fireball" +msgstr "%s provou a bola de fogo de %s" + +#: qcsrc/server/w_grenadelauncher.qc:2 +msgid "Mortar" +msgstr "Mortar" + +#: qcsrc/server/w_grenadelauncher.qc:383 +#, c-format +msgid "%s tried out his own grenade" +msgstr "%s experimentou a sua própria granada" + +#: qcsrc/server/w_grenadelauncher.qc:385 +#, c-format +msgid "%s detonated" +msgstr "%s foi detonado" + +#: qcsrc/server/w_grenadelauncher.qc:391 +#, c-format +msgid "%s didn't see %s's grenade" +msgstr "%s não viu a granada de %s" + +#: qcsrc/server/w_grenadelauncher.qc:393 +#, c-format +msgid "%s almost dodged %s's grenade" +msgstr "%s quase se desviou da granada de %s" + +#: qcsrc/server/w_grenadelauncher.qc:395 +#, c-format +msgid "%s ate %s's grenade" +msgstr "%s comeu a granada de %s" + +#: qcsrc/server/w_hagar.qc:2 +msgid "Hagar" +msgstr "Hagar" + +#: qcsrc/server/w_hagar.qc:395 qcsrc/server/w_seeker.qc:655 +#, c-format +msgid "%s played with tiny rockets" +msgstr "%s brincou com pequenos foguetes" + +#: qcsrc/server/w_hagar.qc:399 +#, c-format +msgid "%s hoped %s's missiles wouldn't bounce" +msgstr "%s rezou para que os misseis de %s não resaltassem" + +#: qcsrc/server/w_hagar.qc:401 qcsrc/server/w_seeker.qc:661 +#, c-format +msgid "%s was pummeled by %s" +msgstr "%s foi serrado por %s" + +#: qcsrc/server/w_hlac.qc:2 +msgid "Heavy Laser Assault Cannon" +msgstr "Heavy Laser Assault Cannon" + +#: qcsrc/server/w_hlac.qc:242 +#, c-format +msgid "%s was cut down by %s" +msgstr "%s foi totalmente cortado por %s" + +#: qcsrc/server/w_hook.qc:2 +msgid "Grappling Hook" +msgstr "Grappling Hook" + +#: qcsrc/server/w_hook.qc:266 qcsrc/server/w_porto.qc:296 +#, c-format +msgid "%s did the impossible" +msgstr "%s fez o impossível" + +#: qcsrc/server/w_hook.qc:268 +#, c-format +msgid "%s has run into %s's gravity bomb" +msgstr "%s correu contra uma bomba gravitacional %s" + +#: qcsrc/server/w_laser.qc:2 +msgid "Laser" +msgstr "Laser" + +#: qcsrc/server/w_laser.qc:311 +#, c-format +msgid "%s lasered themself to hell" +msgstr "%s laserou-se até à morte" + +#: qcsrc/server/w_laser.qc:315 +#, c-format +msgid "%s was cut in half by %s's gauntlet" +msgstr "%s foi cortado ao meio pela gauntlet de %s" + +#: qcsrc/server/w_laser.qc:317 +#, c-format +msgid "%s was lasered to death by %s" +msgstr "%s foi lasereado até à morte por %s" + +#: qcsrc/server/w_minelayer.qc:2 +msgid "Mine Layer" +msgstr "Mine Layer" + +#: qcsrc/server/w_minelayer.qc:523 qcsrc/server/w_rocketlauncher.qc:501 +#, c-format +msgid "%s exploded" +msgstr "%s explodiu" + +#: qcsrc/server/w_minelayer.qc:527 +#, c-format +msgid "%s got too close to %s's mine" +msgstr "%s estava perto demais da mina de %s" + +#: qcsrc/server/w_minelayer.qc:529 +#, c-format +msgid "%s almost dodged %s's mine" +msgstr "%s quase se desviou da mina de %s" + +#: qcsrc/server/w_minelayer.qc:531 +#, c-format +msgid "%s stepped on %s's mine" +msgstr "%s pisou a mina de %s" + +#: qcsrc/server/w_minstanex.qc:2 +msgid "MinstaNex" +msgstr "MinstaNex" + +#: qcsrc/server/w_minstanex.qc:293 qcsrc/server/w_nex.qc:253 +#: qcsrc/server/w_shotgun.qc:215 qcsrc/server/w_uzi.qc:317 +#, c-format +msgid "%s is now thinking with portals" +msgstr "%s está agora a pensar com portais" + +#: qcsrc/server/w_minstanex.qc:295 qcsrc/server/w_nex.qc:255 +#, c-format +msgid "%s has been vaporized by %s" +msgstr "%s foi vaporizado por %s" + +#: qcsrc/server/w_nex.qc:2 +msgid "Nex" +msgstr "Nex" + +#: qcsrc/server/w_porto.qc:2 +msgid "Port-O-Launch" +msgstr "Port-O-Launch" + +#: qcsrc/server/w_porto.qc:298 +#, c-format +msgid "%s felt %s doing the impossible to him" +msgstr "%s sentiu %s fazer-lhe o impossível" + +#: qcsrc/server/w_rifle.qc:2 +msgid "Rifle" +msgstr "Espingarda" + +#: qcsrc/server/w_rifle.qc:233 +#, c-format +msgid "%s shot themself automatically" +msgstr "%s disparou em si próprio" + +#: qcsrc/server/w_rifle.qc:235 +#, c-format +msgid "%s sniped themself somehow" +msgstr "%s snipou-se de alguma forma..." + +#: qcsrc/server/w_rifle.qc:242 +#, c-format +msgid "%s failed to hide from %s's bullet hail" +msgstr "%s não se conseguiu esconder da chuva de balas de %s" + +#: qcsrc/server/w_rifle.qc:244 +#, c-format +msgid "%s died in %s's bullet hail" +msgstr "%s morreu na chuva de balas de %s" + +#: qcsrc/server/w_rifle.qc:251 +#, c-format +msgid "%s failed to hide from %s's rifle" +msgstr "%s não se conseguiu esconder da espingarda de %s" + +#: qcsrc/server/w_rifle.qc:256 +#, c-format +msgid "%s got hit in the head by %s" +msgstr "%s foi atingido na cabeça por %s" + +#: qcsrc/server/w_rifle.qc:258 qcsrc/server/w_uzi.qc:321 +#, c-format +msgid "%s was sniped by %s" +msgstr "%s foi snipado por %s" + +#: qcsrc/server/w_rocketlauncher.qc:2 +msgid "Rocket Launcher" +msgstr "Rocket Launcher" + +#: qcsrc/server/w_rocketlauncher.qc:505 +#, c-format +msgid "%s got too close to %s's rocket" +msgstr "%s estava demasiado perto do foguete de %s" + +#: qcsrc/server/w_rocketlauncher.qc:507 +#, c-format +msgid "%s almost dodged %s's rocket" +msgstr "%s quase se desviou do foguete de %s" + +#: qcsrc/server/w_rocketlauncher.qc:509 +#, c-format +msgid "%s ate %s's rocket" +msgstr "%s comeu o foguete de %s" + +#: qcsrc/server/w_seeker.qc:2 +msgid "T.A.G. Seeker" +msgstr "T.A.G. Seeker" + +#: qcsrc/server/w_seeker.qc:659 +#, c-format +msgid "%s was tagged by %s" +msgstr "%s foi marcado por %s" + +#: qcsrc/server/w_shotgun.qc:2 +msgid "Shotgun" +msgstr "Shotgun" + +#: qcsrc/server/w_shotgun.qc:219 +#, c-format +msgid "%2$s ^7slapped %1$s ^7around a bit with a large ^2shotgun" +msgstr "%2$s ^7maltratou %1$s ^7com uma grande ^2caçadeira" + +#: qcsrc/server/w_shotgun.qc:221 +#, c-format +msgid "%s was gunned by %s" +msgstr "%s foi atingido por %s" + +#: qcsrc/server/w_tuba.qc:2 +#, c-format +msgid "@!#%'n Tuba" +msgstr "@!#%'n Tuba" + +#: qcsrc/server/w_tuba.qc:252 +#, c-format +msgid "%s hurt his own ears with the @!#%%'n Tuba" +msgstr "%s magoou-se a si próprio com a Tuba" + +#: qcsrc/server/w_tuba.qc:256 +#, c-format +msgid "%s died of %s's great playing on the @!#%%'n Tuba" +msgstr "%s morreu por causa da grande actuação de %s" + +#: qcsrc/server/w_uzi.qc:2 +msgid "Machine Gun" +msgstr "Machine Gun" + +#: qcsrc/server/w_uzi.qc:323 +#, c-format +msgid "%s was riddled full of holes by %s" +msgstr "%s foi enchido de buracos por %s" diff --git a/menu.dat.ro.po b/menu.dat.ro.po new file mode 100644 index 0000000000..7d08c49173 --- /dev/null +++ b/menu.dat.ro.po @@ -0,0 +1,2913 @@ +# Xonotic Romanian Translation. +# Copyright (C) 2011 +# This file is distributed under the same license as the PACKAGE package. +# MirceaKitsune <sonichedgehog_hyperblast00@yahoo.com>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: Xonotic 0.1preview\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-09-02 07:51+0200\n" +"PO-Revision-Date: 2011-01-18 11:53+0100\t\n" +"Last-Translator: MirceaKitsune <sonichedgehog_hyperblast00@yahoo.com>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: ro\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: qcsrc/common/mapinfo.qc:1092 qcsrc/menu/xonotic/skinlist.c:163 +#, c-format +msgid "%s: %s" +msgstr "%s: %s" + +#: qcsrc/menu/gamecommand.qc:47 +#, c-format +msgid "error: status is %d\n" +msgstr "eroare: statusul este %d\n" + +#: qcsrc/menu/gamecommand.qc:65 +msgid "Usage: menu_cmd command..., where possible commands are:\n" +msgstr "Utilizare: menu_cmd comanda..., unde comenzile posibile sunt:\n" + +#: qcsrc/menu/gamecommand.qc:66 +msgid " sync - reloads all cvars on the current menu page\n" +msgstr " sync - reincarca toate variabilele de pe pagina de meniu curenta\n" + +#: qcsrc/menu/gamecommand.qc:67 +msgid " directmenu ITEM - select a menu item as main item\n" +msgstr "" +" directmenu OBIECT - selecteaza un obiect din meniu ca obiect principal\n" + +#: qcsrc/menu/gamecommand.qc:193 +msgid "error creating curl handle\n" +msgstr "eroare in crearea unei manevre curl" + +#: qcsrc/menu/gamecommand.qc:239 +msgid "Invalid command. For a list of supported commands, try menu_cmd help.\n" +msgstr "" +"Comanda invalida. Pentru o lista cu comenzile suportate, scrieti menu_cmd " +"ajutor (in consola).\n" + +#: qcsrc/menu/item/gecko.c:49 +msgid "Browser not initialized!" +msgstr "Browserul nu a fost initializat!" + +#: qcsrc/menu/item/label.c:63 +#, c-format +msgid "NOTE: label text %s too wide for label, condensed by factor %f\n" +msgstr "ATENTIE: eticheta text %s este prea mare, condensata cu %f\n" + +#: qcsrc/menu/item/listbox.c:300 +#, c-format +msgid "Item %d" +msgstr "Obiect %d" + +#: qcsrc/menu/item/slider.c:64 +#, c-format +msgid "%d (%s)" +msgstr "%d (%s)" + +#: qcsrc/menu/item/textslider.c:29 qcsrc/menu/item/textslider.c:31 +msgid "custom" +msgstr "personalizat" + +#: qcsrc/menu/menu.qc:29 +#, c-format +msgid "^4MQC Build information: ^1%s\n" +msgstr "^4MQC Informatii compilare: %s\n" + +#: qcsrc/menu/xonotic/campaign.c:284 +#: qcsrc/menu/xonotic/dialog_singleplayer.c:134 +msgid "???" +msgstr "???" + +#: qcsrc/menu/xonotic/campaign.c:285 +#, c-format +msgid "Level %d: %s" +msgstr "Nivelul %d: %s" + +#: qcsrc/menu/xonotic/cvarlist.c:85 +msgid "will be saved to config.cfg" +msgstr "se va salva catre config.cfg" + +#: qcsrc/menu/xonotic/cvarlist.c:87 +msgid "will not be saved" +msgstr "nu se va salva" + +#: qcsrc/menu/xonotic/cvarlist.c:89 +msgid "private" +msgstr "privat" + +#: qcsrc/menu/xonotic/cvarlist.c:91 +msgid "engine setting" +msgstr "setari motor" + +#: qcsrc/menu/xonotic/cvarlist.c:93 +msgid "read only" +msgstr "numai de citit" + +#: qcsrc/menu/xonotic/dialog_credits.c:5 +msgid "Credits" +msgstr "Credite" + +#: qcsrc/menu/xonotic/dialog_credits.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:269 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:41 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:57 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:61 +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:21 +msgid "OK" +msgstr "OK" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:4 +msgid "Welcome" +msgstr "Bun venit" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:33 +msgid "" +"Welcome to Xonotic, please select your language preference and enter your " +"player name to get started. You can change these options later through the " +"menu system." +msgstr "" +"Bine ati venit in Xonotic, va rugam selectati limba dorita si numele " +"dumneavoastra de jucator pentru a incepe. Puteti schimba aceste preferinte " +"mai tarziu din cadrul meniului." + +#: qcsrc/menu/xonotic/dialog_firstrun.c:38 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:35 +msgid "Text language:" +msgstr "Limba text:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:47 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:40 +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:39 +msgid "Name:" +msgstr "Nume:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:69 +msgid "Save settings" +msgstr "Salvare setari" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:4 +msgid "Ammo Panel" +msgstr "Fereastra Munitii" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:22 +msgid "Ammunition display:" +msgstr "Afisaj mutitii:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:25 +msgid "Show only current ammo type" +msgstr "Afiseaza numai munitia armei selectate" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:28 +msgid "Align icon:" +msgstr "Aliniere icon:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:29 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:36 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:40 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:40 +msgid "Left" +msgstr "Stanga" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:38 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:41 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:41 +msgid "Right" +msgstr "Dreapta" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:4 +msgid "Centerprint" +msgstr "Text centru" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:23 +msgid "Message duration:" +msgstr "Durata mesaj:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:27 +msgid "Fade time:" +msgstr "Durata atenuare:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:31 +msgid "Flip messages order" +msgstr "Inversare ordine mesaje" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:33 +msgid "Text alignment:" +msgstr "Aliniere text:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:37 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:50 +msgid "Center" +msgstr "Centru:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:41 +msgid "Font scale:" +msgstr "Marime font:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:4 +msgid "Chat Panel" +msgstr "Fereastra Chat" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:22 +msgid "Chat entries:" +msgstr "Intrari chat:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:25 +msgid "Chat size:" +msgstr "Marime chat:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:29 +msgid "Chat lifetime:" +msgstr "Durata chat:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:33 +msgid "Chat beep sound" +msgstr "Sunet chat:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:4 +msgid "Engine Info Panel" +msgstr "Fereastra Informatii Motor" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:22 +msgid "Engine info:" +msgstr "Informatii motor:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:25 +msgid "Use an averaging algorithm for fps" +msgstr "Utilizare algoritm centrare FPS" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:4 +msgid "Health/Armor Panel" +msgstr "Fereastra Viata/Armura" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:22 +msgid "Enable status bar" +msgstr "Activare bara de statut" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:24 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:24 +msgid "Status bar alignment:" +msgstr "Aliniere bara de statut:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:42 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:42 +msgid "Inward" +msgstr "Interior" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:43 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:43 +msgid "Outward" +msgstr "Exterior" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:37 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:37 +msgid "Icon alignment:" +msgstr "Aliniere iconuri:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:45 +msgid "Flip health and armor positions" +msgstr "Oglindire pozitie viata/armura" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:4 +msgid "Info Messages Panel" +msgstr "Fereastra Informatii" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:22 +msgid "Info messages:" +msgstr "Informatii:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:25 +msgid "Flip align" +msgstr "Oglindire pozitie" + +#: qcsrc/menu/xonotic/dialog_hudpanel_modicons.c:4 +msgid "Mod Icons Panel" +msgstr "Fereastra Iconuri Moduri" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:4 +msgid "Notification Panel" +msgstr "Fereastra Notificatii" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:22 +msgid "Notifications:" +msgstr "Notificatii:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:25 +msgid "Also print notifications to the console" +msgstr "Printare notificatii si in consola" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:28 +msgid "Flip notify order" +msgstr "Inversare ordine notificatii" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:31 +msgid "Entry lifetime:" +msgstr "Durata notificare:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:35 +msgid "Entry fadetime:" +msgstr "Durata atenuare notificatie:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:4 +msgid "Physics Panel" +msgstr "Panou Fizici" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:21 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:21 +msgid "Panel disabled" +msgstr "Dezactivata" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:23 +msgid "Panel enabled" +msgstr "Panou activ" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:24 +msgid "Panel enabled even observing" +msgstr "Panou activ si spectatorilor" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:25 +msgid "Panel enabled only in Race/CTS" +msgstr "Panou activ numai in Cursa/CTS" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:31 +msgid "Status bar" +msgstr "Bara statut" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:48 +msgid "Left align" +msgstr "Aliniere stanga" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:34 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:52 +msgid "Right align" +msgstr "Aliniere dreapta" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:35 +msgid "Inward align" +msgstr "Aliniere interioara" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:36 +msgid "Outward align" +msgstr "Aliniere exterioara" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:40 +msgid "Flip speed/acceleration positions" +msgstr "Inversare pozitie viteza/acceleratie" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:44 +msgid "Speed:" +msgstr "Viteza:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:45 +msgid "Include vertical speed" +msgstr "Include viteza verticala" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:56 +msgid "Speed unit:" +msgstr "Unitate viteza" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:58 +msgid "qu/s" +msgstr "qu/s" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:59 +msgid "m/s" +msgstr "m/s" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:60 +msgid "km/h" +msgstr "km/h" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:61 +msgid "mph" +msgstr "mph" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:62 +msgid "knots" +msgstr "noduri" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:64 +msgid "Show" +msgstr "Afiseaza" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:67 +msgid "Top speed" +msgstr "Viteza maxima:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:73 +msgid "Acceleration:" +msgstr "Acceleratie:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:74 +msgid "Include vertical acceleration" +msgstr "Include acceleratia verticala" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:4 +msgid "Powerups Panel" +msgstr "Fereastra Powerup" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:45 +msgid "Flip strength and shield positions" +msgstr "Oglindire pozitie iconuri" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:4 +msgid "Pressed Keys Panel" +msgstr "Fereastra Taste Apasate" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:22 +msgid "Panel enabled when spectating" +msgstr "Activa pentru spectatori" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:23 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:23 +msgid "Panel always enabled" +msgstr "Mereu activa" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:30 +msgid "Forced aspect:" +msgstr "Aspect fortat:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_racetimer.c:4 +msgid "Race Timer Panel" +msgstr "Fereastra Timp Curse" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:4 +msgid "Radar Panel" +msgstr "Fereastra Radar" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:22 +msgid "Panel enabled in teamgames" +msgstr "Activa in jocuri de echipa" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:29 +msgid "Radar:" +msgstr "Radar:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:32 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:43 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:154 +#: qcsrc/menu/xonotic/util.qc:600 +msgid "Alpha:" +msgstr "Opacitate:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:36 +msgid "Rotation:" +msgstr "Rotatie:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:38 +msgid "Forward" +msgstr "Inainte" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:39 +msgid "West" +msgstr "Vest" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:40 +msgid "South" +msgstr "Sud" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:41 +msgid "East" +msgstr "Est" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:42 +msgid "North" +msgstr "Nord" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:46 +msgid "Scale:" +msgstr "Marime:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:50 +msgid "Zoom mode:" +msgstr "Modalitate Zoom:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:52 +msgid "Zoomed in" +msgstr "In interior" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:53 +msgid "Zoomed out" +msgstr "In exterior" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:54 +msgid "Always zoomed" +msgstr "Permanent activ" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:55 +msgid "Never zoomed" +msgstr "Niciodata activ" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:4 +msgid "Score Panel" +msgstr "Fereastra Scor" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:22 +msgid "Score:" +msgstr "Scor:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:25 +msgid "Rankings:" +msgstr "Clasificari:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:26 +msgid "Off" +msgstr "Dezactivat" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:27 +msgid "And me" +msgstr "Si eu" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:28 +msgid "Pure" +msgstr "Pur" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:4 +msgid "Timer Panel" +msgstr "Fereastra Timp" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:22 +msgid "Timer:" +msgstr "Timp:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:25 +msgid "Show elapsed time" +msgstr "Afisaj timp ramas" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:4 +msgid "Vote Panel" +msgstr "Fereastra Voturi" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:22 +msgid "Alpha after voting:" +msgstr "Opacitate dupa vot:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:4 +msgid "Weapons Panel" +msgstr "Fereastra Arme" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:24 +msgid "Fade out after:" +msgstr "Atenuare opacitate dupa:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:26 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:36 +msgid "Never" +msgstr "Niciodata" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:28 +#, c-format +msgid "%ds" +msgstr "%ds" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:32 +msgid "Fade effect:" +msgstr "Atenuare opacitate:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:35 +msgid "EF^None" +msgstr "Nici una" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:36 +msgid "Slide" +msgstr "Glisare" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:37 +msgid "Alpha" +msgstr "Opacitate" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:38 +msgid "EF^Both" +msgstr "Ambele" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:42 +msgid "Weapon icons:" +msgstr "Iconuri arme:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:45 +msgid "Show weapon ID as:" +msgstr "Afisaj ID arme ca:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:46 +msgid "SHOWAS^None" +msgstr "Nici una" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:47 +msgid "Number" +msgstr "Numar" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:48 +msgid "Bind" +msgstr "Tasta" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:51 +msgid "Show Accuracy" +msgstr "Afisaj Acuratete" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:52 +msgid "Show Ammo" +msgstr "Afisaj Munitie" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:55 +msgid "Ammo bar color:" +msgstr "Culoare bara munitie:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:61 +msgid "Ammo bar alpha:" +msgstr "Opacitate bara munitie:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:4 +msgid "Panel HUD Setup" +msgstr "Configurate Interfata (HUD)" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:21 +msgid "Panel background defaults:" +msgstr "Setari normale fond:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:23 qcsrc/menu/xonotic/util.qc:575 +msgid "Background:" +msgstr "Fundal:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:25 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:37 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:52 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:91 qcsrc/menu/xonotic/util.qc:578 +#: qcsrc/menu/xonotic/util.qc:594 qcsrc/menu/xonotic/util.qc:611 +msgid "Disable" +msgstr "Dezactivat" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:30 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:77 qcsrc/menu/xonotic/util.qc:583 +msgid "Color:" +msgstr "Culoare:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:35 qcsrc/menu/xonotic/util.qc:591 +msgid "Border size:" +msgstr "Marime borduri:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:50 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:89 +msgid "Team color:" +msgstr "Culoare echipa:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:58 qcsrc/menu/xonotic/util.qc:617 +msgid "Test team color in configure mode" +msgstr "Testare culoare echipa in timpul configurarii" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:61 qcsrc/menu/xonotic/util.qc:620 +msgid "Padding:" +msgstr "Ajustare:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:68 +msgid "HUD Dock:" +msgstr "Magnet ferestre:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:70 +msgid "DOCK^Disabled" +msgstr "Dezactivat" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:71 +msgid "DOCK^Small" +msgstr "Mic" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:72 +msgid "DOCK^Medium" +msgstr "Mediu" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:73 +msgid "DOCK^Large" +msgstr "Mare" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:96 +msgid "Grid settings:" +msgstr "Setari grila:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:99 +msgid "Snap panels to grid" +msgstr "Utilizare grila pentru ferestre" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:102 +msgid "Grid size:" +msgstr "Marime grila:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:103 +msgid "X:" +msgstr "X:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:109 +msgid "Y:" +msgstr "Y:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:117 +msgid "Exit setup" +msgstr "Iesire configurare" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:4 +msgid "Multiplayer" +msgstr "Multiplayer" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:18 +msgid "Servers" +msgstr "Servere" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:19 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:5 +msgid "Create" +msgstr "Creare Joc" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:20 +msgid "Demos" +msgstr "Demonstratii" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:5 +msgid "Player Setup" +msgstr "Setari Jucator" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:34 +msgid "Game type:" +msgstr "Mod joc:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:46 +msgid "Match settings:" +msgstr "Setari meci:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:49 +msgid "Time limit:" +msgstr "Limita de timp:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:53 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:61 +msgid "Use map specified default" +msgstr "Utilizare setari harta" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:56 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:155 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:156 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:157 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:161 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:162 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:163 +msgid "Point limit:" +msgstr "Limita de puncte:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:64 +msgid "Player slots:" +msgstr "Numar maxim jucatori:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:67 +msgid "Number of bots:" +msgstr "Numar boti:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:71 +msgid "Bot skill:" +msgstr "Dificultate boti:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:74 +msgid "Botlike" +msgstr "Nula" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:75 +msgid "Beginner" +msgstr "Incepator" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:76 +msgid "You will win" +msgstr "Vei castiga" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:77 +msgid "You can win" +msgstr "Poti castiga" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:78 +msgid "You might win" +msgstr "Ai putea castiga" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:79 +msgid "Advanced" +msgstr "Avansat" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:80 +msgid "Expert" +msgstr "Expert" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:81 +msgid "Pro" +msgstr "Profesional" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:82 +msgid "Assassin" +msgstr "Asasin" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:83 +msgid "Unhuman" +msgstr "Inuman" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:84 +msgid "Godlike" +msgstr "Dumnezeiesc" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:88 +msgid "Mutators..." +msgstr "Modificari speciale..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:97 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:57 +msgid "Advanced settings..." +msgstr "Setari avansate..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:104 +msgid "Map list:" +msgstr "Lista harti:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:110 +msgid "Select all" +msgstr "Selecteaza totul" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:113 +msgid "Select none" +msgstr "Golire selectie" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:119 +msgid "Start Multiplayer!" +msgstr "Pornire Joc Multiplayer!" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:154 +msgid "Capture limit:" +msgstr "Limita de capturi:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:158 +msgid "Lives:" +msgstr "Vieti:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:159 +msgid "Laps:" +msgstr "Ture:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:160 +msgid "Goals:" +msgstr "Goluri:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:164 +msgid "Frag limit:" +msgstr "Limita de omoruri:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:6 +msgid "Advanced server settings" +msgstr "Setari avansate server" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:25 +msgid "Game settings:" +msgstr "Setari joc" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:28 +msgid "Allow spectating" +msgstr "Perimite spectatori" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:31 +msgid "Spawn shield:" +msgstr "Scut pornire:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:36 +msgid "Game speed:" +msgstr "Viteza joc:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:40 +msgid "Teamplay settings:" +msgstr "Setari echipe:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:43 +msgid "Friendly fire scale:" +msgstr "Scara foc prietenesc:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:47 +msgid "Virtual friendly fire (effect only)" +msgstr "Foc prietenesc virtual (efect)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:50 +msgid "Friendly fire penalty:" +msgstr "Penalitate foc prietenesc:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:54 +msgid "Virtual penalty (effect only)" +msgstr "Penalitate virtuala (efect)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:57 +msgid "Teams:" +msgstr "Echipe:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:66 +msgid "Map voting:" +msgstr "Vot harti:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:68 +msgid "No voting" +msgstr "Vot dezactivat" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:69 +msgid "2 choices" +msgstr "2 alegeri" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:70 +msgid "3 choices" +msgstr "3 alegeri" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:71 +msgid "4 choices" +msgstr "4 alegeri" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:72 +msgid "5 choices" +msgstr "5 alegeri" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:73 +msgid "6 choices" +msgstr "6 alegeri" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:74 +msgid "7 choices" +msgstr "7 alegeri" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:75 +msgid "8 choices" +msgstr "8 alegeri" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:76 +msgid "9 choices" +msgstr "9 alageri" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:79 +msgid "Simple majority wins vcall" +msgstr "Majoritatea castiga mereu" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:5 +msgid "Map Information" +msgstr "Informatii harta:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "Full item placement" +msgstr "Plasare obiecte" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "MinstaGib only" +msgstr "Numai MinstaGib" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:78 +msgid "Title:" +msgstr "Titlu:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:84 +msgid "Author:" +msgstr "Autor:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:90 +msgid "Features:" +msgstr "Trasaturi:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:95 +msgid "Game types:" +msgstr "Moduri de joc:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:118 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:314 +msgid "Close" +msgstr "Inchidere" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:121 +msgid "MAP^Play" +msgstr "Joaca" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:7 +msgid "Mutators" +msgstr "Modificari speciale" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:33 +msgid "All Weapons Arena" +msgstr "Toate armele" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:35 +msgid "Most Weapons Arena" +msgstr "Cele mai multe arme" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:56 +#, c-format +msgid "%s Arena" +msgstr "Arena %s" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:68 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:167 +msgid "Dodging" +msgstr "Satiruta laterala" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:70 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:250 +msgid "MinstaGib" +msgstr "MinstaGib" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:253 +msgid "NIX" +msgstr "NIX" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:74 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:205 +msgid "Rocket Flying" +msgstr "Zbor Rachete" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:78 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:264 +msgid "No start weapons" +msgstr "Fara arme initiale" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:80 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:189 +msgid "Low gravity" +msgstr "Gravitatie scazuta" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:170 +msgid "Cloaked" +msgstr "Jucatori transparenti" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:84 +msgid "Hook" +msgstr "Carlig" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:86 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:173 +msgid "Midair" +msgstr "Lovituri in aer" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:88 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:176 +msgid "Vampire" +msgstr "Vampir" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:90 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:208 +msgid "Piñata" +msgstr "Piñata" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:92 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:211 +msgid "Weapons stay" +msgstr "Arme persistente" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:94 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:180 +msgid "Blood loss" +msgstr "Pierdere de sange" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:96 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:202 +msgid "Jet pack" +msgstr "Reactie" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:98 +msgid "MUT^None" +msgstr "Nici una" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:164 +msgid "Gameplay mutators:" +msgstr "Modificari speciale joc:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:196 +msgid "Weapon & item mutators:" +msgstr "Modificari speciale arme si obiecte:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:199 +msgid "Grappling hook" +msgstr "Carlig" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:215 +msgid "Weapon arenas:" +msgstr "Arene arme:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:218 +msgid "Regular (no arena)" +msgstr "Normal (fara arene)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:239 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:256 +msgid "with laser" +msgstr "cu arma laser" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:247 +msgid "Special arenas:" +msgstr "Arene speciale:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:260 +msgid "Most weapons" +msgstr "Majoritatea armelor" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:4 +msgid "Demo" +msgstr "Demonstratie" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:28 +msgid "Record demos while playing" +msgstr "Creare demonstratii in timpul jocului" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:32 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:28 +msgid "Filter:" +msgstr "Filtrare:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:29 +#: qcsrc/menu/xonotic/dialog_settings_input.c:41 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:24 +msgid "Clear" +msgstr "Curatare" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:43 +msgid "Timedemo" +msgstr "Timedemo" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:46 +msgid "DEMO^Play" +msgstr "Vizualizare" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:4 +msgid "Join" +msgstr "Alaturare" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:36 +msgid "SRVS^Empty" +msgstr "Gol" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:40 +msgid "SRVS^Full" +msgstr "Plin" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:44 +msgid "Pause" +msgstr "Pauza" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:56 +msgid "Address:" +msgstr "Adresa:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:67 +msgid "Info..." +msgstr "Informatii..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:317 +msgid "Join!" +msgstr "Alaturare!" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:5 +msgid "Server Information" +msgstr "Informatii Server" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:115 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:116 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:183 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:189 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:199 +msgid "N/A" +msgstr "N/A" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:158 +#, c-format +msgid "%d/%d, %d free player slots" +msgstr "%d/%d, %d locuri disponibile" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +#, c-format +msgid "%d modified settings" +msgstr "%d setari modificate" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +msgid "Official settings" +msgstr "Setarile oficiale" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:197 +msgid "N/A (can't connect)" +msgstr "N/A (nu se poate conecta)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:205 +msgid "not supported (can't connect)" +msgstr "nesuportat (nu se poate conecta)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:207 +msgid "not supported (won't encrypt)" +msgstr "nesuportat (nu se poate encripta)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:211 +msgid "supported (will encrypt)" +msgstr "suportat (se va encripta)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:213 +msgid "supported (won't encrypt)" +msgstr "suportat (nu se va encripta)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:217 +msgid "requested (will encrypt)" +msgstr "cerut (se va encripta)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:219 +msgid "requested (won't encrypt)" +msgstr "cerut (nu se va encripta)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:223 +msgid "required (can't connect)" +msgstr "necesar (nu se poate conecta)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:225 +msgid "required (will encrypt)" +msgstr "necesar (se va encripta)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:246 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:269 +msgid "Players:" +msgstr "Jucatori:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:254 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:38 +msgid "Type:" +msgstr "Tip:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:259 +msgid "Map:" +msgstr "Harta:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:264 +msgid "Gameplay:" +msgstr "Mod:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:274 +msgid "Bots:" +msgstr "Boti:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:279 +msgid "Mod:" +msgstr "Modificare:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:284 +msgid "Version:" +msgstr "Versiune:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:289 +msgid "Ping:" +msgstr "Latenta:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:295 +msgid "CA:" +msgstr "CA:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:301 +msgid "Key:" +msgstr "Cheie:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:307 +msgid "Encryption:" +msgstr "Encriptare:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:63 +msgid "Model:" +msgstr "Model:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:88 +msgid "Field of view:" +msgstr "Camp vizual:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:92 +msgid "View bobbing:" +msgstr "Miscare camera mers:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:96 +msgid "Zoom factor:" +msgstr "Factor Zoom:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:100 +msgid "Zoom speed:" +msgstr "Viteza Zoom:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:103 +msgid "Weapon settings..." +msgstr "Setari arme..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:110 +msgid "Crosshair:" +msgstr "Ochian:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:111 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:139 +msgid "Per weapon" +msgstr "Depinde de arma" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:130 +msgid "Crosshair size:" +msgstr "Marime ochian:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:134 +msgid "Crosshair alpha:" +msgstr "Opacitate ochian:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:138 +msgid "Crosshair color:" +msgstr "Culoare ochian:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:140 +msgid "By health" +msgstr "Dupa sanatate" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:143 +msgid "Custom" +msgstr "personalizat" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:148 +msgid "Enable center dot" +msgstr "Utilizare punct ochian" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:151 +msgid "Size:" +msgstr "Marime:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:158 +msgid "Hit test:" +msgstr "Detectare tinta:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:159 +msgid "HTST^None" +msgstr "Nici una" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:160 +msgid "TrueAim" +msgstr "TrueAim" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:161 +msgid "Enemies" +msgstr "Dusmani" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:164 +msgid "Waypoints setup..." +msgstr "Setari indicatoare..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:169 +msgid "Enter HUD editor" +msgstr "Editor interfata" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:174 +msgid "Force models:" +msgstr "Modele jucator fortate:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:175 +msgid "MDL^None" +msgstr "Nici una" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:176 +msgid "MDL^Custom" +msgstr "Personalizat" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:177 +msgid "MDL^All" +msgstr "Toate" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:180 +msgid "Disable gore effects" +msgstr "Dezactivare efecte violente" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:182 +msgid "Gibs:" +msgstr "Cotlete:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:184 +msgid "GIBS^None" +msgstr "Nici unul" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:185 +msgid "GIBS^Few" +msgstr "Putine" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:186 +msgid "GIBS^Many" +msgstr "Multe" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:187 +msgid "GIBS^Lots" +msgstr "Foarte multe" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:191 +msgid "Damage splash:" +msgstr "Efect ranire:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:195 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:173 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:194 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:30 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:41 +#: qcsrc/menu/xonotic/dialog_settings_video.c:109 +msgid "Apply immediately" +msgstr "Aplica imediat" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:5 +msgid "Waypoints" +msgstr "Indicatoare" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:23 +msgid "Show base waypoints" +msgstr "Afisaj indicatoare de baza" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:25 +msgid "Waypoint scale:" +msgstr "Marime indicatoare:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:29 +msgid "Waypoint alpha:" +msgstr "Opacitate indicatoare:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:34 +msgid "Show names:" +msgstr "Afisaj nume:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:37 +msgid "Teammates" +msgstr "Coechipieri" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:38 +msgid "All players" +msgstr "Toti jucatorii" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:6 +msgid "Weapon settings" +msgstr "Setari arme" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:29 +msgid "Weapon priority list:" +msgstr "Lista prioritate arme:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:34 +msgid "Up" +msgstr "Sus" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:37 +msgid "Down" +msgstr "Jos" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:41 +msgid "Use priority list for weapon cycling" +msgstr "Utilizare lista pentru selectarea armelor" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:43 +msgid "Auto switch weapons on pickup" +msgstr "Selectare automata a armelor obtinute" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:45 +msgid "Draw 1st person weapon model" +msgstr "Afisaj model 1st person" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:55 +msgid "Flip view horizontally" +msgstr "Oglindire orizontala ecran" + +#: qcsrc/menu/xonotic/dialog_news.c:4 +msgid "News" +msgstr "Stiri" + +#: qcsrc/menu/xonotic/dialog_news.c:18 +msgid "http://www.xonotic.org/team/blog/" +msgstr "http://www.xonotic.org/team/blog/" + +#: qcsrc/menu/xonotic/dialog_quit.c:4 +msgid "Quit" +msgstr "Iesire" + +#: qcsrc/menu/xonotic/dialog_quit.c:17 +msgid "Are you sure you want to quit?" +msgstr "Sunteti sigur ca vreti sa iesiti?" + +#: qcsrc/menu/xonotic/dialog_quit.c:20 +msgid "Yes" +msgstr "Da" + +#: qcsrc/menu/xonotic/dialog_quit.c:21 +msgid "No" +msgstr "Nu" + +#: qcsrc/menu/xonotic/dialog_settings.c:4 +msgid "Settings" +msgstr "Setari" + +#: qcsrc/menu/xonotic/dialog_settings.c:18 +#: qcsrc/menu/xonotic/dialog_settings_input.c:4 +msgid "Input" +msgstr "Control" + +#: qcsrc/menu/xonotic/dialog_settings.c:19 +#: qcsrc/menu/xonotic/dialog_settings_video.c:4 +msgid "Video" +msgstr "Video" + +#: qcsrc/menu/xonotic/dialog_settings.c:20 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:4 +msgid "Effects" +msgstr "Efecte" + +#: qcsrc/menu/xonotic/dialog_settings.c:21 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:4 +msgid "Audio" +msgstr "Audio" + +#: qcsrc/menu/xonotic/dialog_settings.c:22 +#: qcsrc/menu/xonotic/dialog_settings_network.c:4 +msgid "Network" +msgstr "Retea" + +#: qcsrc/menu/xonotic/dialog_settings.c:23 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:4 +msgid "Misc" +msgstr "Altele" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:27 +msgid "Master:" +msgstr "General:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:33 +msgid "Music:" +msgstr "Muzica:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:41 +msgid "VOL^Ambient:" +msgstr "Ambianta:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:48 +msgid "Info:" +msgstr "Informatii:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:55 +msgid "Items:" +msgstr "Obiecte:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:62 +msgid "Pain:" +msgstr "Durere:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:69 +msgid "Player:" +msgstr "Jucator:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:76 +msgid "Shots:" +msgstr "Focuri de arma:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:83 +msgid "Voice:" +msgstr "Voci:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:91 +msgid "Weapons:" +msgstr "Arme:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:98 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:156 +msgid "Frequency:" +msgstr "Frecventa:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:100 +msgid "8 kHz" +msgstr "8 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:101 +msgid "11.025 kHz" +msgstr "11.025 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:102 +msgid "16 kHz" +msgstr "16 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:103 +msgid "22.05 kHz" +msgstr "22.05 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:104 +msgid "24 kHz" +msgstr "24 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:105 +msgid "32 kHz" +msgstr "32 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:106 +msgid "44.1 kHz" +msgstr "44.1 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:107 +msgid "48 kHz" +msgstr "48 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:110 +msgid "Channels:" +msgstr "Canale:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:112 +msgid "Mono" +msgstr "Mono" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:113 +msgid "Stereo" +msgstr "Stereo" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:114 +msgid "2.1" +msgstr "2.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:115 +msgid "4" +msgstr "4" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:116 +msgid "5" +msgstr "5" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:117 +msgid "5.1" +msgstr "5.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:118 +msgid "6.1" +msgstr "6.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:119 +msgid "7.1" +msgstr "7.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:123 +msgid "Swap Stereo" +msgstr "Inversare canale stereo" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:127 +msgid "Headphone friendly mode" +msgstr "Mod casti audio" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:131 +msgid "Spatial voices:" +msgstr "Voci spatializate:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:132 +msgid "VOCS^None" +msgstr "Nici una" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:133 +msgid "VOCS^Taunts" +msgstr "Glume" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:134 +msgid "VOCS^All" +msgstr "Toate" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:137 +msgid "Taunt range:" +msgstr "Distanta voci:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:140 +msgid "RNG^Very short" +msgstr "Foarte scurta" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:141 +msgid "RNG^Short" +msgstr "Scurta" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:142 +msgid "RNG^Normal" +msgstr "Normala" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:143 +msgid "RNG^Long" +msgstr "Lunga" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:144 +msgid "RNG^Full" +msgstr "Toate" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:151 +msgid "Automatic taunts" +msgstr "Glume automate" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:160 +msgid "Time warning:" +msgstr "Avertisment timp:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:162 +msgid "WRN^None" +msgstr "Nici una" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:163 +msgid "1 minute" +msgstr "1 minut" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:164 +msgid "5 minutes" +msgstr "5 minute" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:165 +msgid "WRN^Both" +msgstr "Ambele" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:168 +msgid "Hit indicator" +msgstr "Indicator lovituri" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:170 +msgid "Menu sounds" +msgstr "Sunete meniu" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:38 +msgid "Quality preset:" +msgstr "Setari calitate:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:41 +msgid "PRE^OMG!" +msgstr "SFINTE!" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:42 +msgid "PRE^Low" +msgstr "Scazut" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:43 +msgid "PRE^Medium" +msgstr "Mediu" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:44 +msgid "PRE^Normal" +msgstr "Normal" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:45 +msgid "PRE^High" +msgstr "Ridicat" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:46 +msgid "PRE^Ultra" +msgstr "Foarte ridicat" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:48 +msgid "PRE^Ultimate" +msgstr "Extrem de ridicat" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:52 +msgid "Geometry detail:" +msgstr "Detaliu geometrie:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:54 +msgid "DET^Lowest" +msgstr "Cel mai scazut" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:55 +msgid "DET^Low" +msgstr "Scazut" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:56 +msgid "DET^Normal" +msgstr "Normal" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:57 +msgid "DET^Good" +msgstr "Ridicat" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:58 +msgid "DET^Best" +msgstr "Cel mai ridicat" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:59 +msgid "DET^Insane" +msgstr "Extrem" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:62 +msgid "Antialiasing:" +msgstr "Margini fine:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:64 +msgid "AA^Disabled" +msgstr "Dezactivat" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:65 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:103 +msgid "2x" +msgstr "2x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:66 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:104 +msgid "4x" +msgstr "4x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:70 +msgid "Texture resolution:" +msgstr "Calitate texturi:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:73 +msgid "RES^Leet" +msgstr "Minima" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:74 +msgid "RES^Lowest" +msgstr "Cea mai joasa" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:75 +msgid "RES^Low" +msgstr "Joasa" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:76 +msgid "RES^Normal" +msgstr "Normala" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:77 +msgid "RES^Good" +msgstr "Ridicata" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:78 +msgid "RES^Best" +msgstr "Cea mai ridicata" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:91 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:94 +msgid "Avoid lossy texture compression" +msgstr "Evitare compresie rapida texturi" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:100 +msgid "Anisotropy:" +msgstr "Filtrare anisotropica:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:102 +msgid "ANISO^Disabled" +msgstr "Dezactivat" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:105 +msgid "8x" +msgstr "8x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:106 +msgid "16x" +msgstr "16x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:110 +msgid "Particle quality:" +msgstr "Calicate particule:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:113 +msgid "Particle distance:" +msgstr "Distanta particule:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:117 +msgid "Decals" +msgstr "Semne" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:118 +msgid "Decals on models" +msgstr "Semne pe modele" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:122 +msgid "Distance:" +msgstr "Distanta:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:128 +msgid "Time:" +msgstr "Durata:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:134 +msgid "Use lightmaps" +msgstr "Utilizare lightmap" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:135 +msgid "Deluxe mapping" +msgstr "Texturi Deluxe" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:137 +msgid "Gloss" +msgstr "Suprafete lucioase" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:140 +msgid "Offset mapping" +msgstr "Relief" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:142 +msgid "Relief mapping" +msgstr "Detaliu relief" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:145 +msgid "Reflections:" +msgstr "Reflectii:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:148 +msgid "Blurred" +msgstr "Blurate" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:149 +msgid "REFL^Good" +msgstr "Bune" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:150 +msgid "Sharp" +msgstr "Ascutite" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:155 +msgid "Show surfaces" +msgstr "Afisaj suprafete" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:157 +msgid "No dynamic lighting" +msgstr "Luminozitate dinamica dezactivata" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:159 +msgid "Flash blend approximation" +msgstr "Luminozitate dinamica rapida" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:161 +msgid "Realtime dynamic lighting" +msgstr "Luminozitate dinamica in timp real" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:162 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:166 +msgid "Shadows" +msgstr "Umbre" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:165 +msgid "Realtime world lighting" +msgstr "Luminozitate ambienta in timp real" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:170 +msgid "Use normal maps" +msgstr "Utilizare texturi normale" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:172 +msgid "Soft shadows" +msgstr "Umbre fine" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:175 +msgid "Coronas" +msgstr "Coroane lumini" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:176 +msgid "Use Occlusion Queries" +msgstr "Utilizare Ocluzii" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:178 +msgid "Bloom" +msgstr "Luminozitate moale" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:180 +msgid "High Dynamic Range (HDR)" +msgstr "Distanta Dinamica Inalta (HDR)" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:184 +msgid "Motion blur:" +msgstr "Blurare viteza:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:189 +msgid "Blur and sharpen postprocessing" +msgstr "Postprocesare blurare si ascutire" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:26 +msgid "Key bindings:" +msgstr "Taste:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:31 +msgid "Change key..." +msgstr "Schimbare tasta..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:35 +msgid "Edit..." +msgstr "Editare..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:46 +msgid "Sensitivity:" +msgstr "Sensitivitate:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:51 +msgid "UI mouse speed:" +msgstr "Viteza mouse in meniu:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:55 +msgid "Mouse filter" +msgstr "Filtrare mouse" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:57 +msgid "Invert mouse" +msgstr "Inversare mouse" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:60 +#: qcsrc/menu/xonotic/dialog_settings_input.c:62 +msgid "Use joystick input" +msgstr "Utilizare joystick" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:65 +#: qcsrc/menu/xonotic/dialog_settings_input.c:67 +msgid "Turn off OS mouse acceleration" +msgstr "Dezactivare acceleratie mouse din OS" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:69 +msgid "\"enter console\" also closes" +msgstr "\"enter\" inchide si consola" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:5 +msgid "User defined key bind" +msgstr "Functionalitate tasta definita:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:42 +msgid "Command when pressed:" +msgstr "Commanda apasare tasta:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:45 +msgid "Command when released:" +msgstr "Commanda eliberare tasta:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:48 +msgid "Save" +msgstr "Salvare" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:51 +msgid "Cancel" +msgstr "Anulare" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:26 +msgid "Menu skins:" +msgstr "Stil meniu:" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:47 +msgid "Show current time" +msgstr "Afisaj ora" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:49 +msgid "Show current date" +msgstr "Afisaj data" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:51 +msgid "Show frames per second" +msgstr "Afisaj cadre pe secunda" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:53 +msgid "Minimize input latency" +msgstr "Minimizare latenta control" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:5 +msgid "Advanced settings" +msgstr "Setari avansate" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:23 +msgid "Cvar filter:" +msgstr "Filtru variabile:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:34 +msgid "Setting:" +msgstr "Setari:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:42 +msgid "Value:" +msgstr "Valoare:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:56 +msgid "Description:" +msgstr "Descriere:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:26 +msgid "Client-side movement prediction" +msgstr "Predictie miscare" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:30 +msgid "Show netgraph" +msgstr "Afisaj grafic retea" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:33 +msgid "Network speed:" +msgstr "Viteza retea:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:35 +msgid "56k" +msgstr "56k" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:36 +msgid "ISDN" +msgstr "ISDN" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:37 +msgid "Slow ADSL" +msgstr "ADSL lent" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:38 +msgid "Fast ADSL" +msgstr "ADSL rapid" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:39 +msgid "Broadband" +msgstr "Cablu/Fibra optica" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:42 +msgid "Input packets/s:" +msgstr "Pachete intrare/secunda:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:46 +msgid "HTTP downloads:" +msgstr "Descarcari HTTP:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:49 +msgid "Downloads:" +msgstr "Descarcari simultane:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:53 +msgid "Speed (kB/s):" +msgstr "Viteza (kB/s):" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:57 +msgid "Client UDP port:" +msgstr "Port UDP client:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:26 +msgid "Resolution:" +msgstr "Rezolutie:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:29 +msgid "Font/UI size:" +msgstr "Marime font:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:31 +msgid "SZ^Unreadable" +msgstr "Ilizibil" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:32 +msgid "SZ^Tiny" +msgstr "Minuscul" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:33 +msgid "SZ^Little" +msgstr "Foarte mic" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:34 +msgid "SZ^Small" +msgstr "Mic" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:35 +msgid "SZ^Medium" +msgstr "Mediu" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:36 +msgid "SZ^Large" +msgstr "Mare" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:37 +msgid "SZ^Huge" +msgstr "Foarte mare" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:38 +msgid "SZ^Gigantic" +msgstr "Gigantic" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:39 +msgid "SZ^Colossal" +msgstr "Colosal" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:42 +msgid "Color depth:" +msgstr "Adancime culoare:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:45 +msgid "Full screen" +msgstr "Ecran plin" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:46 +msgid "Vertical Synchronization" +msgstr "Sincronizare Verticala" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:49 +msgid "Use OpenGL 2.0 shaders (GLSL)" +msgstr "Utilizare OpenGL 2.0 (GLSL)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:52 +msgid "Use GLSL to handle color control" +msgstr "Utilizare GLSL pentru culori" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:56 +msgid "Vertex Buffer Objects (VBOs)" +msgstr "Tampon Memorie Obiecte (VBOs)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:59 +msgid "VBO^Off" +msgstr "Dezactivat" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:60 +msgid "Vertices, some Tris (compatible)" +msgstr "Puncte, unele Triunghiuri (compatibil)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:63 +msgid "Vertices" +msgstr "Puncte" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:64 +msgid "Vertices and Triangles" +msgstr "Puncte si Triunghiuri" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:67 +msgid "Depth first:" +msgstr "Calcul adancime:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:69 +msgid "DF^Disabled" +msgstr "Dezactivat" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:70 +msgid "DF^World" +msgstr "Mediul" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:71 +msgid "DF^All" +msgstr "Totul" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:75 +msgid "Disable multithreaded OpenGL" +msgstr "Dezactiveaza OpenGL multi-core" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:77 +msgid "Wait for GPU to finish each frame" +msgstr "Asteapta ca GPU sa termine fiecare cadru" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:80 +msgid "Brightness:" +msgstr "Luminozitate:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:83 +msgid "Contrast:" +msgstr "Contrast:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:86 +msgid "Gamma:" +msgstr "Gama:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:91 +msgid "Contrast boost:" +msgstr "Exagerare contrast:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:96 +msgid "Saturation:" +msgstr "Saturatie:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:102 +msgid "LIT^Ambient:" +msgstr "Ambianta:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:105 +msgid "Intensity:" +msgstr "Intensitate:" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:4 +msgid "Singleplayer" +msgstr "Joc singular" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:127 +msgid "Instant action! (random map with bots)" +msgstr "Actiune instanta! (harta aleatorie cu boti)" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:148 +msgid "Start Singleplayer!" +msgstr "Pornire Joc Singular!" + +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:4 +msgid "Winner" +msgstr "Castigator" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:5 +msgid "Team Selection" +msgstr "Selectie echipa" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:41 +msgid "join 'best' team (auto-select)" +msgstr "cea mai potrivita echipa (selectie automata)" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:45 +msgid "red" +msgstr "rosu" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:46 +msgid "blue" +msgstr "albastru" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:47 +msgid "yellow" +msgstr "galben" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:48 +msgid "pink" +msgstr "roz" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:51 +msgid "spectate" +msgstr "spectator" + +#: qcsrc/menu/xonotic/mainwindow.c:35 qcsrc/menu/xonotic/mainwindow.c:38 +msgid "Do not press this button again!" +msgstr "Nu mai apasati acest buton din nou!" + +#: qcsrc/menu/xonotic/maplist.c:278 +msgid "" +"Huh? Can't play this (m is NULL). Refiltering so this won't happen again.\n" +msgstr "" +"Huh? Nu se poate juca asta (m este NUL). Re-filtrez pentru a preveni asta pe " +"viitor.\n" + +#: qcsrc/menu/xonotic/maplist.c:286 +#, c-format +msgid "%s's Xonotic Server" +msgstr "Serverul Xonotic al lui %s" + +#: qcsrc/menu/xonotic/maplist.c:291 +msgid "" +"Huh? Can't play this (invalid game type). Refiltering so this won't happen " +"again.\n" +msgstr "" +"Huh? Nu se poate juca asta (tipul jocului este invalid). Re-filtrez pentru a " +"preveni asta pe viitor.\n" + +#: qcsrc/menu/xonotic/playermodel.c:174 +msgid "<no model found>" +msgstr "<nu a fost gasit nici un model>" + +#: qcsrc/menu/xonotic/serverlist.c:185 +msgid "Remove" +msgstr "Stergere" + +#: qcsrc/menu/xonotic/serverlist.c:187 +msgid "Bookmark" +msgstr "Favorit" + +#: qcsrc/menu/xonotic/serverlist.c:527 +msgid "Ping" +msgstr "Latenta" + +#: qcsrc/menu/xonotic/serverlist.c:528 +msgid "Host name" +msgstr "Nume server" + +#: qcsrc/menu/xonotic/serverlist.c:529 +msgid "Map" +msgstr "Harta" + +#: qcsrc/menu/xonotic/serverlist.c:530 +msgid "Type" +msgstr "Mod" + +#: qcsrc/menu/xonotic/serverlist.c:531 +msgid "Players" +msgstr "Jucatori" + +#: qcsrc/menu/xonotic/skinlist.c:105 +msgid "<TITLE>" +msgstr "<TITLU>" + +#: qcsrc/menu/xonotic/skinlist.c:106 +msgid "<AUTHOR>" +msgstr "<AUTOR>" + +#: qcsrc/menu/xonotic/slider_decibels.c:50 +msgid "VOL^OFF" +msgstr "OPRIT" + +#: qcsrc/menu/xonotic/slider_decibels.c:52 +msgid "VOL^MAX" +msgstr "MAXIM" + +#: qcsrc/menu/xonotic/slider_decibels.c:53 +#, c-format +msgid "%s dB" +msgstr "%s dB" + +#: qcsrc/menu/xonotic/slider_resolution.c:65 +#, c-format +msgid "%dx%d" +msgstr "%dx%d" + +#: qcsrc/menu/xonotic/util.qc:270 +#, c-format +msgid "Received HTTP request data for an invalid id %d.\n" +msgstr "Primit cerere HTTP pentru un id invalid %d.\n" + +#: qcsrc/menu/xonotic/util.qc:285 +#, c-format +msgid "error receiving update notification: status is %d\n" +msgstr "eroare primire notificare update: statutul este %d\n" + +#: qcsrc/menu/xonotic/util.qc:290 +msgid "error: received HTML instead of an update notification\n" +msgstr "eroare: primit HTML in schimbul unei notificari de update\n" + +#: qcsrc/menu/xonotic/util.qc:295 +msgid "error: received carriage returns from update notification server\n" +msgstr "eroare: primit un mesaj eronat de la serverul de notificari update\n" + +#: qcsrc/menu/xonotic/util.qc:316 +#, c-format +msgid "" +"Update can be downloaded at:\n" +"%s\n" +msgstr "" +"Un update se poate descarca aici:\n" +"%s\n" + +#: qcsrc/menu/xonotic/util.qc:337 +msgid "Autogenerating mapinfo for newly added maps..." +msgstr "Auto-generare mapinfo pentru hartile proaspat adaugate..." + +#: qcsrc/menu/xonotic/util.qc:367 +#, c-format +msgid "^1%s TEST BUILD" +msgstr "^1%s VERSIUNE TESTARE" + +#: qcsrc/menu/xonotic/util.qc:432 +#, c-format +msgid "Update to %s now!" +msgstr "Updatati la %s acum!" + +#: qcsrc/menu/xonotic/util.qc:501 +msgid "" +"^1ERROR: Texture compression is required but not supported.\n" +"^1Expect visual problems.\n" +msgstr "" +"^1EROARE: Comprimarea texturilor este necesara dar nu si suportata.\n" +"^1Asteptati-va la probleme vizuale.\n" + +#: qcsrc/menu/xonotic/util.qc:523 +msgid "Arena" +msgstr "Arena" + +#: qcsrc/menu/xonotic/util.qc:524 +msgid "Assault" +msgstr "Asalt" + +#: qcsrc/menu/xonotic/util.qc:525 +msgid "Capture The Flag" +msgstr "Captureaza Steagul" + +#: qcsrc/menu/xonotic/util.qc:526 +msgid "Clan Arena" +msgstr "Clan Arena" + +#: qcsrc/menu/xonotic/util.qc:527 +msgid "Deathmatch" +msgstr "Meciul Mortii" + +#: qcsrc/menu/xonotic/util.qc:528 +msgid "Domination" +msgstr "Dominatie" + +#: qcsrc/menu/xonotic/util.qc:529 +msgid "Freeze Tag" +msgstr "Inghet" + +#: qcsrc/menu/xonotic/util.qc:530 +msgid "Keepaway" +msgstr "Keepaway" + +#: qcsrc/menu/xonotic/util.qc:531 +msgid "Key Hunt" +msgstr "Vanatoarea Cheilor" + +#: qcsrc/menu/xonotic/util.qc:532 +msgid "Last Man Standing" +msgstr "Ultimul Supravietuitor" + +#: qcsrc/menu/xonotic/util.qc:533 +msgid "Nexball" +msgstr "Nexball" + +#: qcsrc/menu/xonotic/util.qc:534 +msgid "Onslaught" +msgstr "Onslaught" + +#: qcsrc/menu/xonotic/util.qc:535 +msgid "Race" +msgstr "Cursa" + +#: qcsrc/menu/xonotic/util.qc:536 +msgid "Race CTS" +msgstr "Cursa CTS" + +#: qcsrc/menu/xonotic/util.qc:537 +msgid "Runematch" +msgstr "Runematch" + +#: qcsrc/menu/xonotic/util.qc:538 +msgid "Team Deathmatch" +msgstr "Meciul Mortii (in echipa)" + +#: qcsrc/menu/xonotic/util.qc:557 +#, c-format +msgid "@!#%'n Tuba Throwing" +msgstr "Arunca @!#%'n Tuba" + +#: qcsrc/menu/xonotic/util.qc:577 qcsrc/menu/xonotic/util.qc:593 +#: qcsrc/menu/xonotic/util.qc:602 qcsrc/menu/xonotic/util.qc:610 +#: qcsrc/menu/xonotic/util.qc:622 +msgid "Default" +msgstr "Setare normala" + +#: qcsrc/menu/xonotic/util.qc:588 +msgid "Use default" +msgstr "Utilizare setare normala" + +#: qcsrc/menu/xonotic/util.qc:608 +msgid "Team Color:" +msgstr "Culoare echipa:" + +#: qcsrc/menu/xonotic/util.qh:47 +msgid "Enable panel" +msgstr "Activare panou" + +#: qcsrc/server/w_crylink.qc:2 +msgid "Crylink" +msgstr "Crylink" + +#: qcsrc/server/w_crylink.qc:666 +#, c-format +msgid "%s succeeded at self-destructing themself with the Crylink" +msgstr "%s a reusit sa se auto-distruga cu Crylink-ul" + +#: qcsrc/server/w_crylink.qc:671 +#, c-format +msgid "%s could not hide from %s's Crylink" +msgstr "%s nu s-a putut ascunde de Crylink-ul lui %s" + +#: qcsrc/server/w_crylink.qc:673 +#, c-format +msgid "%s was too close to %s's Crylink" +msgstr "%s s-a apropiat prea mult de Crylink-ul lui %s" + +#: qcsrc/server/w_crylink.qc:675 +#, c-format +msgid "%s took a close look at %s's Crylink" +msgstr "%s s-a uitat in deaproape la Crylink-ul lui %s" + +#: qcsrc/server/w_electro.qc:2 +msgid "Electro" +msgstr "Electro" + +#: qcsrc/server/w_electro.qc:574 +#, c-format +msgid "%s could not remember where they put plasma" +msgstr "%s a uitat unde a pus plasma" + +#: qcsrc/server/w_electro.qc:576 +#, c-format +msgid "%s played with plasma" +msgstr "%s s-a jucat cu plasma" + +#: qcsrc/server/w_electro.qc:583 +#, c-format +msgid "%s just noticed %s's blue ball" +msgstr "%s tocmai a observat bilele albastre ale lui %s" + +#: qcsrc/server/w_electro.qc:585 +#, c-format +msgid "%s got in touch with %s's blue ball" +msgstr "%s a intrat in contact cu bila albastra a lui %s" + +#: qcsrc/server/w_electro.qc:590 +#, c-format +msgid "%s felt the electrifying air of %s's combo" +msgstr "%s a simtit forta electrica a combinatiei lui %s" + +#: qcsrc/server/w_electro.qc:592 +#, c-format +msgid "%s got too close to %s's blue beam" +msgstr "%s s-a apropiat prea mult de raza albastra a lui %s" + +#: qcsrc/server/w_electro.qc:594 +#, c-format +msgid "%s was blasted by %s's blue beam" +msgstr "%s a fost lovit de raza albastra a lui %s" + +#: qcsrc/server/w_fireball.qc:2 +msgid "Fireball" +msgstr "Fireball" + +#: qcsrc/server/w_fireball.qc:417 +#, c-format +msgid "%s forgot about some firemine" +msgstr "%s a uitat o minge de foc" + +#: qcsrc/server/w_fireball.qc:419 qcsrc/server/w_hlac.qc:240 +#, c-format +msgid "%s should have used a smaller gun" +msgstr "%s trebuia sa foloseasca o arma mai mica" + +#: qcsrc/server/w_fireball.qc:426 +#, c-format +msgid "%s tried to catch %s's firemine" +msgstr "%s a incercat sa prinda mingea de foc a lui %s" + +#: qcsrc/server/w_fireball.qc:428 +#, c-format +msgid "%s fatefully ignored %s's firemine" +msgstr "%s a ignorat mingea de foc a lui %s cu incredere" + +#: qcsrc/server/w_fireball.qc:435 +#, c-format +msgid "%s could not hide from %s's fireball" +msgstr "%s nu s-a putut ascunde de Fireball-ul lui %s" + +#: qcsrc/server/w_fireball.qc:437 +#, c-format +msgid "%s saw the pretty lights of %s's fireball" +msgstr "%s a vazut luminita de la capatul Fireball-ului lui %s" + +#: qcsrc/server/w_fireball.qc:440 +#, c-format +msgid "%s got too close to %s's fireball" +msgstr "%s s-a apropiat prea mult de Fireball-ul lui %s" + +#: qcsrc/server/w_fireball.qc:442 +#, c-format +msgid "%s tasted %s's fireball" +msgstr "%s a gustat din Fireball-ul lui %s" + +#: qcsrc/server/w_grenadelauncher.qc:2 +msgid "Mortar" +msgstr "Mortar" + +#: qcsrc/server/w_grenadelauncher.qc:383 +#, c-format +msgid "%s tried out his own grenade" +msgstr "%s si-a incercat propria grenada" + +#: qcsrc/server/w_grenadelauncher.qc:385 +#, c-format +msgid "%s detonated" +msgstr "%s a detonat" + +#: qcsrc/server/w_grenadelauncher.qc:391 +#, c-format +msgid "%s didn't see %s's grenade" +msgstr "%s nu a vazut grenada lui %s" + +#: qcsrc/server/w_grenadelauncher.qc:393 +#, c-format +msgid "%s almost dodged %s's grenade" +msgstr "%s aproape ca s-a ferit de grenada lui %s" + +#: qcsrc/server/w_grenadelauncher.qc:395 +#, c-format +msgid "%s ate %s's grenade" +msgstr "%s a mancat grenada lui %s" + +#: qcsrc/server/w_hagar.qc:2 +msgid "Hagar" +msgstr "Hagar" + +#: qcsrc/server/w_hagar.qc:395 qcsrc/server/w_seeker.qc:655 +#, c-format +msgid "%s played with tiny rockets" +msgstr "%s s-a jucat cu rachete" + +#: qcsrc/server/w_hagar.qc:399 +#, c-format +msgid "%s hoped %s's missiles wouldn't bounce" +msgstr "%s a sperat ca rachetele lui %s nu vor ricosa" + +#: qcsrc/server/w_hagar.qc:401 qcsrc/server/w_seeker.qc:661 +#, c-format +msgid "%s was pummeled by %s" +msgstr "%s a fost batut mar de %s" + +#: qcsrc/server/w_hlac.qc:2 +msgid "Heavy Laser Assault Cannon" +msgstr "Heavy Laser Assault Cannon" + +#: qcsrc/server/w_hlac.qc:242 +#, c-format +msgid "%s was cut down by %s" +msgstr "%s a fost taiat de %s" + +#: qcsrc/server/w_hook.qc:2 +msgid "Grappling Hook" +msgstr "Grappling Hook" + +#: qcsrc/server/w_hook.qc:266 qcsrc/server/w_porto.qc:296 +#, c-format +msgid "%s did the impossible" +msgstr "%s a reusit imposibilul" + +#: qcsrc/server/w_hook.qc:268 +#, c-format +msgid "%s has run into %s's gravity bomb" +msgstr "%s a fost absorbit de bomba gravitationala a lui %s" + +#: qcsrc/server/w_laser.qc:2 +msgid "Laser" +msgstr "Laser" + +#: qcsrc/server/w_laser.qc:311 +#, c-format +msgid "%s lasered themself to hell" +msgstr "%s s-a lovit prea mult cu laserul" + +#: qcsrc/server/w_laser.qc:315 +#, c-format +msgid "%s was cut in half by %s's gauntlet" +msgstr "%s a fost taiat in doua de socul lui %s" + +#: qcsrc/server/w_laser.qc:317 +#, c-format +msgid "%s was lasered to death by %s" +msgstr "%s a fost omorat cu laser de %s" + +#: qcsrc/server/w_minelayer.qc:2 +msgid "Mine Layer" +msgstr "Mine Layer" + +#: qcsrc/server/w_minelayer.qc:523 qcsrc/server/w_rocketlauncher.qc:501 +#, c-format +msgid "%s exploded" +msgstr "%s a explodat" + +#: qcsrc/server/w_minelayer.qc:527 +#, c-format +msgid "%s got too close to %s's mine" +msgstr "%s s-a apropiat prea mult de mina lui %s" + +#: qcsrc/server/w_minelayer.qc:529 +#, c-format +msgid "%s almost dodged %s's mine" +msgstr "%s aproape ca s-a ferit de mina lui %s" + +#: qcsrc/server/w_minelayer.qc:531 +#, c-format +msgid "%s stepped on %s's mine" +msgstr "%s a calcat pe mina lui %s" + +#: qcsrc/server/w_minstanex.qc:2 +msgid "MinstaNex" +msgstr "MinstaNex" + +#: qcsrc/server/w_minstanex.qc:293 qcsrc/server/w_nex.qc:253 +#: qcsrc/server/w_shotgun.qc:215 qcsrc/server/w_uzi.qc:317 +#, c-format +msgid "%s is now thinking with portals" +msgstr "%s gandeste acum cu portaluri" + +#: qcsrc/server/w_minstanex.qc:295 qcsrc/server/w_nex.qc:255 +#, c-format +msgid "%s has been vaporized by %s" +msgstr "%s a fost vaporizat de %s" + +#: qcsrc/server/w_nex.qc:2 +msgid "Nex" +msgstr "Nex" + +#: qcsrc/server/w_porto.qc:2 +msgid "Port-O-Launch" +msgstr "Port-O-Launch" + +#: qcsrc/server/w_porto.qc:298 +#, c-format +msgid "%s felt %s doing the impossible to him" +msgstr "%s a simtit cum %s a reusit imposibilul" + +#: qcsrc/server/w_rifle.qc:2 +msgid "Rifle" +msgstr "Luneta" + +#: qcsrc/server/w_rifle.qc:233 +#, c-format +msgid "%s shot themself automatically" +msgstr "%s s-a impuscat automat" + +#: qcsrc/server/w_rifle.qc:235 +#, c-format +msgid "%s sniped themself somehow" +msgstr "%s s-a impuscat oarecum cu luneta" + +#: qcsrc/server/w_rifle.qc:242 +#, c-format +msgid "%s failed to hide from %s's bullet hail" +msgstr "%s nu a reusit sa se ascunda de ploaia de gloante a lui %s" + +#: qcsrc/server/w_rifle.qc:244 +#, c-format +msgid "%s died in %s's bullet hail" +msgstr "%s a murit in ploaia de gloante a lui %s" + +#: qcsrc/server/w_rifle.qc:251 +#, c-format +msgid "%s failed to hide from %s's rifle" +msgstr "%s nu a reusit sa se ascunda de luneta lui %s" + +#: qcsrc/server/w_rifle.qc:256 +#, c-format +msgid "%s got hit in the head by %s" +msgstr "%s a fost lovit in cap de %s" + +#: qcsrc/server/w_rifle.qc:258 qcsrc/server/w_uzi.qc:321 +#, c-format +msgid "%s was sniped by %s" +msgstr "%s a fost nimerit cu luneta de %s" + +#: qcsrc/server/w_rocketlauncher.qc:2 +msgid "Rocket Launcher" +msgstr "Rocket Launcher" + +#: qcsrc/server/w_rocketlauncher.qc:505 +#, c-format +msgid "%s got too close to %s's rocket" +msgstr "%s s-a apropiat prea mult de racheta lui %s" + +#: qcsrc/server/w_rocketlauncher.qc:507 +#, c-format +msgid "%s almost dodged %s's rocket" +msgstr "%s aproape ca s-a ferit de racheta lui %s" + +#: qcsrc/server/w_rocketlauncher.qc:509 +#, c-format +msgid "%s ate %s's rocket" +msgstr "%s a mancat racheta lui %s" + +#: qcsrc/server/w_seeker.qc:2 +msgid "T.A.G. Seeker" +msgstr "T.A.G. Seeker" + +#: qcsrc/server/w_seeker.qc:659 +#, c-format +msgid "%s was tagged by %s" +msgstr "%s a fost marcat de %s" + +#: qcsrc/server/w_shotgun.qc:2 +msgid "Shotgun" +msgstr "Shotgun" + +#: qcsrc/server/w_shotgun.qc:219 +#, c-format +msgid "%2$s ^7slapped %1$s ^7around a bit with a large ^2shotgun" +msgstr "%2$s ^7l-a plesnit pe %1$s ^7cu o ^2Pusca ^7foarte mare" + +#: qcsrc/server/w_shotgun.qc:221 +#, c-format +msgid "%s was gunned by %s" +msgstr "%s a fost impuscat de %s" + +#: qcsrc/server/w_tuba.qc:2 +#, c-format +msgid "@!#%'n Tuba" +msgstr "@!#%'n Tuba" + +#: qcsrc/server/w_tuba.qc:252 +#, c-format +msgid "%s hurt his own ears with the @!#%%'n Tuba" +msgstr "%s si-a spart urechile cu propria @!#%%'n Tuba" + +#: qcsrc/server/w_tuba.qc:256 +#, c-format +msgid "%s died of %s's great playing on the @!#%%'n Tuba" +msgstr "%s a murit de la cantecul lui %s cu @!#%%'n Tuba" + +#: qcsrc/server/w_uzi.qc:2 +msgid "Machine Gun" +msgstr "Machine Gun" + +#: qcsrc/server/w_uzi.qc:323 +#, c-format +msgid "%s was riddled full of holes by %s" +msgstr "%s a fost gaurit de %s" + +#~ msgid "%d/%d" +#~ msgstr "%d/%d" + +#~ msgid "Waypoint settings:" +#~ msgstr "Setari indicatoare:" + +#~ msgid "Sniper Rifle" +#~ msgstr "Sniper Rifle" + +#~ msgid "Accelerometer scale:" +#~ msgstr "Marime metru acceleratie:" + +#~ msgid "Show accelerometer" +#~ msgstr "Afisaj metru acceleratie" + +#~ msgid "qu/s (hidden)" +#~ msgstr "qu/s (ascuns)" + +#~ msgid "Speedometer" +#~ msgstr "Vitezometru" + +#~ msgid "Damage & water blur" +#~ msgstr "Blurare ranire & apa:" + +#~ msgid "Powerup sharpen" +#~ msgstr "Ascutire powerup" + +#, fuzzy +#~ msgid "Panel enabled if not observing" +#~ msgstr "Activa pentru spectatori" diff --git a/menu.dat.ru.po b/menu.dat.ru.po new file mode 100644 index 0000000000..1ad8ddcc61 --- /dev/null +++ b/menu.dat.ru.po @@ -0,0 +1,2942 @@ +# Xonotic Menu +# Copyright (C) 2011 Team Xonotic +# This file is distributed under the same license as the Xonotic package. +# Lord Canistra <lordcanistra@gmail.com>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: 0.1preview\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-09-02 07:51+0200\n" +"PO-Revision-Date: 2011-01-20 13:16+0300\n" +"Last-Translator: Nikoli <nikoli@lavabit.com>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: qcsrc/common/mapinfo.qc:1092 qcsrc/menu/xonotic/skinlist.c:163 +#, c-format +msgid "%s: %s" +msgstr "%s: %s" + +#: qcsrc/menu/gamecommand.qc:47 +#, c-format +msgid "error: status is %d\n" +msgstr "ошибка: статус %d\n" + +#: qcsrc/menu/gamecommand.qc:65 +msgid "Usage: menu_cmd command..., where possible commands are:\n" +msgstr "Использование: menu_cmd command..., где возможные команды:\n" + +#: qcsrc/menu/gamecommand.qc:66 +msgid " sync - reloads all cvars on the current menu page\n" +msgstr " синх. - обновляет все cvar на текущей странице меню\n" + +#: qcsrc/menu/gamecommand.qc:67 +msgid " directmenu ITEM - select a menu item as main item\n" +msgstr " directmenu ITEM - определить элемент меню как главный элемент\n" + +#: qcsrc/menu/gamecommand.qc:193 +msgid "error creating curl handle\n" +msgstr "ошибка при создании curl handle\n" + +#: qcsrc/menu/gamecommand.qc:239 +msgid "Invalid command. For a list of supported commands, try menu_cmd help.\n" +msgstr "" +"Неверная команда. Попробуйте menu_cmd help, чтобы получить список доступных " +"команд.\n" + +#: qcsrc/menu/item/gecko.c:49 +msgid "Browser not initialized!" +msgstr "Браузер не запущен!" + +#: qcsrc/menu/item/label.c:63 +#, c-format +msgid "NOTE: label text %s too wide for label, condensed by factor %f\n" +msgstr "ВНИМАНИЕ: текст %s слишком широк для надписи, сжат до %f раз\n" + +#: qcsrc/menu/item/listbox.c:300 +#, c-format +msgid "Item %d" +msgstr "Предмет %d" + +#: qcsrc/menu/item/slider.c:64 +#, c-format +msgid "%d (%s)" +msgstr "%d (%s)" + +#: qcsrc/menu/item/textslider.c:29 qcsrc/menu/item/textslider.c:31 +msgid "custom" +msgstr "особо" + +#: qcsrc/menu/menu.qc:29 +#, fuzzy, c-format +msgid "^4MQC Build information: ^1%s\n" +msgstr "^4Сведения о сборке MQC: %s\n" + +#: qcsrc/menu/xonotic/campaign.c:284 +#: qcsrc/menu/xonotic/dialog_singleplayer.c:134 +msgid "???" +msgstr "???" + +#: qcsrc/menu/xonotic/campaign.c:285 +#, c-format +msgid "Level %d: %s" +msgstr "Уровень %d: %s" + +#: qcsrc/menu/xonotic/cvarlist.c:85 +msgid "will be saved to config.cfg" +msgstr "будет сохранено в config.cfg" + +#: qcsrc/menu/xonotic/cvarlist.c:87 +msgid "will not be saved" +msgstr "не будет сохранено" + +# личное, частное +#: qcsrc/menu/xonotic/cvarlist.c:89 +msgid "private" +msgstr "личное" + +#: qcsrc/menu/xonotic/cvarlist.c:91 +msgid "engine setting" +msgstr "установка движка" + +#: qcsrc/menu/xonotic/cvarlist.c:93 +msgid "read only" +msgstr "только чтение" + +#: qcsrc/menu/xonotic/dialog_credits.c:5 +msgid "Credits" +msgstr "Разработчики" + +#: qcsrc/menu/xonotic/dialog_credits.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:269 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:41 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:57 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:61 +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:21 +msgid "OK" +msgstr "ОК" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:4 +msgid "Welcome" +msgstr "Добро пожаловать" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:33 +msgid "" +"Welcome to Xonotic, please select your language preference and enter your " +"player name to get started. You can change these options later through the " +"menu system." +msgstr "" +"Добро пожаловать в Xonotic. Для начала, пожалуйста, выберите ваш язык и " +"введите ваше имя. Позже вы сможете изменить эти настройки в меню." + +#: qcsrc/menu/xonotic/dialog_firstrun.c:38 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:35 +msgid "Text language:" +msgstr "Язык меню:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:47 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:40 +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:39 +msgid "Name:" +msgstr "Имя:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:69 +msgid "Save settings" +msgstr "Сохранить настройки:" + +# делать транслитерацию вместо перевода нежелательно, panel можно перевести как: +# область, табло, (приборная) доска, щит, лист, плата, плита, список +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:4 +msgid "Ammo Panel" +msgstr "Панель боеприпасов" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:22 +msgid "Ammunition display:" +msgstr "Показ боеприпасов:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:25 +msgid "Show only current ammo type" +msgstr "Показывать только текущий вид боеприпасов" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:28 +msgid "Align icon:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:29 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:36 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:40 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:40 +msgid "Left" +msgstr "Слева" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:38 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:41 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:41 +msgid "Right" +msgstr "Справа" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:4 +msgid "Centerprint" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:23 +#, fuzzy +msgid "Message duration:" +msgstr "Насыщенность:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:27 +#, fuzzy +msgid "Fade time:" +msgstr "Время исчезновения:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:31 +#, fuzzy +msgid "Flip messages order" +msgstr "Обратить порядок уведомлений" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:33 +#, fuzzy +msgid "Text alignment:" +msgstr "Выравнивание иконок:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:37 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:50 +msgid "Center" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:41 +#, fuzzy +msgid "Font scale:" +msgstr "Размер отметок:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:4 +msgid "Chat Panel" +msgstr "Панель чата" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:22 +msgid "Chat entries:" +msgstr "Записи в чате:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:25 +msgid "Chat size:" +msgstr "Размер чата:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:29 +msgid "Chat lifetime:" +msgstr "Время жизни:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:33 +msgid "Chat beep sound" +msgstr "Звук чата:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:4 +msgid "Engine Info Panel" +msgstr "Панель сведений о движке" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:22 +msgid "Engine info:" +msgstr "Сведения о движке:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:25 +msgid "Use an averaging algorithm for fps" +msgstr "Исп. алгоритм усреднения для FPS" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:4 +msgid "Health/Armor Panel" +msgstr "Панель здоровья/брони" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:22 +msgid "Enable status bar" +msgstr "Включить полосу состояния" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:24 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:24 +msgid "Status bar alignment:" +msgstr "Выравнивание полосы состояния:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:42 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:42 +msgid "Inward" +msgstr "Внутрь" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:43 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:43 +msgid "Outward" +msgstr "Наружу" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:37 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:37 +msgid "Icon alignment:" +msgstr "Выравнивание иконок:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:45 +msgid "Flip health and armor positions" +msgstr "Поменять местами здоровье и броню" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:4 +msgid "Info Messages Panel" +msgstr "Панель информационных сообщений" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:22 +msgid "Info messages:" +msgstr "Инф. сообщения:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:25 +msgid "Flip align" +msgstr "Перевернуть выравнивание" + +#: qcsrc/menu/xonotic/dialog_hudpanel_modicons.c:4 +msgid "Mod Icons Panel" +msgstr "Панель иконок мода" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:4 +msgid "Notification Panel" +msgstr "Панель уведомлений" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:22 +msgid "Notifications:" +msgstr "Уведомления:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:25 +msgid "Also print notifications to the console" +msgstr "Также показывать уведомления в консоли" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:28 +msgid "Flip notify order" +msgstr "Обратить порядок уведомлений" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:31 +msgid "Entry lifetime:" +msgstr "Время видимости:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:35 +msgid "Entry fadetime:" +msgstr "Время исчезновения:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:4 +#, fuzzy +msgid "Physics Panel" +msgstr "Панель чата" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:21 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:21 +msgid "Panel disabled" +msgstr "Отключена" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:23 +#, fuzzy +msgid "Panel enabled" +msgstr "Отключена" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:24 +#, fuzzy +msgid "Panel enabled even observing" +msgstr "Включена при наблюдении" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:25 +#, fuzzy +msgid "Panel enabled only in Race/CTS" +msgstr "Панель включена в командных играх" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:31 +#, fuzzy +msgid "Status bar" +msgstr "Включить полосу состояния" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:48 +msgid "Left align" +msgstr "Слева" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:34 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:52 +msgid "Right align" +msgstr "Справа" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:35 +#, fuzzy +msgid "Inward align" +msgstr "Внутрь" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:36 +#, fuzzy +msgid "Outward align" +msgstr "Наружу" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:40 +#, fuzzy +msgid "Flip speed/acceleration positions" +msgstr "Поменять местами здоровье и броню" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:44 +#, fuzzy +msgid "Speed:" +msgstr "Скорость (кБ/с):" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:45 +msgid "Include vertical speed" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:56 +msgid "Speed unit:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:58 +msgid "qu/s" +msgstr "qu/s" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:59 +msgid "m/s" +msgstr "м/с" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:60 +msgid "km/h" +msgstr "км/ч" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:61 +msgid "mph" +msgstr "м/ч" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:62 +msgid "knots" +msgstr "узлы" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:64 +#, fuzzy +msgid "Show" +msgstr "Показывать Боеприпасы" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:67 +#, fuzzy +msgid "Top speed" +msgstr "Скорость увеличения:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:73 +#, fuzzy +msgid "Acceleration:" +msgstr "Отражения:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:74 +msgid "Include vertical acceleration" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:4 +msgid "Powerups Panel" +msgstr "Панель бонусов" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:45 +msgid "Flip strength and shield positions" +msgstr "Поменять местами Силу и Щит" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:4 +msgid "Pressed Keys Panel" +msgstr "Панель нажатых кнопок" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:22 +msgid "Panel enabled when spectating" +msgstr "Включена при наблюдении" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:23 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:23 +msgid "Panel always enabled" +msgstr "Всегда включена" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:30 +msgid "Forced aspect:" +msgstr "Соотношение:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_racetimer.c:4 +msgid "Race Timer Panel" +msgstr "Панель Гоночного Таймера" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:4 +msgid "Radar Panel" +msgstr "Панель радара" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:22 +msgid "Panel enabled in teamgames" +msgstr "Панель включена в командных играх" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:29 +msgid "Radar:" +msgstr "Радар:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:32 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:43 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:154 +#: qcsrc/menu/xonotic/util.qc:600 +msgid "Alpha:" +msgstr "Прозрачность:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:36 +msgid "Rotation:" +msgstr "Поворот:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:38 +msgid "Forward" +msgstr "Взгляд" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:39 +msgid "West" +msgstr "Запад" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:40 +msgid "South" +msgstr "Юг" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:41 +msgid "East" +msgstr "Восток" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:42 +msgid "North" +msgstr "Север" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:46 +msgid "Scale:" +msgstr "Размер:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:50 +msgid "Zoom mode:" +msgstr "Режим увел.:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:52 +msgid "Zoomed in" +msgstr "Приближён" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:53 +msgid "Zoomed out" +msgstr "Не приближён" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:54 +msgid "Always zoomed" +msgstr "Всегда приближён" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:55 +msgid "Never zoomed" +msgstr "Никогда не приближён" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:4 +msgid "Score Panel" +msgstr "Таблица Очков" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:22 +msgid "Score:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:25 +msgid "Rankings:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:26 +#, fuzzy +msgid "Off" +msgstr "Отключено" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:27 +msgid "And me" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:28 +msgid "Pure" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:4 +msgid "Timer Panel" +msgstr "Панель таймера" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:22 +msgid "Timer:" +msgstr "Таймер:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:25 +msgid "Show elapsed time" +msgstr "Показывать прошедшее время" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:4 +msgid "Vote Panel" +msgstr "Панель голосования" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:22 +msgid "Alpha after voting:" +msgstr "Прозр. после голосования:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:4 +msgid "Weapons Panel" +msgstr "Панель оружия" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:24 +msgid "Fade out after:" +msgstr "Исчезать после:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:26 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:36 +msgid "Never" +msgstr "Никогда" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:28 +#, c-format +msgid "%ds" +msgstr "%dс" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:32 +msgid "Fade effect:" +msgstr "Эффект исчезновения:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:35 +msgid "EF^None" +msgstr "Отсутствует" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:36 +msgid "Slide" +msgstr "Скольжение" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:37 +msgid "Alpha" +msgstr "Исчезновение" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:38 +#, fuzzy +msgid "EF^Both" +msgstr "1 и 5 минут" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:42 +msgid "Weapon icons:" +msgstr "Иконки оружия:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:45 +msgid "Show weapon ID as:" +msgstr "Показывать ID оружия как:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:46 +msgid "SHOWAS^None" +msgstr "Не показывать" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:47 +msgid "Number" +msgstr "Число" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:48 +msgid "Bind" +msgstr "Привязка" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:51 +msgid "Show Accuracy" +msgstr "Показывать Точность" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:52 +msgid "Show Ammo" +msgstr "Показывать Боеприпасы" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:55 +msgid "Ammo bar color:" +msgstr "Цвет полосы боеприпасов" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:61 +msgid "Ammo bar alpha:" +msgstr "Прозрачность полосы боеприпасов:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:4 +msgid "Panel HUD Setup" +msgstr "Настройка панелей" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:21 +msgid "Panel background defaults:" +msgstr "Фон по умолчанию:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:23 qcsrc/menu/xonotic/util.qc:575 +msgid "Background:" +msgstr "Фон:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:25 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:37 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:52 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:91 qcsrc/menu/xonotic/util.qc:578 +#: qcsrc/menu/xonotic/util.qc:594 qcsrc/menu/xonotic/util.qc:611 +msgid "Disable" +msgstr "Отключить" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:30 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:77 qcsrc/menu/xonotic/util.qc:583 +msgid "Color:" +msgstr "Цвет:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:35 qcsrc/menu/xonotic/util.qc:591 +msgid "Border size:" +msgstr "Ширина краёв:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:50 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:89 +msgid "Team color:" +msgstr "Цвет команды:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:58 qcsrc/menu/xonotic/util.qc:617 +msgid "Test team color in configure mode" +msgstr "Проверить цвет команды в режиме настройки" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:61 qcsrc/menu/xonotic/util.qc:620 +msgid "Padding:" +msgstr "Промежуток:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:68 +msgid "HUD Dock:" +msgstr "Область HUD:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:70 +msgid "DOCK^Disabled" +msgstr "Отключено" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:71 +msgid "DOCK^Small" +msgstr "Небольшая" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:72 +msgid "DOCK^Medium" +msgstr "Средняя" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:73 +msgid "DOCK^Large" +msgstr "Большая" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:96 +msgid "Grid settings:" +msgstr "Настройки сетки:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:99 +msgid "Snap panels to grid" +msgstr "Передвижение панелей по сетке" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:102 +msgid "Grid size:" +msgstr "Шаг сетки:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:103 +msgid "X:" +msgstr "X:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:109 +msgid "Y:" +msgstr "Y:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:117 +msgid "Exit setup" +msgstr "Выйти из настроек" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:4 +msgid "Multiplayer" +msgstr "Игра по сети" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:18 +msgid "Servers" +msgstr "Серверы" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:19 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:5 +msgid "Create" +msgstr "Создать" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:20 +msgid "Demos" +msgstr "Демо" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:5 +msgid "Player Setup" +msgstr "Настройки игрока" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:34 +msgid "Game type:" +msgstr "Вид игры:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:46 +msgid "Match settings:" +msgstr "Настройки состязания:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:49 +msgid "Time limit:" +msgstr "Предел времени:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:53 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:61 +msgid "Use map specified default" +msgstr "Исп. предел карты" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:56 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:155 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:156 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:157 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:161 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:162 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:163 +msgid "Point limit:" +msgstr "Предел очков:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:64 +msgid "Player slots:" +msgstr "Кол-во игроков:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:67 +msgid "Number of bots:" +msgstr "Кол-во ботов:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:71 +msgid "Bot skill:" +msgstr "Уровень ботов:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:74 +msgid "Botlike" +msgstr "Ботоподобный" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:75 +msgid "Beginner" +msgstr "Новичок" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:76 +msgid "You will win" +msgstr "Легко победить" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:77 +msgid "You can win" +msgstr "Можно победить" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:78 +msgid "You might win" +msgstr "Возможно победить" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:79 +msgid "Advanced" +msgstr "Продвинутый" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:80 +msgid "Expert" +msgstr "Опытный" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:81 +msgid "Pro" +msgstr "Профессионал" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:82 +msgid "Assassin" +msgstr "Убийца" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:83 +msgid "Unhuman" +msgstr "Сверхчеловек" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:84 +msgid "Godlike" +msgstr "Богоподобный" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:88 +msgid "Mutators..." +msgstr "Мутаторы..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:97 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:57 +msgid "Advanced settings..." +msgstr "Доп. настройки..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:104 +msgid "Map list:" +msgstr "Список карт:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:110 +msgid "Select all" +msgstr "Выбрать все" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:113 +msgid "Select none" +msgstr "Снять выделение" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:119 +msgid "Start Multiplayer!" +msgstr "Начать игру по сети" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:154 +msgid "Capture limit:" +msgstr "Предел захватов:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:158 +msgid "Lives:" +msgstr "Жизни:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:159 +msgid "Laps:" +msgstr "Круги:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:160 +msgid "Goals:" +msgstr "Цели:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:164 +msgid "Frag limit:" +msgstr "Предел убийств:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:6 +msgid "Advanced server settings" +msgstr "Доп. серверные настройки" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:25 +msgid "Game settings:" +msgstr "Настройки игры:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:28 +msgid "Allow spectating" +msgstr "Разрешить наблюдение" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:31 +msgid "Spawn shield:" +msgstr "Защита при возрождении" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:36 +msgid "Game speed:" +msgstr "Скорость игры:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:40 +msgid "Teamplay settings:" +msgstr "Настройки команд:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:43 +msgid "Friendly fire scale:" +msgstr "Огонь по союзникам:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:47 +msgid "Virtual friendly fire (effect only)" +msgstr "Мнимый огонь по союзникам (только впечатление)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:50 +msgid "Friendly fire penalty:" +msgstr "Штраф за огонь по союзникам" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:54 +msgid "Virtual penalty (effect only)" +msgstr "Мнимый штраф (только впечатление)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:57 +msgid "Teams:" +msgstr "Команды:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:66 +msgid "Map voting:" +msgstr "Голосование за карты:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:68 +msgid "No voting" +msgstr "Без голосования" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:69 +msgid "2 choices" +msgstr "2 выбора" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:70 +msgid "3 choices" +msgstr "3 выбора" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:71 +msgid "4 choices" +msgstr "4 выбора" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:72 +msgid "5 choices" +msgstr "5 выборов" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:73 +msgid "6 choices" +msgstr "6 выборов" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:74 +msgid "7 choices" +msgstr "7 выборов" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:75 +msgid "8 choices" +msgstr "8 выборов" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:76 +msgid "9 choices" +msgstr "9 выборов" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:79 +msgid "Simple majority wins vcall" +msgstr "Простое большинство выигрывает" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:5 +msgid "Map Information" +msgstr "Сведения о карте" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "Full item placement" +msgstr "С оружием" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "MinstaGib only" +msgstr "Только MinstaGib" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:78 +msgid "Title:" +msgstr "Заголовок:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:84 +msgid "Author:" +msgstr "Автор:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:90 +msgid "Features:" +msgstr "Особенности:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:95 +msgid "Game types:" +msgstr "Режимы игры:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:118 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:314 +msgid "Close" +msgstr "Закрыть" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:121 +#, fuzzy +msgid "MAP^Play" +msgstr "Играть" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:7 +msgid "Mutators" +msgstr "Мутаторы" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:33 +msgid "All Weapons Arena" +msgstr "Арена со всем оружием" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:35 +msgid "Most Weapons Arena" +msgstr "Арена с большинством оружия" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:56 +#, c-format +msgid "%s Arena" +msgstr "%s Арена" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:68 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:167 +msgid "Dodging" +msgstr "Уклонение" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:70 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:250 +msgid "MinstaGib" +msgstr "MinstaGib" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:253 +msgid "NIX" +msgstr "NIX" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:74 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:205 +msgid "Rocket Flying" +msgstr "Ракетный полёт" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:78 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:264 +msgid "No start weapons" +msgstr "Начинать без оружия" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:80 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:189 +msgid "Low gravity" +msgstr "Низкая гравитация" + +# В игре это включает не невидимость, а полупрозрачность, хотя так переводить вполне уместно. +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:170 +msgid "Cloaked" +msgstr "Невидимость" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:84 +msgid "Hook" +msgstr "Крюк" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:86 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:173 +msgid "Midair" +msgstr "Воздушный бой" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:88 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:176 +msgid "Vampire" +msgstr "Вампиризм" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:90 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:208 +msgid "Piñata" +msgstr "Piñata" + +# "Неисчерпаемое Оружие" - неправильно, галка не даёт бесконечный боеприпас, а сохраняет все подобранные оружия после каждого возраждения. +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:92 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:211 +msgid "Weapons stay" +msgstr "Оружия остаются" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:94 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:180 +msgid "Blood loss" +msgstr "Кровотечение" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:96 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:202 +msgid "Jet pack" +msgstr "Реактивный ранец" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:98 +msgid "MUT^None" +msgstr "Отсутствуют" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:164 +msgid "Gameplay mutators:" +msgstr "Мутаторы игрового процесса:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:196 +msgid "Weapon & item mutators:" +msgstr "Мутаторы оружия и предметов:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:199 +msgid "Grappling hook" +msgstr "Крюк" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:215 +msgid "Weapon arenas:" +msgstr "Арены оружия" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:218 +msgid "Regular (no arena)" +msgstr "Обычная (не арена)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:239 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:256 +msgid "with laser" +msgstr "с лазером" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:247 +msgid "Special arenas:" +msgstr "Особые арены:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:260 +msgid "Most weapons" +msgstr "Большинство оружия" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:4 +msgid "Demo" +msgstr "Демо" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:28 +msgid "Record demos while playing" +msgstr "Записывать демо во время игры" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:32 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:28 +msgid "Filter:" +msgstr "Фильтр:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:29 +#: qcsrc/menu/xonotic/dialog_settings_input.c:41 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:24 +msgid "Clear" +msgstr "Очистить" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:43 +msgid "Timedemo" +msgstr "Проверка производительности" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:46 +#, fuzzy +msgid "DEMO^Play" +msgstr "Играть" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:4 +msgid "Join" +msgstr "Присоединиться" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:36 +msgid "SRVS^Empty" +msgstr "Пустые" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:40 +msgid "SRVS^Full" +msgstr "Полные" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:44 +msgid "Pause" +msgstr "Пауза" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:56 +msgid "Address:" +msgstr "Адрес:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:67 +msgid "Info..." +msgstr "Сведения..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:317 +msgid "Join!" +msgstr "Присоединиться" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:5 +msgid "Server Information" +msgstr "Сведения о сервере" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:115 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:116 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:183 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:189 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:199 +msgid "N/A" +msgstr "Н/Д" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:158 +#, c-format +msgid "%d/%d, %d free player slots" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +#, c-format +msgid "%d modified settings" +msgstr "кол-во изменённых настроек: %d" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +msgid "Official settings" +msgstr "Официальные настройки" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:197 +msgid "N/A (can't connect)" +msgstr "Н/Д (не могу подключиться)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:205 +msgid "not supported (can't connect)" +msgstr "не поддерживается (не могу подключиться)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:207 +msgid "not supported (won't encrypt)" +msgstr "не поддерживается (шифрования не будет)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:211 +msgid "supported (will encrypt)" +msgstr "поддерживается (будет шифрование)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:213 +msgid "supported (won't encrypt)" +msgstr "поддерживается (шифрования не будет)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:217 +msgid "requested (will encrypt)" +msgstr "запрошено (будет шифрование)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:219 +msgid "requested (won't encrypt)" +msgstr "запрошено (шифрования не будет)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:223 +msgid "required (can't connect)" +msgstr "требуется (не могу подключиться)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:225 +msgid "required (will encrypt)" +msgstr "требуется (будет шифрование)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:246 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:269 +msgid "Players:" +msgstr "Игроки:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:254 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:38 +msgid "Type:" +msgstr "Вид:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:259 +msgid "Map:" +msgstr "Карта:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:264 +msgid "Gameplay:" +msgstr "Геймплей:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:274 +msgid "Bots:" +msgstr "Боты:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:279 +msgid "Mod:" +msgstr "Мод:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:284 +msgid "Version:" +msgstr "Версия:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:289 +msgid "Ping:" +msgstr "Пинг:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:295 +msgid "CA:" +msgstr "CA:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:301 +msgid "Key:" +msgstr "Ключ:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:307 +msgid "Encryption:" +msgstr "Шифрование:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:63 +msgid "Model:" +msgstr "Модель:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:88 +msgid "Field of view:" +msgstr "Угол обзора:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:92 +msgid "View bobbing:" +msgstr "Качание вида:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:96 +msgid "Zoom factor:" +msgstr "Множитель увеличения:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:100 +msgid "Zoom speed:" +msgstr "Скорость увеличения:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:103 +msgid "Weapon settings..." +msgstr "Настройки оружия..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:110 +msgid "Crosshair:" +msgstr "Прицел:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:111 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:139 +msgid "Per weapon" +msgstr "Зависит от оружия" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:130 +msgid "Crosshair size:" +msgstr "Величина прицела:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:134 +msgid "Crosshair alpha:" +msgstr "Прозрачность:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:138 +msgid "Crosshair color:" +msgstr "Цвет прицела:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:140 +msgid "By health" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:143 +#, fuzzy +msgid "Custom" +msgstr "особо" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:148 +msgid "Enable center dot" +msgstr "Точка в центре" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:151 +msgid "Size:" +msgstr "Размер:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:158 +msgid "Hit test:" +msgstr "Проверка на попадание:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:159 +msgid "HTST^None" +msgstr "Отключена" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:160 +msgid "TrueAim" +msgstr "TrueAim" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:161 +msgid "Enemies" +msgstr "Враги" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:164 +msgid "Waypoints setup..." +msgstr "Настройка отметок..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:169 +msgid "Enter HUD editor" +msgstr "Войти в редактор HUD" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:174 +msgid "Force models:" +msgstr "Использовать свои модели:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:175 +msgid "MDL^None" +msgstr "Нет" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:176 +msgid "MDL^Custom" +msgstr "Вместо нестандартных" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:177 +msgid "MDL^All" +msgstr "Вместо всех" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:180 +msgid "Disable gore effects" +msgstr "Отключить эффекты жестокости" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:182 +msgid "Gibs:" +msgstr "Ошмётки:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:184 +msgid "GIBS^None" +msgstr "Нет" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:185 +msgid "GIBS^Few" +msgstr "Мало" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:186 +msgid "GIBS^Many" +msgstr "Много" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:187 +msgid "GIBS^Lots" +msgstr "Тонны" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:191 +msgid "Damage splash:" +msgstr "Изображ. урона" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:195 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:173 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:194 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:30 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:41 +#: qcsrc/menu/xonotic/dialog_settings_video.c:109 +msgid "Apply immediately" +msgstr "Применить" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:5 +msgid "Waypoints" +msgstr "Отметки" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:23 +msgid "Show base waypoints" +msgstr "Показывать основные отметки" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:25 +msgid "Waypoint scale:" +msgstr "Размер отметок:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:29 +msgid "Waypoint alpha:" +msgstr "Прозрачность отметок:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:34 +msgid "Show names:" +msgstr "Показывать имена:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:37 +msgid "Teammates" +msgstr "Союзники" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:38 +msgid "All players" +msgstr "Все игроки" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:6 +msgid "Weapon settings" +msgstr "Настройки оружия" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:29 +msgid "Weapon priority list:" +msgstr "Список приоритета оружия:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:34 +msgid "Up" +msgstr "Вверх" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:37 +msgid "Down" +msgstr "Вниз" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:41 +msgid "Use priority list for weapon cycling" +msgstr "Использовать приоритеты для прокрутки оружия" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:43 +msgid "Auto switch weapons on pickup" +msgstr "Автоматически переключаться на поднятое оружие" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:45 +msgid "Draw 1st person weapon model" +msgstr "Показывать модель оружия в руках" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:55 +msgid "Flip view horizontally" +msgstr "Перевернуть изображение по горизонтали" + +#: qcsrc/menu/xonotic/dialog_news.c:4 +msgid "News" +msgstr "Новости" + +#: qcsrc/menu/xonotic/dialog_news.c:18 +msgid "http://www.xonotic.org/team/blog/" +msgstr "http://www.xonotic.org/team/blog/" + +#: qcsrc/menu/xonotic/dialog_quit.c:4 +msgid "Quit" +msgstr "Выход" + +#: qcsrc/menu/xonotic/dialog_quit.c:17 +msgid "Are you sure you want to quit?" +msgstr "Вы точно желаете выйти?" + +#: qcsrc/menu/xonotic/dialog_quit.c:20 +msgid "Yes" +msgstr "Да" + +#: qcsrc/menu/xonotic/dialog_quit.c:21 +msgid "No" +msgstr "Нет" + +#: qcsrc/menu/xonotic/dialog_settings.c:4 +msgid "Settings" +msgstr "Настройки" + +#: qcsrc/menu/xonotic/dialog_settings.c:18 +#: qcsrc/menu/xonotic/dialog_settings_input.c:4 +msgid "Input" +msgstr "Ввод" + +#: qcsrc/menu/xonotic/dialog_settings.c:19 +#: qcsrc/menu/xonotic/dialog_settings_video.c:4 +msgid "Video" +msgstr "Изображение" + +#: qcsrc/menu/xonotic/dialog_settings.c:20 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:4 +msgid "Effects" +msgstr "Эффекты" + +#: qcsrc/menu/xonotic/dialog_settings.c:21 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:4 +msgid "Audio" +msgstr "Звук" + +#: qcsrc/menu/xonotic/dialog_settings.c:22 +#: qcsrc/menu/xonotic/dialog_settings_network.c:4 +msgid "Network" +msgstr "Сеть" + +#: qcsrc/menu/xonotic/dialog_settings.c:23 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:4 +msgid "Misc" +msgstr "Разное" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:27 +msgid "Master:" +msgstr "Главный:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:33 +msgid "Music:" +msgstr "Музыка:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:41 +msgid "VOL^Ambient:" +msgstr "Фоновые звуки:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:48 +msgid "Info:" +msgstr "Инфо:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:55 +msgid "Items:" +msgstr "Предметы:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:62 +msgid "Pain:" +msgstr "Боль:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:69 +msgid "Player:" +msgstr "Игрок:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:76 +msgid "Shots:" +msgstr "Выстрелы:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:83 +msgid "Voice:" +msgstr "Голос:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:91 +msgid "Weapons:" +msgstr "Оружие:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:98 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:156 +msgid "Frequency:" +msgstr "Частота:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:100 +msgid "8 kHz" +msgstr "8 кГц" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:101 +msgid "11.025 kHz" +msgstr "11.025 кГц" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:102 +msgid "16 kHz" +msgstr "16 кГц" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:103 +msgid "22.05 kHz" +msgstr "22.05 кГц" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:104 +msgid "24 kHz" +msgstr "24 кГц" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:105 +msgid "32 kHz" +msgstr "32 кГц" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:106 +msgid "44.1 kHz" +msgstr "44.1 кГц" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:107 +msgid "48 kHz" +msgstr "48 кГц" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:110 +msgid "Channels:" +msgstr "Каналы:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:112 +msgid "Mono" +msgstr "Моно" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:113 +msgid "Stereo" +msgstr "Стерео" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:114 +msgid "2.1" +msgstr "2.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:115 +msgid "4" +msgstr "4" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:116 +msgid "5" +msgstr "5" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:117 +msgid "5.1" +msgstr "5.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:118 +msgid "6.1" +msgstr "6.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:119 +msgid "7.1" +msgstr "7.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:123 +msgid "Swap Stereo" +msgstr "Обмен местами каналов" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:127 +msgid "Headphone friendly mode" +msgstr "Ориентированный на наушники режим" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:131 +msgid "Spatial voices:" +msgstr "Объёмные голоса:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:132 +msgid "VOCS^None" +msgstr "Отключены" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:133 +msgid "VOCS^Taunts" +msgstr "Насмешки" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:134 +msgid "VOCS^All" +msgstr "Все" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:137 +msgid "Taunt range:" +msgstr "Радиус насмешек:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:140 +msgid "RNG^Very short" +msgstr "Очень маленький" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:141 +msgid "RNG^Short" +msgstr "Маленький" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:142 +msgid "RNG^Normal" +msgstr "Обычный" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:143 +msgid "RNG^Long" +msgstr "Большой" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:144 +msgid "RNG^Full" +msgstr "Полный" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:151 +msgid "Automatic taunts" +msgstr "Автоматические насмешки" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:160 +msgid "Time warning:" +msgstr "Предупреждение о таймауте за:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:162 +msgid "WRN^None" +msgstr "Нет" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:163 +msgid "1 minute" +msgstr "1 минуту" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:164 +msgid "5 minutes" +msgstr "5 минут" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:165 +msgid "WRN^Both" +msgstr "1 и 5 минут" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:168 +msgid "Hit indicator" +msgstr "Оповещать о попадании" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:170 +msgid "Menu sounds" +msgstr "Звуки меню" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:38 +msgid "Quality preset:" +msgstr "Предустановки качества:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:41 +msgid "PRE^OMG!" +msgstr "Ужасное" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:42 +msgid "PRE^Low" +msgstr "Низкое" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:43 +msgid "PRE^Medium" +msgstr "Среднее" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:44 +msgid "PRE^Normal" +msgstr "Обычное" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:45 +msgid "PRE^High" +msgstr "Высокое" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:46 +msgid "PRE^Ultra" +msgstr "Сверх" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:48 +msgid "PRE^Ultimate" +msgstr "Предельное" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:52 +msgid "Geometry detail:" +msgstr "Подробность геометрии:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:54 +msgid "DET^Lowest" +msgstr "Нижайшая" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:55 +msgid "DET^Low" +msgstr "Низкая" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:56 +msgid "DET^Normal" +msgstr "Обычная" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:57 +msgid "DET^Good" +msgstr "Хорошая" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:58 +msgid "DET^Best" +msgstr "Лучшая" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:59 +msgid "DET^Insane" +msgstr "Высочайшая" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:62 +msgid "Antialiasing:" +msgstr "Сглаживание:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:64 +msgid "AA^Disabled" +msgstr "Отключено" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:65 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:103 +msgid "2x" +msgstr "2x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:66 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:104 +msgid "4x" +msgstr "4x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:70 +msgid "Texture resolution:" +msgstr "Разрешение текстур:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:73 +msgid "RES^Leet" +msgstr "Ужасное" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:74 +msgid "RES^Lowest" +msgstr "Нижайшее" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:75 +msgid "RES^Low" +msgstr "Низкое" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:76 +msgid "RES^Normal" +msgstr "Обычное" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:77 +msgid "RES^Good" +msgstr "Хорошее" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:78 +msgid "RES^Best" +msgstr "Лучшее" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:91 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:94 +msgid "Avoid lossy texture compression" +msgstr "Избегать сжатия текстур с потерями" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:100 +msgid "Anisotropy:" +msgstr "Анизотропия:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:102 +msgid "ANISO^Disabled" +msgstr "Отключена" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:105 +msgid "8x" +msgstr "8x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:106 +msgid "16x" +msgstr "16x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:110 +msgid "Particle quality:" +msgstr "Качество частиц:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:113 +msgid "Particle distance:" +msgstr "Дальность частиц:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:117 +msgid "Decals" +msgstr "Декали:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:118 +msgid "Decals on models" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:122 +msgid "Distance:" +msgstr "Дальность:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:128 +msgid "Time:" +msgstr "Время:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:134 +msgid "Use lightmaps" +msgstr "Использовать карты освещения" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:135 +msgid "Deluxe mapping" +msgstr "Особое качество" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:137 +msgid "Gloss" +msgstr "Блеск" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:140 +msgid "Offset mapping" +msgstr "Офсетное текстурирование" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:142 +msgid "Relief mapping" +msgstr "Рельефное текстурирование" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:145 +msgid "Reflections:" +msgstr "Отражения:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:148 +msgid "Blurred" +msgstr "Размытые" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:149 +msgid "REFL^Good" +msgstr "Хорошие" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:150 +msgid "Sharp" +msgstr "Резкие" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:155 +msgid "Show surfaces" +msgstr "Показывать поверхности" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:157 +msgid "No dynamic lighting" +msgstr "Без динамического освещения" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:159 +msgid "Flash blend approximation" +msgstr "Грубая имитация" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:161 +msgid "Realtime dynamic lighting" +msgstr "Дин. освещение в реальном времени" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:162 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:166 +msgid "Shadows" +msgstr "Тени" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:165 +msgid "Realtime world lighting" +msgstr "Дин. освещение мира в реальном времени" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:170 +msgid "Use normal maps" +msgstr "Использовать карты нормалей" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:172 +msgid "Soft shadows" +msgstr "Мягкие тени" + +# Перевод может быть неверным. +#: qcsrc/menu/xonotic/dialog_settings_effects.c:175 +msgid "Coronas" +msgstr "Короны" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:176 +msgid "Use Occlusion Queries" +msgstr "Использовать Occlusion Queries (Проверка видимости)" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:178 +msgid "Bloom" +msgstr "Свечение" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:180 +msgid "High Dynamic Range (HDR)" +msgstr "High Dynamic Range (HDR)" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:184 +msgid "Motion blur:" +msgstr "Размытие от движения:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:189 +msgid "Blur and sharpen postprocessing" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:26 +msgid "Key bindings:" +msgstr "Привязки клавиш:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:31 +msgid "Change key..." +msgstr "Сменить кнопку..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:35 +msgid "Edit..." +msgstr "Изменить..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:46 +msgid "Sensitivity:" +msgstr "Чувствительность:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:51 +msgid "UI mouse speed:" +msgstr "Скорость мыши в UI:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:55 +msgid "Mouse filter" +msgstr "Фильтр мыши" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:57 +msgid "Invert mouse" +msgstr "Обратить мышь" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:60 +#: qcsrc/menu/xonotic/dialog_settings_input.c:62 +msgid "Use joystick input" +msgstr "Использовать ввод с джойстика" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:65 +#: qcsrc/menu/xonotic/dialog_settings_input.c:67 +msgid "Turn off OS mouse acceleration" +msgstr "Отключить ускорение OS мыши" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:69 +msgid "\"enter console\" also closes" +msgstr "\"открыть консоль\" также закрывает" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:5 +msgid "User defined key bind" +msgstr "Определённая пользователем привязка клавиш" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:42 +msgid "Command when pressed:" +msgstr "Команда при нажатии:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:45 +msgid "Command when released:" +msgstr "Команда при отжатии:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:48 +msgid "Save" +msgstr "Сохранение" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:51 +msgid "Cancel" +msgstr "Отмена" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:26 +msgid "Menu skins:" +msgstr "Оформления:" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:47 +msgid "Show current time" +msgstr "Показывать время" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:49 +msgid "Show current date" +msgstr "Показывать дату" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:51 +msgid "Show frames per second" +msgstr "Показывать кадры/с (FPS)" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:53 +msgid "Minimize input latency" +msgstr "Уменьшить задержку ввода" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:5 +msgid "Advanced settings" +msgstr "Доп. настройки" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:23 +msgid "Cvar filter:" +msgstr "Фильтр Cvar:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:34 +msgid "Setting:" +msgstr "Настройка:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:42 +msgid "Value:" +msgstr "Значение:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:56 +msgid "Description:" +msgstr "Описание:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:26 +msgid "Client-side movement prediction" +msgstr "Предсказание движения на стороне клиента" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:30 +msgid "Show netgraph" +msgstr "Показывать netgraph" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:33 +msgid "Network speed:" +msgstr "Скорость соединения:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:35 +msgid "56k" +msgstr "56k" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:36 +msgid "ISDN" +msgstr "ISDN" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:37 +msgid "Slow ADSL" +msgstr "Медленный ADSL" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:38 +msgid "Fast ADSL" +msgstr "Быстрый ADSL" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:39 +msgid "Broadband" +msgstr "Широкополосное" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:42 +msgid "Input packets/s:" +msgstr "Кол-во пакетов/с" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:46 +msgid "HTTP downloads:" +msgstr "HTTP загрузки:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:49 +msgid "Downloads:" +msgstr "Загрузки:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:53 +msgid "Speed (kB/s):" +msgstr "Скорость (кБ/с):" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:57 +msgid "Client UDP port:" +msgstr "UDP порт клиента:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:26 +msgid "Resolution:" +msgstr "Разрешение:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:29 +msgid "Font/UI size:" +msgstr "Размера шрифта/UI" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:31 +msgid "SZ^Unreadable" +msgstr "Нечитаемый" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:32 +msgid "SZ^Tiny" +msgstr "Крошечный" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:33 +msgid "SZ^Little" +msgstr "Маленький" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:34 +msgid "SZ^Small" +msgstr "Небольшой" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:35 +msgid "SZ^Medium" +msgstr "Средний" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:36 +msgid "SZ^Large" +msgstr "Большой" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:37 +msgid "SZ^Huge" +msgstr "Огромный" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:38 +msgid "SZ^Gigantic" +msgstr "Гигантский" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:39 +msgid "SZ^Colossal" +msgstr "Колоссальный" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:42 +msgid "Color depth:" +msgstr "Глубина цвета:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:45 +msgid "Full screen" +msgstr "На весь экран" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:46 +msgid "Vertical Synchronization" +msgstr "Вертикальная синхронизация" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:49 +msgid "Use OpenGL 2.0 shaders (GLSL)" +msgstr "Использовать шейдеры OpenGL 2.0 (GLSL)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:52 +msgid "Use GLSL to handle color control" +msgstr "Использовать GLSL для управления цветом" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:56 +msgid "Vertex Buffer Objects (VBOs)" +msgstr "Использование Vertex Buffer Objects (VBOs)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:59 +msgid "VBO^Off" +msgstr "Отключено" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:60 +msgid "Vertices, some Tris (compatible)" +msgstr "Вершины, некоторые треугольники (совместимо)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:63 +msgid "Vertices" +msgstr "Вершины" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:64 +msgid "Vertices and Triangles" +msgstr "Вершины и треугольники" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:67 +msgid "Depth first:" +msgstr "Сперва глубина:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:69 +msgid "DF^Disabled" +msgstr "Отключено" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:70 +msgid "DF^World" +msgstr "Мир" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:71 +msgid "DF^All" +msgstr "Всё" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:75 +msgid "Disable multithreaded OpenGL" +msgstr "Отключить многопоточный OpenGL" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:77 +msgid "Wait for GPU to finish each frame" +msgstr "Ждать завершения каждого кадра GPU" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:80 +msgid "Brightness:" +msgstr "Яркость:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:83 +msgid "Contrast:" +msgstr "Контраст:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:86 +msgid "Gamma:" +msgstr "Гамма:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:91 +msgid "Contrast boost:" +msgstr "Усиление контраста:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:96 +msgid "Saturation:" +msgstr "Насыщенность:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:102 +msgid "LIT^Ambient:" +msgstr "Окружающее освещение:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:105 +msgid "Intensity:" +msgstr "Мощность:" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:4 +msgid "Singleplayer" +msgstr "Одиночная игра" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:127 +msgid "Instant action! (random map with bots)" +msgstr "Быстрая игра (случайная карта с ботами)" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:148 +msgid "Start Singleplayer!" +msgstr "Начать одиночную игру" + +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:4 +msgid "Winner" +msgstr "Победитель" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:5 +msgid "Team Selection" +msgstr "Выбор команды" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:41 +msgid "join 'best' team (auto-select)" +msgstr "Выбрать 'лучшую' команду (автовыбор)" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:45 +msgid "red" +msgstr "красная" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:46 +msgid "blue" +msgstr "синяя" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:47 +msgid "yellow" +msgstr "жёлтая" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:48 +msgid "pink" +msgstr "розовая" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:51 +msgid "spectate" +msgstr "наблюдать" + +#: qcsrc/menu/xonotic/mainwindow.c:35 qcsrc/menu/xonotic/mainwindow.c:38 +msgid "Do not press this button again!" +msgstr "Не нажимайте снова эту кнопку!" + +#: qcsrc/menu/xonotic/maplist.c:278 +msgid "" +"Huh? Can't play this (m is NULL). Refiltering so this won't happen again.\n" +msgstr "" +"Что? Не могу зайти (m = NULL). Перефильтрую, чтобы такого больше не " +"случалось.\n" + +#: qcsrc/menu/xonotic/maplist.c:286 +#, c-format +msgid "%s's Xonotic Server" +msgstr "Сервер Xonotic от %s" + +#: qcsrc/menu/xonotic/maplist.c:291 +msgid "" +"Huh? Can't play this (invalid game type). Refiltering so this won't happen " +"again.\n" +msgstr "" +"Что? Не могу зайти (неверный вид игры). Перефильтрую, чтобы такого больше не " +"случалось.\n" + +#: qcsrc/menu/xonotic/playermodel.c:174 +msgid "<no model found>" +msgstr "<модель игрока не найдена>" + +#: qcsrc/menu/xonotic/serverlist.c:185 +msgid "Remove" +msgstr "Убрать" + +#: qcsrc/menu/xonotic/serverlist.c:187 +msgid "Bookmark" +msgstr "В закладки" + +#: qcsrc/menu/xonotic/serverlist.c:527 +msgid "Ping" +msgstr "Пинг" + +#: qcsrc/menu/xonotic/serverlist.c:528 +msgid "Host name" +msgstr "Имя сервера" + +#: qcsrc/menu/xonotic/serverlist.c:529 +msgid "Map" +msgstr "Карта" + +#: qcsrc/menu/xonotic/serverlist.c:530 +msgid "Type" +msgstr "Вид" + +#: qcsrc/menu/xonotic/serverlist.c:531 +msgid "Players" +msgstr "Игроки" + +#: qcsrc/menu/xonotic/skinlist.c:105 +msgid "<TITLE>" +msgstr "<ЗАГОЛОВОК>" + +#: qcsrc/menu/xonotic/skinlist.c:106 +msgid "<AUTHOR>" +msgstr "<АВТОР>" + +#: qcsrc/menu/xonotic/slider_decibels.c:50 +msgid "VOL^OFF" +msgstr "Отключено" + +#: qcsrc/menu/xonotic/slider_decibels.c:52 +msgid "VOL^MAX" +msgstr "Максимум" + +#: qcsrc/menu/xonotic/slider_decibels.c:53 +#, c-format +msgid "%s dB" +msgstr "%s дБ" + +#: qcsrc/menu/xonotic/slider_resolution.c:65 +#, c-format +msgid "%dx%d" +msgstr "%dx%d" + +#: qcsrc/menu/xonotic/util.qc:270 +#, c-format +msgid "Received HTTP request data for an invalid id %d.\n" +msgstr "Получены данные HTTP запроса для неверного id %d.\n" + +#: qcsrc/menu/xonotic/util.qc:285 +#, c-format +msgid "error receiving update notification: status is %d\n" +msgstr "ошибка при получении уведомления об обновлении: статус %d\n" + +#: qcsrc/menu/xonotic/util.qc:290 +msgid "error: received HTML instead of an update notification\n" +msgstr "ошибка: получение HTML вместо уведомления об обновлении\n" + +#: qcsrc/menu/xonotic/util.qc:295 +msgid "error: received carriage returns from update notification server\n" +msgstr "" +"ошибка: получены символы возврата строки от сервера уведомлений об " +"обновлениях\n" + +#: qcsrc/menu/xonotic/util.qc:316 +#, c-format +msgid "" +"Update can be downloaded at:\n" +"%s\n" +msgstr "" +"Обновление может быть загружено с:\n" +"%s\n" + +#: qcsrc/menu/xonotic/util.qc:337 +msgid "Autogenerating mapinfo for newly added maps..." +msgstr "Автоматическое создание mapinfo для новых карт..." + +#: qcsrc/menu/xonotic/util.qc:367 +#, c-format +msgid "^1%s TEST BUILD" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:432 +#, c-format +msgid "Update to %s now!" +msgstr "Обновитесь до %s сейчас же!" + +#: qcsrc/menu/xonotic/util.qc:501 +msgid "" +"^1ERROR: Texture compression is required but not supported.\n" +"^1Expect visual problems.\n" +msgstr "" +"1^ОШИБКА: Сжатие текстур требуется, но не поддерживается.\n" +"1^Ожидайте проблемы с отображением.\n" + +#: qcsrc/menu/xonotic/util.qc:523 +msgid "Arena" +msgstr "Arena" + +#: qcsrc/menu/xonotic/util.qc:524 +msgid "Assault" +msgstr "Assault" + +#: qcsrc/menu/xonotic/util.qc:525 +msgid "Capture The Flag" +msgstr "Capture The Flag" + +#: qcsrc/menu/xonotic/util.qc:526 +msgid "Clan Arena" +msgstr "Clan Arena" + +#: qcsrc/menu/xonotic/util.qc:527 +msgid "Deathmatch" +msgstr "Deathmatch" + +#: qcsrc/menu/xonotic/util.qc:528 +msgid "Domination" +msgstr "Domination" + +#: qcsrc/menu/xonotic/util.qc:529 +msgid "Freeze Tag" +msgstr "Freeze Tag" + +#: qcsrc/menu/xonotic/util.qc:530 +msgid "Keepaway" +msgstr "Keepaway" + +#: qcsrc/menu/xonotic/util.qc:531 +msgid "Key Hunt" +msgstr "Key Hunt" + +#: qcsrc/menu/xonotic/util.qc:532 +msgid "Last Man Standing" +msgstr "Last Man Standing" + +#: qcsrc/menu/xonotic/util.qc:533 +msgid "Nexball" +msgstr "Nexball" + +#: qcsrc/menu/xonotic/util.qc:534 +msgid "Onslaught" +msgstr "Onslaught" + +#: qcsrc/menu/xonotic/util.qc:535 +msgid "Race" +msgstr "Race" + +#: qcsrc/menu/xonotic/util.qc:536 +msgid "Race CTS" +msgstr "Race CTS" + +#: qcsrc/menu/xonotic/util.qc:537 +msgid "Runematch" +msgstr "Runematch" + +#: qcsrc/menu/xonotic/util.qc:538 +msgid "Team Deathmatch" +msgstr "Team Deathmatch" + +#: qcsrc/menu/xonotic/util.qc:557 +#, c-format +msgid "@!#%'n Tuba Throwing" +msgstr "@!#%'n Швыряние Тубой" + +#: qcsrc/menu/xonotic/util.qc:577 qcsrc/menu/xonotic/util.qc:593 +#: qcsrc/menu/xonotic/util.qc:602 qcsrc/menu/xonotic/util.qc:610 +#: qcsrc/menu/xonotic/util.qc:622 +msgid "Default" +msgstr "По умолчанию" + +#: qcsrc/menu/xonotic/util.qc:588 +msgid "Use default" +msgstr "Исп. настройки по умолчанию" + +#: qcsrc/menu/xonotic/util.qc:608 +msgid "Team Color:" +msgstr "Цвет команды:" + +#: qcsrc/menu/xonotic/util.qh:47 +msgid "Enable panel" +msgstr "Включить панель" + +#: qcsrc/server/w_crylink.qc:2 +msgid "Crylink" +msgstr "Crylink" + +#: qcsrc/server/w_crylink.qc:666 +#, c-format +msgid "%s succeeded at self-destructing themself with the Crylink" +msgstr "" + +#: qcsrc/server/w_crylink.qc:671 +#, c-format +msgid "%s could not hide from %s's Crylink" +msgstr "" + +#: qcsrc/server/w_crylink.qc:673 +#, c-format +msgid "%s was too close to %s's Crylink" +msgstr "" + +#: qcsrc/server/w_crylink.qc:675 +#, c-format +msgid "%s took a close look at %s's Crylink" +msgstr "" + +#: qcsrc/server/w_electro.qc:2 +msgid "Electro" +msgstr "Electro" + +#: qcsrc/server/w_electro.qc:574 +#, c-format +msgid "%s could not remember where they put plasma" +msgstr "" + +#: qcsrc/server/w_electro.qc:576 +#, c-format +msgid "%s played with plasma" +msgstr "" + +#: qcsrc/server/w_electro.qc:583 +#, c-format +msgid "%s just noticed %s's blue ball" +msgstr "" + +#: qcsrc/server/w_electro.qc:585 +#, c-format +msgid "%s got in touch with %s's blue ball" +msgstr "" + +#: qcsrc/server/w_electro.qc:590 +#, c-format +msgid "%s felt the electrifying air of %s's combo" +msgstr "" + +#: qcsrc/server/w_electro.qc:592 +#, c-format +msgid "%s got too close to %s's blue beam" +msgstr "" + +#: qcsrc/server/w_electro.qc:594 +#, c-format +msgid "%s was blasted by %s's blue beam" +msgstr "" + +#: qcsrc/server/w_fireball.qc:2 +msgid "Fireball" +msgstr "Fireball" + +#: qcsrc/server/w_fireball.qc:417 +#, c-format +msgid "%s forgot about some firemine" +msgstr "" + +#: qcsrc/server/w_fireball.qc:419 qcsrc/server/w_hlac.qc:240 +#, c-format +msgid "%s should have used a smaller gun" +msgstr "" + +#: qcsrc/server/w_fireball.qc:426 +#, c-format +msgid "%s tried to catch %s's firemine" +msgstr "" + +#: qcsrc/server/w_fireball.qc:428 +#, c-format +msgid "%s fatefully ignored %s's firemine" +msgstr "" + +#: qcsrc/server/w_fireball.qc:435 +#, c-format +msgid "%s could not hide from %s's fireball" +msgstr "" + +#: qcsrc/server/w_fireball.qc:437 +#, c-format +msgid "%s saw the pretty lights of %s's fireball" +msgstr "" + +#: qcsrc/server/w_fireball.qc:440 +#, c-format +msgid "%s got too close to %s's fireball" +msgstr "" + +#: qcsrc/server/w_fireball.qc:442 +#, c-format +msgid "%s tasted %s's fireball" +msgstr "" + +#: qcsrc/server/w_grenadelauncher.qc:2 +msgid "Mortar" +msgstr "Mortar" + +#: qcsrc/server/w_grenadelauncher.qc:383 +#, c-format +msgid "%s tried out his own grenade" +msgstr "" + +#: qcsrc/server/w_grenadelauncher.qc:385 +#, c-format +msgid "%s detonated" +msgstr "" + +#: qcsrc/server/w_grenadelauncher.qc:391 +#, c-format +msgid "%s didn't see %s's grenade" +msgstr "" + +#: qcsrc/server/w_grenadelauncher.qc:393 +#, c-format +msgid "%s almost dodged %s's grenade" +msgstr "" + +#: qcsrc/server/w_grenadelauncher.qc:395 +#, c-format +msgid "%s ate %s's grenade" +msgstr "" + +#: qcsrc/server/w_hagar.qc:2 +msgid "Hagar" +msgstr "Hagar" + +#: qcsrc/server/w_hagar.qc:395 qcsrc/server/w_seeker.qc:655 +#, c-format +msgid "%s played with tiny rockets" +msgstr "" + +#: qcsrc/server/w_hagar.qc:399 +#, c-format +msgid "%s hoped %s's missiles wouldn't bounce" +msgstr "" + +#: qcsrc/server/w_hagar.qc:401 qcsrc/server/w_seeker.qc:661 +#, c-format +msgid "%s was pummeled by %s" +msgstr "" + +#: qcsrc/server/w_hlac.qc:2 +msgid "Heavy Laser Assault Cannon" +msgstr "Heavy Laser Assault Cannon" + +#: qcsrc/server/w_hlac.qc:242 +#, c-format +msgid "%s was cut down by %s" +msgstr "" + +#: qcsrc/server/w_hook.qc:2 +msgid "Grappling Hook" +msgstr "Grappling Hook" + +#: qcsrc/server/w_hook.qc:266 qcsrc/server/w_porto.qc:296 +#, c-format +msgid "%s did the impossible" +msgstr "" + +#: qcsrc/server/w_hook.qc:268 +#, c-format +msgid "%s has run into %s's gravity bomb" +msgstr "" + +#: qcsrc/server/w_laser.qc:2 +msgid "Laser" +msgstr "Laser" + +#: qcsrc/server/w_laser.qc:311 +#, c-format +msgid "%s lasered themself to hell" +msgstr "" + +#: qcsrc/server/w_laser.qc:315 +#, c-format +msgid "%s was cut in half by %s's gauntlet" +msgstr "" + +#: qcsrc/server/w_laser.qc:317 +#, c-format +msgid "%s was lasered to death by %s" +msgstr "" + +#: qcsrc/server/w_minelayer.qc:2 +msgid "Mine Layer" +msgstr "Mine Layer" + +#: qcsrc/server/w_minelayer.qc:523 qcsrc/server/w_rocketlauncher.qc:501 +#, c-format +msgid "%s exploded" +msgstr "" + +#: qcsrc/server/w_minelayer.qc:527 +#, c-format +msgid "%s got too close to %s's mine" +msgstr "" + +#: qcsrc/server/w_minelayer.qc:529 +#, c-format +msgid "%s almost dodged %s's mine" +msgstr "" + +#: qcsrc/server/w_minelayer.qc:531 +#, c-format +msgid "%s stepped on %s's mine" +msgstr "" + +#: qcsrc/server/w_minstanex.qc:2 +msgid "MinstaNex" +msgstr "MinstaNex" + +#: qcsrc/server/w_minstanex.qc:293 qcsrc/server/w_nex.qc:253 +#: qcsrc/server/w_shotgun.qc:215 qcsrc/server/w_uzi.qc:317 +#, c-format +msgid "%s is now thinking with portals" +msgstr "" + +#: qcsrc/server/w_minstanex.qc:295 qcsrc/server/w_nex.qc:255 +#, c-format +msgid "%s has been vaporized by %s" +msgstr "" + +#: qcsrc/server/w_nex.qc:2 +msgid "Nex" +msgstr "Nex" + +#: qcsrc/server/w_porto.qc:2 +msgid "Port-O-Launch" +msgstr "Port-O-Launch" + +#: qcsrc/server/w_porto.qc:298 +#, c-format +msgid "%s felt %s doing the impossible to him" +msgstr "" + +#: qcsrc/server/w_rifle.qc:2 +msgid "Rifle" +msgstr "" + +#: qcsrc/server/w_rifle.qc:233 +#, c-format +msgid "%s shot themself automatically" +msgstr "" + +#: qcsrc/server/w_rifle.qc:235 +#, c-format +msgid "%s sniped themself somehow" +msgstr "" + +#: qcsrc/server/w_rifle.qc:242 +#, c-format +msgid "%s failed to hide from %s's bullet hail" +msgstr "" + +#: qcsrc/server/w_rifle.qc:244 +#, c-format +msgid "%s died in %s's bullet hail" +msgstr "" + +#: qcsrc/server/w_rifle.qc:251 +#, c-format +msgid "%s failed to hide from %s's rifle" +msgstr "" + +#: qcsrc/server/w_rifle.qc:256 +#, c-format +msgid "%s got hit in the head by %s" +msgstr "" + +#: qcsrc/server/w_rifle.qc:258 qcsrc/server/w_uzi.qc:321 +#, c-format +msgid "%s was sniped by %s" +msgstr "" + +#: qcsrc/server/w_rocketlauncher.qc:2 +msgid "Rocket Launcher" +msgstr "Rocket Launcher" + +#: qcsrc/server/w_rocketlauncher.qc:505 +#, c-format +msgid "%s got too close to %s's rocket" +msgstr "" + +#: qcsrc/server/w_rocketlauncher.qc:507 +#, c-format +msgid "%s almost dodged %s's rocket" +msgstr "" + +#: qcsrc/server/w_rocketlauncher.qc:509 +#, c-format +msgid "%s ate %s's rocket" +msgstr "" + +#: qcsrc/server/w_seeker.qc:2 +msgid "T.A.G. Seeker" +msgstr "T.A.G. Seeker" + +#: qcsrc/server/w_seeker.qc:659 +#, c-format +msgid "%s was tagged by %s" +msgstr "" + +#: qcsrc/server/w_shotgun.qc:2 +msgid "Shotgun" +msgstr "Shotgun" + +#: qcsrc/server/w_shotgun.qc:219 +#, c-format +msgid "%2$s ^7slapped %1$s ^7around a bit with a large ^2shotgun" +msgstr "" + +#: qcsrc/server/w_shotgun.qc:221 +#, c-format +msgid "%s was gunned by %s" +msgstr "" + +#: qcsrc/server/w_tuba.qc:2 +#, c-format +msgid "@!#%'n Tuba" +msgstr "@!#%'n Tuba" + +#: qcsrc/server/w_tuba.qc:252 +#, c-format +msgid "%s hurt his own ears with the @!#%%'n Tuba" +msgstr "" + +#: qcsrc/server/w_tuba.qc:256 +#, c-format +msgid "%s died of %s's great playing on the @!#%%'n Tuba" +msgstr "" + +#: qcsrc/server/w_uzi.qc:2 +msgid "Machine Gun" +msgstr "Machine Gun" + +#: qcsrc/server/w_uzi.qc:323 +#, c-format +msgid "%s was riddled full of holes by %s" +msgstr "" + +#, fuzzy +#~ msgid "Damage & water blur" +#~ msgstr "Размытие от урона:" + +#, fuzzy +#~ msgid "Powerup sharpen" +#~ msgstr "Панель бонусов" + +#~ msgid "Speedometer" +#~ msgstr "Спидометр" + +# "quake units per second" +# you can also translate it as inch/second +# as it is roughly the same +#~ msgid "qu/s (hidden)" +#~ msgstr "qu/s (без назв.)" + +#~ msgid "Show accelerometer" +#~ msgstr "Показывать акселерометр" + +#~ msgid "Accelerometer scale:" +#~ msgstr "Размер акселерометра:" + +#~ msgid "Sniper Rifle" +#~ msgstr "Sniper Rifle" + +#~ msgid "Waypoint settings:" +#~ msgstr "Настройки отметок:" + +#~ msgid "%d/%d" +#~ msgstr "%d/%d" diff --git a/menu.dat.se.po b/menu.dat.se.po new file mode 100644 index 0000000000..c21c30d3fc --- /dev/null +++ b/menu.dat.se.po @@ -0,0 +1,2910 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-09-02 07:51+0200\n" +"PO-Revision-Date: 2011-01-11 22:51+ZONE\n" +"Last-Translator: marcus256 <marcus256@users.sourceforge.net>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: se\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: qcsrc/common/mapinfo.qc:1092 qcsrc/menu/xonotic/skinlist.c:163 +#, c-format +msgid "%s: %s" +msgstr "" + +#: qcsrc/menu/gamecommand.qc:47 +#, c-format +msgid "error: status is %d\n" +msgstr "fel: status är %d\n" + +#: qcsrc/menu/gamecommand.qc:65 +msgid "Usage: menu_cmd command..., where possible commands are:\n" +msgstr "Användning: menu_cmd kommando..., där möjliga kommandon är:\n" + +#: qcsrc/menu/gamecommand.qc:66 +msgid " sync - reloads all cvars on the current menu page\n" +msgstr " sync - laddar om alla cvars på nuvarande menysida\n" + +#: qcsrc/menu/gamecommand.qc:67 +msgid " directmenu ITEM - select a menu item as main item\n" +msgstr " directmenu ITEM - utse en menyrad som huvudrad\n" + +#: qcsrc/menu/gamecommand.qc:193 +msgid "error creating curl handle\n" +msgstr "fel vid skapande av curl handle\n" + +#: qcsrc/menu/gamecommand.qc:239 +msgid "Invalid command. For a list of supported commands, try menu_cmd help.\n" +msgstr "" +"Ogiltigt kommando. För en lista över giltiga kommandon, prova menu_cmd " +"help.\n" + +#: qcsrc/menu/item/gecko.c:49 +msgid "Browser not initialized!" +msgstr "" + +#: qcsrc/menu/item/label.c:63 +#, c-format +msgid "NOTE: label text %s too wide for label, condensed by factor %f\n" +msgstr "" + +#: qcsrc/menu/item/listbox.c:300 +#, c-format +msgid "Item %d" +msgstr "" + +#: qcsrc/menu/item/slider.c:64 +#, c-format +msgid "%d (%s)" +msgstr "" + +#: qcsrc/menu/item/textslider.c:29 qcsrc/menu/item/textslider.c:31 +msgid "custom" +msgstr "" + +#: qcsrc/menu/menu.qc:29 +#, c-format +msgid "^4MQC Build information: ^1%s\n" +msgstr "" + +#: qcsrc/menu/xonotic/campaign.c:284 +#: qcsrc/menu/xonotic/dialog_singleplayer.c:134 +msgid "???" +msgstr "" + +#: qcsrc/menu/xonotic/campaign.c:285 +#, c-format +msgid "Level %d: %s" +msgstr "" + +#: qcsrc/menu/xonotic/cvarlist.c:85 +msgid "will be saved to config.cfg" +msgstr "" + +#: qcsrc/menu/xonotic/cvarlist.c:87 +msgid "will not be saved" +msgstr "" + +#: qcsrc/menu/xonotic/cvarlist.c:89 +msgid "private" +msgstr "" + +#: qcsrc/menu/xonotic/cvarlist.c:91 +msgid "engine setting" +msgstr "" + +#: qcsrc/menu/xonotic/cvarlist.c:93 +msgid "read only" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_credits.c:5 +msgid "Credits" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_credits.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:269 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:41 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:57 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:61 +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:21 +msgid "OK" +msgstr "OK" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:4 +msgid "Welcome" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:33 +msgid "" +"Welcome to Xonotic, please select your language preference and enter your " +"player name to get started. You can change these options later through the " +"menu system." +msgstr "" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:38 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:35 +#, fuzzy +msgid "Text language:" +msgstr "Avstånd för pikar:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:47 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:40 +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:39 +msgid "Name:" +msgstr "Namn:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:69 +#, fuzzy +msgid "Save settings" +msgstr "Inställningar" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:4 +msgid "Ammo Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:22 +msgid "Ammunition display:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:25 +msgid "Show only current ammo type" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:28 +msgid "Align icon:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:29 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:36 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:40 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:40 +msgid "Left" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:38 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:41 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:41 +msgid "Right" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:4 +msgid "Centerprint" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:23 +msgid "Message duration:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:27 +#, fuzzy +msgid "Fade time:" +msgstr "Tona ut efter:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:31 +msgid "Flip messages order" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:33 +#, fuzzy +msgid "Text alignment:" +msgstr "Avstånd för pikar:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:37 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:50 +msgid "Center" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:41 +msgid "Font scale:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:4 +msgid "Chat Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:22 +msgid "Chat entries:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:25 +msgid "Chat size:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:29 +msgid "Chat lifetime:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:33 +msgid "Chat beep sound" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:4 +msgid "Engine Info Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:22 +msgid "Engine info:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:25 +msgid "Use an averaging algorithm for fps" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:4 +msgid "Health/Armor Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:22 +msgid "Enable status bar" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:24 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:24 +msgid "Status bar alignment:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:42 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:42 +msgid "Inward" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:43 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:43 +msgid "Outward" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:37 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:37 +msgid "Icon alignment:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:45 +msgid "Flip health and armor positions" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:4 +msgid "Info Messages Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:22 +msgid "Info messages:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:25 +msgid "Flip align" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_modicons.c:4 +msgid "Mod Icons Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:4 +msgid "Notification Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:22 +msgid "Notifications:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:25 +msgid "Also print notifications to the console" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:28 +msgid "Flip notify order" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:31 +msgid "Entry lifetime:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:35 +msgid "Entry fadetime:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:4 +msgid "Physics Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:21 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:21 +msgid "Panel disabled" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:23 +msgid "Panel enabled" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:24 +msgid "Panel enabled even observing" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:25 +msgid "Panel enabled only in Race/CTS" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:31 +msgid "Status bar" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:48 +msgid "Left align" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:34 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:52 +msgid "Right align" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:35 +msgid "Inward align" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:36 +msgid "Outward align" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:40 +msgid "Flip speed/acceleration positions" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:44 +#, fuzzy +msgid "Speed:" +msgstr "Hastighet (kB/s):" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:45 +msgid "Include vertical speed" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:56 +msgid "Speed unit:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:58 +msgid "qu/s" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:59 +msgid "m/s" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:60 +msgid "km/h" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:61 +msgid "mph" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:62 +msgid "knots" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:64 +#, fuzzy +msgid "Show" +msgstr "Visa Ammunition" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:67 +#, fuzzy +msgid "Top speed" +msgstr "Nätverkshastighet:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:73 +msgid "Acceleration:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:74 +msgid "Include vertical acceleration" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:4 +msgid "Powerups Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:45 +msgid "Flip strength and shield positions" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:4 +msgid "Pressed Keys Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:22 +msgid "Panel enabled when spectating" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:23 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:23 +msgid "Panel always enabled" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:30 +msgid "Forced aspect:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_racetimer.c:4 +msgid "Race Timer Panel" +msgstr "Tidtagningspanel för Lopp" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:4 +msgid "Radar Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:22 +msgid "Panel enabled in teamgames" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:29 +msgid "Radar:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:32 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:43 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:154 +#: qcsrc/menu/xonotic/util.qc:600 +msgid "Alpha:" +msgstr "Alfa:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:36 +msgid "Rotation:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:38 +msgid "Forward" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:39 +msgid "West" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:40 +msgid "South" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:41 +msgid "East" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:42 +msgid "North" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:46 +msgid "Scale:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:50 +msgid "Zoom mode:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:52 +msgid "Zoomed in" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:53 +msgid "Zoomed out" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:54 +msgid "Always zoomed" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:55 +msgid "Never zoomed" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:4 +msgid "Score Panel" +msgstr "Poängpanel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:22 +msgid "Score:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:25 +msgid "Rankings:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:26 +msgid "Off" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:27 +msgid "And me" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:28 +msgid "Pure" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:4 +msgid "Timer Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:22 +msgid "Timer:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:25 +msgid "Show elapsed time" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:4 +msgid "Vote Panel" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:22 +msgid "Alpha after voting:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:4 +msgid "Weapons Panel" +msgstr "Vapenpanel" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:24 +msgid "Fade out after:" +msgstr "Tona ut efter:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:26 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:36 +msgid "Never" +msgstr "Aldrig" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:28 +#, c-format +msgid "%ds" +msgstr "%ds" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:32 +msgid "Fade effect:" +msgstr "Uttoningseffekt:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:35 +msgid "EF^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:36 +msgid "Slide" +msgstr "Ingen" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:37 +msgid "Alpha" +msgstr "Alfa" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:38 +#, fuzzy +msgid "EF^Both" +msgstr "Både och" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:42 +msgid "Weapon icons:" +msgstr "Vapenikoner:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:45 +msgid "Show weapon ID as:" +msgstr "Visa vapen-ID som:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:46 +msgid "SHOWAS^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:47 +msgid "Number" +msgstr "Nummer" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:48 +msgid "Bind" +msgstr "Koppla" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:51 +msgid "Show Accuracy" +msgstr "Visa Noggrannhet" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:52 +msgid "Show Ammo" +msgstr "Visa Ammunition" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:55 +msgid "Ammo bar color:" +msgstr "Färg på ammoraden:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:61 +msgid "Ammo bar alpha:" +msgstr "Alfa på ammoraden:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:4 +msgid "Panel HUD Setup" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:21 +msgid "Panel background defaults:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:23 qcsrc/menu/xonotic/util.qc:575 +msgid "Background:" +msgstr "Bakgrund:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:25 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:37 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:52 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:91 qcsrc/menu/xonotic/util.qc:578 +#: qcsrc/menu/xonotic/util.qc:594 qcsrc/menu/xonotic/util.qc:611 +msgid "Disable" +msgstr "Inaktivera" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:30 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:77 qcsrc/menu/xonotic/util.qc:583 +msgid "Color:" +msgstr "Färg:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:35 qcsrc/menu/xonotic/util.qc:591 +msgid "Border size:" +msgstr "Ramstorlek:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:50 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:89 +msgid "Team color:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:58 qcsrc/menu/xonotic/util.qc:617 +msgid "Test team color in configure mode" +msgstr "Testa lagfärg i konfigureringsläge" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:61 qcsrc/menu/xonotic/util.qc:620 +msgid "Padding:" +msgstr "Utfyllnad:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:68 +msgid "HUD Dock:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:70 +#, fuzzy +msgid "DOCK^Disabled" +msgstr "Inaktivera" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:71 +msgid "DOCK^Small" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:72 +msgid "DOCK^Medium" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:73 +msgid "DOCK^Large" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:96 +msgid "Grid settings:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:99 +msgid "Snap panels to grid" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:102 +msgid "Grid size:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:103 +msgid "X:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:109 +msgid "Y:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:117 +msgid "Exit setup" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:4 +msgid "Multiplayer" +msgstr "Flera Spelare" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:18 +msgid "Servers" +msgstr "Servrar" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:19 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:5 +msgid "Create" +msgstr "Skapa" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:20 +msgid "Demos" +msgstr "Demos" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:5 +msgid "Player Setup" +msgstr "Spelarinställning" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:34 +msgid "Game type:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:46 +msgid "Match settings:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:49 +msgid "Time limit:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:53 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:61 +msgid "Use map specified default" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:56 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:155 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:156 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:157 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:161 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:162 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:163 +msgid "Point limit:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:64 +msgid "Player slots:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:67 +msgid "Number of bots:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:71 +msgid "Bot skill:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:74 +msgid "Botlike" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:75 +msgid "Beginner" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:76 +msgid "You will win" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:77 +msgid "You can win" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:78 +msgid "You might win" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:79 +msgid "Advanced" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:80 +msgid "Expert" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:81 +msgid "Pro" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:82 +msgid "Assassin" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:83 +msgid "Unhuman" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:84 +msgid "Godlike" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:88 +msgid "Mutators..." +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:97 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:57 +msgid "Advanced settings..." +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:104 +msgid "Map list:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:110 +msgid "Select all" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:113 +msgid "Select none" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:119 +msgid "Start Multiplayer!" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:154 +msgid "Capture limit:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:158 +msgid "Lives:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:159 +msgid "Laps:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:160 +msgid "Goals:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:164 +msgid "Frag limit:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:6 +msgid "Advanced server settings" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:25 +msgid "Game settings:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:28 +msgid "Allow spectating" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:31 +msgid "Spawn shield:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:36 +msgid "Game speed:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:40 +msgid "Teamplay settings:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:43 +msgid "Friendly fire scale:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:47 +msgid "Virtual friendly fire (effect only)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:50 +msgid "Friendly fire penalty:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:54 +msgid "Virtual penalty (effect only)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:57 +msgid "Teams:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:66 +msgid "Map voting:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:68 +msgid "No voting" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:69 +msgid "2 choices" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:70 +msgid "3 choices" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:71 +msgid "4 choices" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:72 +msgid "5 choices" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:73 +msgid "6 choices" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:74 +msgid "7 choices" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:75 +msgid "8 choices" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:76 +msgid "9 choices" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:79 +msgid "Simple majority wins vcall" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:5 +msgid "Map Information" +msgstr "Kartinformation" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "Full item placement" +msgstr "Fullständing sakplacering" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "MinstaGib only" +msgstr "Endast MinstaGib" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:78 +msgid "Title:" +msgstr "Titel:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:84 +msgid "Author:" +msgstr "Upphovsman:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:90 +msgid "Features:" +msgstr "Egenskaper." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:95 +msgid "Game types:" +msgstr "Speltyper:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:118 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:314 +msgid "Close" +msgstr "Stäng" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:121 +#, fuzzy +msgid "MAP^Play" +msgstr "Spela" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:7 +msgid "Mutators" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:33 +msgid "All Weapons Arena" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:35 +msgid "Most Weapons Arena" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:56 +#, c-format +msgid "%s Arena" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:68 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:167 +msgid "Dodging" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:70 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:250 +msgid "MinstaGib" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:253 +msgid "NIX" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:74 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:205 +msgid "Rocket Flying" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:78 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:264 +msgid "No start weapons" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:80 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:189 +msgid "Low gravity" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:170 +msgid "Cloaked" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:84 +msgid "Hook" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:86 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:173 +msgid "Midair" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:88 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:176 +msgid "Vampire" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:90 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:208 +msgid "Piñata" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:92 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:211 +msgid "Weapons stay" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:94 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:180 +msgid "Blood loss" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:96 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:202 +msgid "Jet pack" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:98 +msgid "MUT^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:164 +msgid "Gameplay mutators:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:196 +msgid "Weapon & item mutators:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:199 +msgid "Grappling hook" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:215 +msgid "Weapon arenas:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:218 +msgid "Regular (no arena)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:239 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:256 +msgid "with laser" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:247 +msgid "Special arenas:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:260 +msgid "Most weapons" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:4 +msgid "Demo" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:28 +msgid "Record demos while playing" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:32 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:28 +msgid "Filter:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:29 +#: qcsrc/menu/xonotic/dialog_settings_input.c:41 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:24 +msgid "Clear" +msgstr "Rensa" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:43 +msgid "Timedemo" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:46 +#, fuzzy +msgid "DEMO^Play" +msgstr "Spela" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:4 +msgid "Join" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:36 +msgid "SRVS^Empty" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:40 +#, fuzzy +msgid "SRVS^Full" +msgstr "Fullt" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:44 +msgid "Pause" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:56 +msgid "Address:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:67 +msgid "Info..." +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:317 +msgid "Join!" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:5 +msgid "Server Information" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:115 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:116 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:183 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:189 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:199 +msgid "N/A" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:158 +#, c-format +msgid "%d/%d, %d free player slots" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +#, c-format +msgid "%d modified settings" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +msgid "Official settings" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:197 +msgid "N/A (can't connect)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:205 +msgid "not supported (can't connect)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:207 +msgid "not supported (won't encrypt)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:211 +msgid "supported (will encrypt)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:213 +msgid "supported (won't encrypt)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:217 +msgid "requested (will encrypt)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:219 +msgid "requested (won't encrypt)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:223 +msgid "required (can't connect)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:225 +msgid "required (will encrypt)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:246 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:269 +msgid "Players:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:254 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:38 +msgid "Type:" +msgstr "Typ:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:259 +msgid "Map:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:264 +msgid "Gameplay:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:274 +msgid "Bots:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:279 +msgid "Mod:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:284 +msgid "Version:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:289 +msgid "Ping:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:295 +msgid "CA:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:301 +msgid "Key:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:307 +msgid "Encryption:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:63 +msgid "Model:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:88 +msgid "Field of view:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:92 +msgid "View bobbing:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:96 +msgid "Zoom factor:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:100 +msgid "Zoom speed:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:103 +msgid "Weapon settings..." +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:110 +msgid "Crosshair:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:111 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:139 +msgid "Per weapon" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:130 +msgid "Crosshair size:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:134 +msgid "Crosshair alpha:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:138 +#, fuzzy +msgid "Crosshair color:" +msgstr "Färg på ammoraden:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:140 +msgid "By health" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:143 +msgid "Custom" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:148 +msgid "Enable center dot" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:151 +msgid "Size:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:158 +msgid "Hit test:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:159 +msgid "HTST^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:160 +msgid "TrueAim" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:161 +msgid "Enemies" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:164 +msgid "Waypoints setup..." +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:169 +msgid "Enter HUD editor" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:174 +msgid "Force models:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:175 +msgid "MDL^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:176 +msgid "MDL^Custom" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:177 +#, fuzzy +msgid "MDL^All" +msgstr "Alla" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:180 +msgid "Disable gore effects" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:182 +msgid "Gibs:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:184 +msgid "GIBS^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:185 +msgid "GIBS^Few" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:186 +msgid "GIBS^Many" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:187 +msgid "GIBS^Lots" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:191 +msgid "Damage splash:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:195 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:173 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:194 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:30 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:41 +#: qcsrc/menu/xonotic/dialog_settings_video.c:109 +msgid "Apply immediately" +msgstr "Tillämpa nu" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:5 +msgid "Waypoints" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:23 +msgid "Show base waypoints" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:25 +msgid "Waypoint scale:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:29 +msgid "Waypoint alpha:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:34 +msgid "Show names:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:37 +msgid "Teammates" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:38 +msgid "All players" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:6 +msgid "Weapon settings" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:29 +msgid "Weapon priority list:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:34 +msgid "Up" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:37 +msgid "Down" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:41 +msgid "Use priority list for weapon cycling" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:43 +msgid "Auto switch weapons on pickup" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:45 +msgid "Draw 1st person weapon model" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:55 +msgid "Flip view horizontally" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_news.c:4 +msgid "News" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_news.c:18 +msgid "http://www.xonotic.org/team/blog/" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_quit.c:4 +msgid "Quit" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_quit.c:17 +msgid "Are you sure you want to quit?" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_quit.c:20 +msgid "Yes" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_quit.c:21 +msgid "No" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings.c:4 +msgid "Settings" +msgstr "Inställningar" + +#: qcsrc/menu/xonotic/dialog_settings.c:18 +#: qcsrc/menu/xonotic/dialog_settings_input.c:4 +msgid "Input" +msgstr "Inmatning" + +#: qcsrc/menu/xonotic/dialog_settings.c:19 +#: qcsrc/menu/xonotic/dialog_settings_video.c:4 +msgid "Video" +msgstr "Video" + +#: qcsrc/menu/xonotic/dialog_settings.c:20 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:4 +msgid "Effects" +msgstr "Effekter" + +#: qcsrc/menu/xonotic/dialog_settings.c:21 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:4 +msgid "Audio" +msgstr "Ljud" + +#: qcsrc/menu/xonotic/dialog_settings.c:22 +#: qcsrc/menu/xonotic/dialog_settings_network.c:4 +msgid "Network" +msgstr "Nätverk" + +#: qcsrc/menu/xonotic/dialog_settings.c:23 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:4 +msgid "Misc" +msgstr "Blandat" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:27 +msgid "Master:" +msgstr "Master:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:33 +msgid "Music:" +msgstr "Musik:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:41 +#, fuzzy +msgid "VOL^Ambient:" +msgstr "Bakgrund" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:48 +msgid "Info:" +msgstr "Info:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:55 +msgid "Items:" +msgstr "Saker:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:62 +msgid "Pain:" +msgstr "Smärta:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:69 +msgid "Player:" +msgstr "Spelare:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:76 +msgid "Shots:" +msgstr "Skott:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:83 +msgid "Voice:" +msgstr "Röst:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:91 +msgid "Weapons:" +msgstr "Vapen:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:98 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:156 +msgid "Frequency:" +msgstr "Frekvens:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:100 +msgid "8 kHz" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:101 +msgid "11.025 kHz" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:102 +msgid "16 kHz" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:103 +msgid "22.05 kHz" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:104 +msgid "24 kHz" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:105 +msgid "32 kHz" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:106 +msgid "44.1 kHz" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:107 +msgid "48 kHz" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:110 +msgid "Channels:" +msgstr "Kanaler." + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:112 +msgid "Mono" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:113 +msgid "Stereo" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:114 +msgid "2.1" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:115 +msgid "4" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:116 +msgid "5" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:117 +msgid "5.1" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:118 +msgid "6.1" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:119 +msgid "7.1" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:123 +msgid "Swap Stereo" +msgstr "Växla Stereo" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:127 +msgid "Headphone friendly mode" +msgstr "Hörlursvänligt läge" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:131 +msgid "Spatial voices:" +msgstr "Spatiala kanaler:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:132 +msgid "VOCS^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:133 +#, fuzzy +msgid "VOCS^Taunts" +msgstr "Pikar" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:134 +msgid "VOCS^All" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:137 +msgid "Taunt range:" +msgstr "Avstånd för pikar:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:140 +#, fuzzy +msgid "RNG^Very short" +msgstr "Väldigt kort" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:141 +#, fuzzy +msgid "RNG^Short" +msgstr "Kort" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:142 +#, fuzzy +msgid "RNG^Normal" +msgstr "Normalt" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:143 +#, fuzzy +msgid "RNG^Long" +msgstr "Långt" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:144 +#, fuzzy +msgid "RNG^Full" +msgstr "Fullt" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:151 +msgid "Automatic taunts" +msgstr "Automatiska pikar" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:160 +msgid "Time warning:" +msgstr "Tidsvarning:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:162 +msgid "WRN^None" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:163 +msgid "1 minute" +msgstr "1 minut" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:164 +msgid "5 minutes" +msgstr "5 minuter" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:165 +#, fuzzy +msgid "WRN^Both" +msgstr "Både och" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:168 +msgid "Hit indicator" +msgstr "Skadoindikator" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:170 +msgid "Menu sounds" +msgstr "Menyljud" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:38 +msgid "Quality preset:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:41 +msgid "PRE^OMG!" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:42 +msgid "PRE^Low" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:43 +msgid "PRE^Medium" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:44 +#, fuzzy +msgid "PRE^Normal" +msgstr "Normalt" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:45 +msgid "PRE^High" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:46 +msgid "PRE^Ultra" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:48 +msgid "PRE^Ultimate" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:52 +msgid "Geometry detail:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:54 +msgid "DET^Lowest" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:55 +msgid "DET^Low" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:56 +#, fuzzy +msgid "DET^Normal" +msgstr "Normalt" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:57 +msgid "DET^Good" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:58 +msgid "DET^Best" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:59 +msgid "DET^Insane" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:62 +msgid "Antialiasing:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:64 +#, fuzzy +msgid "AA^Disabled" +msgstr "Inaktivera" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:65 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:103 +msgid "2x" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:66 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:104 +msgid "4x" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:70 +msgid "Texture resolution:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:73 +msgid "RES^Leet" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:74 +msgid "RES^Lowest" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:75 +msgid "RES^Low" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:76 +#, fuzzy +msgid "RES^Normal" +msgstr "Normalt" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:77 +msgid "RES^Good" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:78 +msgid "RES^Best" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:91 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:94 +msgid "Avoid lossy texture compression" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:100 +msgid "Anisotropy:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:102 +#, fuzzy +msgid "ANISO^Disabled" +msgstr "Inaktivera" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:105 +msgid "8x" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:106 +msgid "16x" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:110 +msgid "Particle quality:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:113 +msgid "Particle distance:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:117 +msgid "Decals" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:118 +msgid "Decals on models" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:122 +msgid "Distance:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:128 +msgid "Time:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:134 +msgid "Use lightmaps" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:135 +msgid "Deluxe mapping" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:137 +msgid "Gloss" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:140 +msgid "Offset mapping" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:142 +msgid "Relief mapping" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:145 +msgid "Reflections:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:148 +msgid "Blurred" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:149 +msgid "REFL^Good" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:150 +msgid "Sharp" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:155 +msgid "Show surfaces" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:157 +msgid "No dynamic lighting" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:159 +msgid "Flash blend approximation" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:161 +msgid "Realtime dynamic lighting" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:162 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:166 +msgid "Shadows" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:165 +msgid "Realtime world lighting" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:170 +msgid "Use normal maps" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:172 +msgid "Soft shadows" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:175 +msgid "Coronas" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:176 +msgid "Use Occlusion Queries" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:178 +msgid "Bloom" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:180 +msgid "High Dynamic Range (HDR)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:184 +msgid "Motion blur:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:189 +msgid "Blur and sharpen postprocessing" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:26 +msgid "Key bindings:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:31 +msgid "Change key..." +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:35 +msgid "Edit..." +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:46 +msgid "Sensitivity:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:51 +msgid "UI mouse speed:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:55 +msgid "Mouse filter" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:57 +msgid "Invert mouse" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:60 +#: qcsrc/menu/xonotic/dialog_settings_input.c:62 +msgid "Use joystick input" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:65 +#: qcsrc/menu/xonotic/dialog_settings_input.c:67 +msgid "Turn off OS mouse acceleration" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:69 +msgid "\"enter console\" also closes" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:5 +msgid "User defined key bind" +msgstr "Användardefinierad tangentkoppling" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:42 +msgid "Command when pressed:" +msgstr "Kommando när nedtryckt:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:45 +msgid "Command when released:" +msgstr "Kommando när uppsläppt:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:48 +msgid "Save" +msgstr "Spara" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:51 +msgid "Cancel" +msgstr "Avbryt" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:26 +msgid "Menu skins:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:47 +msgid "Show current time" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:49 +msgid "Show current date" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:51 +msgid "Show frames per second" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:53 +msgid "Minimize input latency" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:5 +msgid "Advanced settings" +msgstr "Avancerade inställningar" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:23 +msgid "Cvar filter:" +msgstr "Cvar-filter:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:34 +msgid "Setting:" +msgstr "Inställning:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:42 +msgid "Value:" +msgstr "Värde:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:56 +msgid "Description:" +msgstr "Beskrivning:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:26 +msgid "Client-side movement prediction" +msgstr "Rörelseprediktering i klienten" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:30 +msgid "Show netgraph" +msgstr "Visa nätgraf" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:33 +msgid "Network speed:" +msgstr "Nätverkshastighet:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:35 +msgid "56k" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:36 +msgid "ISDN" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:37 +msgid "Slow ADSL" +msgstr "Långsam ADSL" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:38 +msgid "Fast ADSL" +msgstr "Snabb ADSL" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:39 +msgid "Broadband" +msgstr "Bredband" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:42 +msgid "Input packets/s:" +msgstr "Inputpaket/s" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:46 +msgid "HTTP downloads:" +msgstr "HTTP-nedladdningar:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:49 +msgid "Downloads:" +msgstr "Nedladdningar:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:53 +msgid "Speed (kB/s):" +msgstr "Hastighet (kB/s):" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:57 +msgid "Client UDP port:" +msgstr "Klientens UDB-port:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:26 +msgid "Resolution:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:29 +msgid "Font/UI size:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:31 +msgid "SZ^Unreadable" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:32 +msgid "SZ^Tiny" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:33 +msgid "SZ^Little" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:34 +msgid "SZ^Small" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:35 +msgid "SZ^Medium" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:36 +msgid "SZ^Large" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:37 +msgid "SZ^Huge" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:38 +msgid "SZ^Gigantic" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:39 +msgid "SZ^Colossal" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:42 +msgid "Color depth:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:45 +msgid "Full screen" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:46 +msgid "Vertical Synchronization" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:49 +msgid "Use OpenGL 2.0 shaders (GLSL)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:52 +msgid "Use GLSL to handle color control" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:56 +msgid "Vertex Buffer Objects (VBOs)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:59 +msgid "VBO^Off" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:60 +msgid "Vertices, some Tris (compatible)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:63 +msgid "Vertices" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:64 +msgid "Vertices and Triangles" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:67 +msgid "Depth first:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:69 +#, fuzzy +msgid "DF^Disabled" +msgstr "Inaktivera" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:70 +msgid "DF^World" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:71 +#, fuzzy +msgid "DF^All" +msgstr "Alla" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:75 +msgid "Disable multithreaded OpenGL" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:77 +msgid "Wait for GPU to finish each frame" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:80 +msgid "Brightness:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:83 +msgid "Contrast:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:86 +msgid "Gamma:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:91 +msgid "Contrast boost:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:96 +msgid "Saturation:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:102 +#, fuzzy +msgid "LIT^Ambient:" +msgstr "Bakgrund" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:105 +msgid "Intensity:" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:4 +msgid "Singleplayer" +msgstr "En Spelare" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:127 +msgid "Instant action! (random map with bots)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:148 +msgid "Start Singleplayer!" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:4 +msgid "Winner" +msgstr "Vinnare" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:5 +msgid "Team Selection" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:41 +msgid "join 'best' team (auto-select)" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:45 +msgid "red" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:46 +msgid "blue" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:47 +msgid "yellow" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:48 +msgid "pink" +msgstr "" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:51 +msgid "spectate" +msgstr "" + +#: qcsrc/menu/xonotic/mainwindow.c:35 qcsrc/menu/xonotic/mainwindow.c:38 +msgid "Do not press this button again!" +msgstr "" + +#: qcsrc/menu/xonotic/maplist.c:278 +msgid "" +"Huh? Can't play this (m is NULL). Refiltering so this won't happen again.\n" +msgstr "" + +#: qcsrc/menu/xonotic/maplist.c:286 +#, c-format +msgid "%s's Xonotic Server" +msgstr "" + +#: qcsrc/menu/xonotic/maplist.c:291 +msgid "" +"Huh? Can't play this (invalid game type). Refiltering so this won't happen " +"again.\n" +msgstr "" + +#: qcsrc/menu/xonotic/playermodel.c:174 +msgid "<no model found>" +msgstr "<ingen modell funnen>" + +#: qcsrc/menu/xonotic/serverlist.c:185 +msgid "Remove" +msgstr "" + +#: qcsrc/menu/xonotic/serverlist.c:187 +msgid "Bookmark" +msgstr "" + +#: qcsrc/menu/xonotic/serverlist.c:527 +msgid "Ping" +msgstr "" + +#: qcsrc/menu/xonotic/serverlist.c:528 +msgid "Host name" +msgstr "" + +#: qcsrc/menu/xonotic/serverlist.c:529 +msgid "Map" +msgstr "" + +#: qcsrc/menu/xonotic/serverlist.c:530 +msgid "Type" +msgstr "" + +#: qcsrc/menu/xonotic/serverlist.c:531 +msgid "Players" +msgstr "" + +#: qcsrc/menu/xonotic/skinlist.c:105 +msgid "<TITLE>" +msgstr "" + +#: qcsrc/menu/xonotic/skinlist.c:106 +msgid "<AUTHOR>" +msgstr "" + +#: qcsrc/menu/xonotic/slider_decibels.c:50 +msgid "VOL^OFF" +msgstr "" + +#: qcsrc/menu/xonotic/slider_decibels.c:52 +msgid "VOL^MAX" +msgstr "" + +#: qcsrc/menu/xonotic/slider_decibels.c:53 +#, c-format +msgid "%s dB" +msgstr "" + +#: qcsrc/menu/xonotic/slider_resolution.c:65 +#, c-format +msgid "%dx%d" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:270 +#, c-format +msgid "Received HTTP request data for an invalid id %d.\n" +msgstr "Mottog HTTP-förfrågan för en ogiltig ID %d.\n" + +#: qcsrc/menu/xonotic/util.qc:285 +#, c-format +msgid "error receiving update notification: status is %d\n" +msgstr "fel vid mottagande av uppdateringsnotifiering: status 'r %d\n" + +#: qcsrc/menu/xonotic/util.qc:290 +msgid "error: received HTML instead of an update notification\n" +msgstr "fel: mottog HTML istället för en uppdateringsnotifiering" + +#: qcsrc/menu/xonotic/util.qc:295 +msgid "error: received carriage returns from update notification server\n" +msgstr "fel: mottog radslut från uppdateringsnotifieringsservern" + +#: qcsrc/menu/xonotic/util.qc:316 +#, c-format +msgid "" +"Update can be downloaded at:\n" +"%s\n" +msgstr "" +"Uppdatering kan laddas ner från:\n" +"%s\n" + +#: qcsrc/menu/xonotic/util.qc:337 +msgid "Autogenerating mapinfo for newly added maps..." +msgstr "Automatgenererar kartinfo för nyligen tillagda kartor..." + +#: qcsrc/menu/xonotic/util.qc:367 +#, c-format +msgid "^1%s TEST BUILD" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:432 +#, c-format +msgid "Update to %s now!" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:501 +msgid "" +"^1ERROR: Texture compression is required but not supported.\n" +"^1Expect visual problems.\n" +msgstr "" +"^1FEL: Texturkompression krävs men stöds ej.\n" +"^1Räkna med visuella problem.\n" + +#: qcsrc/menu/xonotic/util.qc:523 +msgid "Arena" +msgstr "Arena" + +#: qcsrc/menu/xonotic/util.qc:524 +msgid "Assault" +msgstr "Anfall" + +#: qcsrc/menu/xonotic/util.qc:525 +msgid "Capture The Flag" +msgstr "Erövra Flaggan" + +#: qcsrc/menu/xonotic/util.qc:526 +msgid "Clan Arena" +msgstr "Klan Arena" + +#: qcsrc/menu/xonotic/util.qc:527 +msgid "Deathmatch" +msgstr "Dödsmatch" + +#: qcsrc/menu/xonotic/util.qc:528 +msgid "Domination" +msgstr "Dominering" + +#: qcsrc/menu/xonotic/util.qc:529 +msgid "Freeze Tag" +msgstr "Frys-Kull" + +#: qcsrc/menu/xonotic/util.qc:530 +msgid "Keepaway" +msgstr "Håll Dig Undan" + +#: qcsrc/menu/xonotic/util.qc:531 +msgid "Key Hunt" +msgstr "Nyckeljakt" + +#: qcsrc/menu/xonotic/util.qc:532 +msgid "Last Man Standing" +msgstr "Herre På Täppan" + +#: qcsrc/menu/xonotic/util.qc:533 +msgid "Nexball" +msgstr "Nexboll" + +#: qcsrc/menu/xonotic/util.qc:534 +msgid "Onslaught" +msgstr "Stormning" + +#: qcsrc/menu/xonotic/util.qc:535 +msgid "Race" +msgstr "Lopp" + +#: qcsrc/menu/xonotic/util.qc:536 +msgid "Race CTS" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:537 +msgid "Runematch" +msgstr "" + +#: qcsrc/menu/xonotic/util.qc:538 +msgid "Team Deathmatch" +msgstr "Dödsmatch i Lag" + +#: qcsrc/menu/xonotic/util.qc:557 +#, c-format +msgid "@!#%'n Tuba Throwing" +msgstr "@!#%'n Tubakastning" + +#: qcsrc/menu/xonotic/util.qc:577 qcsrc/menu/xonotic/util.qc:593 +#: qcsrc/menu/xonotic/util.qc:602 qcsrc/menu/xonotic/util.qc:610 +#: qcsrc/menu/xonotic/util.qc:622 +msgid "Default" +msgstr "Standard" + +#: qcsrc/menu/xonotic/util.qc:588 +msgid "Use default" +msgstr "Använd standard" + +#: qcsrc/menu/xonotic/util.qc:608 +msgid "Team Color:" +msgstr "Lagfärg:" + +#: qcsrc/menu/xonotic/util.qh:47 +msgid "Enable panel" +msgstr "" + +#: qcsrc/server/w_crylink.qc:2 +msgid "Crylink" +msgstr "" + +#: qcsrc/server/w_crylink.qc:666 +#, c-format +msgid "%s succeeded at self-destructing themself with the Crylink" +msgstr "" + +#: qcsrc/server/w_crylink.qc:671 +#, c-format +msgid "%s could not hide from %s's Crylink" +msgstr "" + +#: qcsrc/server/w_crylink.qc:673 +#, c-format +msgid "%s was too close to %s's Crylink" +msgstr "" + +#: qcsrc/server/w_crylink.qc:675 +#, c-format +msgid "%s took a close look at %s's Crylink" +msgstr "" + +#: qcsrc/server/w_electro.qc:2 +msgid "Electro" +msgstr "" + +#: qcsrc/server/w_electro.qc:574 +#, c-format +msgid "%s could not remember where they put plasma" +msgstr "" + +#: qcsrc/server/w_electro.qc:576 +#, c-format +msgid "%s played with plasma" +msgstr "" + +#: qcsrc/server/w_electro.qc:583 +#, c-format +msgid "%s just noticed %s's blue ball" +msgstr "" + +#: qcsrc/server/w_electro.qc:585 +#, c-format +msgid "%s got in touch with %s's blue ball" +msgstr "" + +#: qcsrc/server/w_electro.qc:590 +#, c-format +msgid "%s felt the electrifying air of %s's combo" +msgstr "" + +#: qcsrc/server/w_electro.qc:592 +#, c-format +msgid "%s got too close to %s's blue beam" +msgstr "" + +#: qcsrc/server/w_electro.qc:594 +#, c-format +msgid "%s was blasted by %s's blue beam" +msgstr "" + +#: qcsrc/server/w_fireball.qc:2 +#, fuzzy +msgid "Fireball" +msgstr "Nexboll" + +#: qcsrc/server/w_fireball.qc:417 +#, c-format +msgid "%s forgot about some firemine" +msgstr "" + +#: qcsrc/server/w_fireball.qc:419 qcsrc/server/w_hlac.qc:240 +#, c-format +msgid "%s should have used a smaller gun" +msgstr "" + +#: qcsrc/server/w_fireball.qc:426 +#, c-format +msgid "%s tried to catch %s's firemine" +msgstr "" + +#: qcsrc/server/w_fireball.qc:428 +#, c-format +msgid "%s fatefully ignored %s's firemine" +msgstr "" + +#: qcsrc/server/w_fireball.qc:435 +#, c-format +msgid "%s could not hide from %s's fireball" +msgstr "" + +#: qcsrc/server/w_fireball.qc:437 +#, c-format +msgid "%s saw the pretty lights of %s's fireball" +msgstr "" + +#: qcsrc/server/w_fireball.qc:440 +#, c-format +msgid "%s got too close to %s's fireball" +msgstr "" + +#: qcsrc/server/w_fireball.qc:442 +#, c-format +msgid "%s tasted %s's fireball" +msgstr "" + +#: qcsrc/server/w_grenadelauncher.qc:2 +msgid "Mortar" +msgstr "" + +#: qcsrc/server/w_grenadelauncher.qc:383 +#, c-format +msgid "%s tried out his own grenade" +msgstr "" + +#: qcsrc/server/w_grenadelauncher.qc:385 +#, c-format +msgid "%s detonated" +msgstr "" + +#: qcsrc/server/w_grenadelauncher.qc:391 +#, c-format +msgid "%s didn't see %s's grenade" +msgstr "" + +#: qcsrc/server/w_grenadelauncher.qc:393 +#, c-format +msgid "%s almost dodged %s's grenade" +msgstr "" + +#: qcsrc/server/w_grenadelauncher.qc:395 +#, c-format +msgid "%s ate %s's grenade" +msgstr "" + +#: qcsrc/server/w_hagar.qc:2 +msgid "Hagar" +msgstr "" + +#: qcsrc/server/w_hagar.qc:395 qcsrc/server/w_seeker.qc:655 +#, c-format +msgid "%s played with tiny rockets" +msgstr "" + +#: qcsrc/server/w_hagar.qc:399 +#, c-format +msgid "%s hoped %s's missiles wouldn't bounce" +msgstr "" + +#: qcsrc/server/w_hagar.qc:401 qcsrc/server/w_seeker.qc:661 +#, c-format +msgid "%s was pummeled by %s" +msgstr "" + +#: qcsrc/server/w_hlac.qc:2 +msgid "Heavy Laser Assault Cannon" +msgstr "" + +#: qcsrc/server/w_hlac.qc:242 +#, c-format +msgid "%s was cut down by %s" +msgstr "" + +#: qcsrc/server/w_hook.qc:2 +msgid "Grappling Hook" +msgstr "" + +#: qcsrc/server/w_hook.qc:266 qcsrc/server/w_porto.qc:296 +#, c-format +msgid "%s did the impossible" +msgstr "" + +#: qcsrc/server/w_hook.qc:268 +#, c-format +msgid "%s has run into %s's gravity bomb" +msgstr "" + +#: qcsrc/server/w_laser.qc:2 +#, fuzzy +msgid "Laser" +msgstr "Master:" + +#: qcsrc/server/w_laser.qc:311 +#, c-format +msgid "%s lasered themself to hell" +msgstr "" + +#: qcsrc/server/w_laser.qc:315 +#, c-format +msgid "%s was cut in half by %s's gauntlet" +msgstr "" + +#: qcsrc/server/w_laser.qc:317 +#, c-format +msgid "%s was lasered to death by %s" +msgstr "" + +#: qcsrc/server/w_minelayer.qc:2 +#, fuzzy +msgid "Mine Layer" +msgstr "En Spelare" + +#: qcsrc/server/w_minelayer.qc:523 qcsrc/server/w_rocketlauncher.qc:501 +#, c-format +msgid "%s exploded" +msgstr "" + +#: qcsrc/server/w_minelayer.qc:527 +#, c-format +msgid "%s got too close to %s's mine" +msgstr "" + +#: qcsrc/server/w_minelayer.qc:529 +#, c-format +msgid "%s almost dodged %s's mine" +msgstr "" + +#: qcsrc/server/w_minelayer.qc:531 +#, c-format +msgid "%s stepped on %s's mine" +msgstr "" + +#: qcsrc/server/w_minstanex.qc:2 +msgid "MinstaNex" +msgstr "" + +#: qcsrc/server/w_minstanex.qc:293 qcsrc/server/w_nex.qc:253 +#: qcsrc/server/w_shotgun.qc:215 qcsrc/server/w_uzi.qc:317 +#, c-format +msgid "%s is now thinking with portals" +msgstr "" + +#: qcsrc/server/w_minstanex.qc:295 qcsrc/server/w_nex.qc:255 +#, c-format +msgid "%s has been vaporized by %s" +msgstr "" + +#: qcsrc/server/w_nex.qc:2 +#, fuzzy +msgid "Nex" +msgstr "Nexboll" + +#: qcsrc/server/w_porto.qc:2 +msgid "Port-O-Launch" +msgstr "" + +#: qcsrc/server/w_porto.qc:298 +#, c-format +msgid "%s felt %s doing the impossible to him" +msgstr "" + +#: qcsrc/server/w_rifle.qc:2 +msgid "Rifle" +msgstr "" + +#: qcsrc/server/w_rifle.qc:233 +#, c-format +msgid "%s shot themself automatically" +msgstr "" + +#: qcsrc/server/w_rifle.qc:235 +#, c-format +msgid "%s sniped themself somehow" +msgstr "" + +#: qcsrc/server/w_rifle.qc:242 +#, c-format +msgid "%s failed to hide from %s's bullet hail" +msgstr "" + +#: qcsrc/server/w_rifle.qc:244 +#, c-format +msgid "%s died in %s's bullet hail" +msgstr "" + +#: qcsrc/server/w_rifle.qc:251 +#, c-format +msgid "%s failed to hide from %s's rifle" +msgstr "" + +#: qcsrc/server/w_rifle.qc:256 +#, c-format +msgid "%s got hit in the head by %s" +msgstr "" + +#: qcsrc/server/w_rifle.qc:258 qcsrc/server/w_uzi.qc:321 +#, c-format +msgid "%s was sniped by %s" +msgstr "" + +#: qcsrc/server/w_rocketlauncher.qc:2 +msgid "Rocket Launcher" +msgstr "" + +#: qcsrc/server/w_rocketlauncher.qc:505 +#, c-format +msgid "%s got too close to %s's rocket" +msgstr "" + +#: qcsrc/server/w_rocketlauncher.qc:507 +#, c-format +msgid "%s almost dodged %s's rocket" +msgstr "" + +#: qcsrc/server/w_rocketlauncher.qc:509 +#, c-format +msgid "%s ate %s's rocket" +msgstr "" + +#: qcsrc/server/w_seeker.qc:2 +msgid "T.A.G. Seeker" +msgstr "" + +#: qcsrc/server/w_seeker.qc:659 +#, c-format +msgid "%s was tagged by %s" +msgstr "" + +#: qcsrc/server/w_shotgun.qc:2 +#, fuzzy +msgid "Shotgun" +msgstr "Kort" + +#: qcsrc/server/w_shotgun.qc:219 +#, c-format +msgid "%2$s ^7slapped %1$s ^7around a bit with a large ^2shotgun" +msgstr "" + +#: qcsrc/server/w_shotgun.qc:221 +#, c-format +msgid "%s was gunned by %s" +msgstr "" + +#: qcsrc/server/w_tuba.qc:2 +#, fuzzy, c-format +msgid "@!#%'n Tuba" +msgstr "@!#%'n Tubakastning" + +#: qcsrc/server/w_tuba.qc:252 +#, c-format +msgid "%s hurt his own ears with the @!#%%'n Tuba" +msgstr "" + +#: qcsrc/server/w_tuba.qc:256 +#, c-format +msgid "%s died of %s's great playing on the @!#%%'n Tuba" +msgstr "" + +#: qcsrc/server/w_uzi.qc:2 +msgid "Machine Gun" +msgstr "" + +#: qcsrc/server/w_uzi.qc:323 +#, c-format +msgid "%s was riddled full of holes by %s" +msgstr "" diff --git a/menu.dat.uk.po b/menu.dat.uk.po new file mode 100644 index 0000000000..f7768ec8c9 --- /dev/null +++ b/menu.dat.uk.po @@ -0,0 +1,2895 @@ +# Xonotic Menu Ukrainian Translation. +# Copyright (C) 2011 Team Xonotic +# This file is distributed under the same license as the Xonotic package. +# Harmata <cigariscigar@gmail.com>, 2011. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 0.5\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-09-12 12:24+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Harmata <cigariscigar@gmail.com>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: uk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: qcsrc/common/mapinfo.qc:1092 qcsrc/menu/xonotic/skinlist.c:163 +#, c-format +msgid "%s: %s" +msgstr "%s: %s" + +#: qcsrc/menu/gamecommand.qc:47 +#, c-format +msgid "error: status is %d\n" +msgstr "помилка: статус %d\n" + +#: qcsrc/menu/gamecommand.qc:65 +msgid "Usage: menu_cmd command..., where possible commands are:\n" +msgstr "Використання: menu_cmd команда..., де можливі такі команди:\n" + +#: qcsrc/menu/gamecommand.qc:66 +msgid " sync - reloads all cvars on the current menu page\n" +msgstr " sync - перезавантажує усі cvars на поточній сторінці меню\n" + +#: qcsrc/menu/gamecommand.qc:67 +msgid " directmenu ITEM - select a menu item as main item\n" +msgstr " directmenu ITEM - обрати компонент меню як головний компонент\n" + +#: qcsrc/menu/gamecommand.qc:193 +msgid "error creating curl handle\n" +msgstr "помилка під час створення curl handle\n" + +#: qcsrc/menu/gamecommand.qc:239 +msgid "Invalid command. For a list of supported commands, try menu_cmd help.\n" +msgstr "" +"Невірна команда. Щоб побачити список доступних команд спробуйте menu_cmd " +"help.\n" + +#: qcsrc/menu/item/gecko.c:49 +msgid "Browser not initialized!" +msgstr "Браузер не ініціалізовано!" + +#: qcsrc/menu/item/label.c:63 +#, c-format +msgid "NOTE: label text %s too wide for label, condensed by factor %f\n" +msgstr "ПРИМІТКА: текст ярлика %s надто широкий для нього, зменшений на %f\n" + +#: qcsrc/menu/item/listbox.c:300 +#, c-format +msgid "Item %d" +msgstr "Предмет %d" + +#: qcsrc/menu/item/slider.c:64 +#, c-format +msgid "%d (%s)" +msgstr "%d (%s)" + +#: qcsrc/menu/item/textslider.c:29 qcsrc/menu/item/textslider.c:31 +msgid "custom" +msgstr "особливо" + +#: qcsrc/menu/menu.qc:29 +#, c-format +msgid "^4MQC Build information: ^1%s\n" +msgstr "^4Відомості про збірку MQC: ^1%s\n" + +#: qcsrc/menu/xonotic/campaign.c:284 +#: qcsrc/menu/xonotic/dialog_singleplayer.c:123 +msgid "???" +msgstr "???" + +#: qcsrc/menu/xonotic/campaign.c:285 +#, c-format +msgid "Level %d: %s" +msgstr "Рівень %d: %s" + +#: qcsrc/menu/xonotic/cvarlist.c:85 +msgid "will be saved to config.cfg" +msgstr "буде збережено в config.cfg" + +#: qcsrc/menu/xonotic/cvarlist.c:87 +msgid "will not be saved" +msgstr "не буде збережено" + +#: qcsrc/menu/xonotic/cvarlist.c:89 +msgid "private" +msgstr "приватно" + +#: qcsrc/menu/xonotic/cvarlist.c:91 +msgid "engine setting" +msgstr "налаштування рушія" + +#: qcsrc/menu/xonotic/cvarlist.c:93 +msgid "read only" +msgstr "тільки читання" + +#: qcsrc/menu/xonotic/dialog_credits.c:5 +msgid "Credits" +msgstr "Розробники" + +#: qcsrc/menu/xonotic/dialog_credits.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:269 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:41 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:57 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:61 +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:21 +msgid "OK" +msgstr "Гаразд" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:4 +msgid "Welcome" +msgstr "Вітаємо" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:33 +msgid "" +"Welcome to Xonotic, please select your language preference and enter your " +"player name to get started. You can change these options later through the " +"menu system." +msgstr "" +"Вітаємо у Xonotic! Будь ласка, для початку оберіть свою мову та вкажіть своє " +"ім'я. Ви зможете змінити їх через систему меню потім." + +#: qcsrc/menu/xonotic/dialog_firstrun.c:38 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:35 +msgid "Text language:" +msgstr "Мова тексту:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:47 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:40 +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:39 +msgid "Name:" +msgstr "Ім'я:" + +#: qcsrc/menu/xonotic/dialog_firstrun.c:69 +msgid "Save settings" +msgstr "Зберегти налаштування" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:4 +msgid "Ammo Panel" +msgstr "Панель боєзапасу" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:22 +msgid "Ammunition display:" +msgstr "Показ амуніції:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:25 +msgid "Show only current ammo type" +msgstr "Показувати тільки поточний тип боєприпасів" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:28 +msgid "Align icon:" +msgstr "Вирівнювання іконок:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:29 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:36 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:40 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:28 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:40 +msgid "Left" +msgstr "Ліворуч" + +#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:38 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:41 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:30 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:41 +msgid "Right" +msgstr "Праворуч" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:4 +msgid "Centerprint" +msgstr "Основні повідомлення" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:23 +msgid "Message duration:" +msgstr "Тривалість існування повідомлень:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:27 +msgid "Fade time:" +msgstr "Час зникнення:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:31 +msgid "Flip messages order" +msgstr "Поміняти місцями порядок повідомлень" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:33 +msgid "Text alignment:" +msgstr "Вирівнювання тексту:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:37 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:50 +msgid "Center" +msgstr "По центру" + +#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c:41 +msgid "Font scale:" +msgstr "Масштаб шрифту:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:4 +msgid "Chat Panel" +msgstr "Панель чату" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:22 +msgid "Chat entries:" +msgstr "Кількість записів:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:25 +msgid "Chat size:" +msgstr "Розмір чату:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:29 +msgid "Chat lifetime:" +msgstr "Тривалість чату:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_chat.c:33 +msgid "Chat beep sound" +msgstr "Звук чату:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:4 +msgid "Engine Info Panel" +msgstr "Панель інформації рушія" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:22 +msgid "Engine info:" +msgstr "Інформація про рушій:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c:25 +msgid "Use an averaging algorithm for fps" +msgstr "Використовувати усереднюючий алгоритм для кадрів за секунду" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:4 +msgid "Health/Armor Panel" +msgstr "Панель здоров'я та броні" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:22 +msgid "Enable status bar" +msgstr "Увімкнути смугу статусу" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:24 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:24 +msgid "Status bar alignment:" +msgstr "Вирівнювання смуги статусу:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:42 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:32 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:42 +msgid "Inward" +msgstr "Всередину" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:43 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:34 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:43 +msgid "Outward" +msgstr "Назовні" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:37 +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:37 +msgid "Icon alignment:" +msgstr "Вирівнювання іконок:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c:45 +msgid "Flip health and armor positions" +msgstr "Поміняти місцями позиції здоров'я та броні" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:4 +msgid "Info Messages Panel" +msgstr "Панель інформаційних повідомлень" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:22 +msgid "Info messages:" +msgstr "Інформаційні повідомлення:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c:25 +msgid "Flip align" +msgstr "Поміняти місцями вирівнювання" + +#: qcsrc/menu/xonotic/dialog_hudpanel_modicons.c:4 +msgid "Mod Icons Panel" +msgstr "Панель іконок модів" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:4 +msgid "Notification Panel" +msgstr "Панель сповіщень" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:22 +msgid "Notifications:" +msgstr "Сповіщення:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:25 +msgid "Also print notifications to the console" +msgstr "Також друкувати сповіщення до консолі" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:28 +msgid "Flip notify order" +msgstr "Поміняти місцями порядок сповіщень" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:31 +msgid "Entry lifetime:" +msgstr "Час існування запису:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_notification.c:35 +msgid "Entry fadetime:" +msgstr "Час зникнення запису:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:4 +msgid "Physics Panel" +msgstr "Панель фізики" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:22 +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:21 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:21 +msgid "Panel disabled" +msgstr "Панель вимкнута" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:23 +msgid "Panel enabled" +msgstr "Увімкнути панель" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:24 +msgid "Panel enabled even observing" +msgstr "Увімкнути панель під час спостерігання" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:25 +msgid "Panel enabled only in Race/CTS" +msgstr "Увімкнути панель тільки під час Гонки/CTS" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:31 +msgid "Status bar" +msgstr "Смуга статусу" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:48 +msgid "Left align" +msgstr "Вирівнювати ліворуч" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:34 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:52 +msgid "Right align" +msgstr "Вирівнювати праворуч" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:35 +msgid "Inward align" +msgstr "Вирівнювати всередину" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:36 +msgid "Outward align" +msgstr "Вирівнюванти назовні" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:40 +msgid "Flip speed/acceleration positions" +msgstr "Поміняти місцями позиції швидкості та акселерації" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:44 +msgid "Speed:" +msgstr "Швидкість:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:45 +msgid "Include vertical speed" +msgstr "Включаючи вертикальну швидкість" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:56 +msgid "Speed unit:" +msgstr "Одиниця швидкості:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:58 +msgid "qu/s" +msgstr "qu/с" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:59 +msgid "m/s" +msgstr "м/с" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:60 +msgid "km/h" +msgstr "км/с" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:61 +msgid "mph" +msgstr "милі" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:62 +msgid "knots" +msgstr "вузли" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:64 +msgid "Show" +msgstr "Показувати" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:67 +msgid "Top speed" +msgstr "Найвища швидкість" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:73 +msgid "Acceleration:" +msgstr "Прискорення:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_physics.c:74 +msgid "Include vertical acceleration" +msgstr "Включаючи вертикальне прискорення" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:4 +msgid "Powerups Panel" +msgstr "Панель підсилень" + +#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.c:45 +msgid "Flip strength and shield positions" +msgstr "Поміняти місцями позиції Сили та Щита" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:4 +msgid "Pressed Keys Panel" +msgstr "Панель натиснутих клавіш" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:22 +msgid "Panel enabled when spectating" +msgstr "Панель працює під час спостерігання" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:23 +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:23 +msgid "Panel always enabled" +msgstr "Панель завжди працює" + +#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c:30 +msgid "Forced aspect:" +msgstr "Примусовий аспект:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_racetimer.c:4 +msgid "Race Timer Panel" +msgstr "Панель таймера гонки" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:4 +msgid "Radar Panel" +msgstr "Панель радару" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:22 +msgid "Panel enabled in teamgames" +msgstr "Панель працюватиме у командних матчах" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:29 +msgid "Radar:" +msgstr "Радар:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:32 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:43 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:154 +#: qcsrc/menu/xonotic/util.qc:612 +msgid "Alpha:" +msgstr "Прозорість:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:36 +msgid "Rotation:" +msgstr "Обертання:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:38 +msgid "Forward" +msgstr "Вперед" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:39 +msgid "West" +msgstr "Захід" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:40 +msgid "South" +msgstr "Південь" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:41 +msgid "East" +msgstr "Схід" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:42 +msgid "North" +msgstr "Північ" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:46 +msgid "Scale:" +msgstr "Масштаб:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:50 +msgid "Zoom mode:" +msgstr "Спосіб зуму:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:52 +msgid "Zoomed in" +msgstr "Наближення" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:53 +msgid "Zoomed out" +msgstr "Віддалення" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:54 +msgid "Always zoomed" +msgstr "Завжди із зумом" + +#: qcsrc/menu/xonotic/dialog_hudpanel_radar.c:55 +msgid "Never zoomed" +msgstr "Ніколи із зумом" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:4 +msgid "Score Panel" +msgstr "Панель рахунку" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:22 +msgid "Score:" +msgstr "Рахунок:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:25 +msgid "Rankings:" +msgstr "Місця:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:26 +msgid "Off" +msgstr "Вимкнуто" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:27 +msgid "And me" +msgstr "І я" + +#: qcsrc/menu/xonotic/dialog_hudpanel_score.c:28 +msgid "Pure" +msgstr "Чистий" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:4 +msgid "Timer Panel" +msgstr "Панель таймеру" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:22 +msgid "Timer:" +msgstr "Таймер:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_timer.c:25 +msgid "Show elapsed time" +msgstr "Показувати час що минув" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:4 +msgid "Vote Panel" +msgstr "Панель голосування" + +#: qcsrc/menu/xonotic/dialog_hudpanel_vote.c:22 +msgid "Alpha after voting:" +msgstr "Прозорість після голосування:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:4 +msgid "Weapons Panel" +msgstr "Панель зброї" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:24 +msgid "Fade out after:" +msgstr "Зникати після:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:26 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:36 +msgid "Never" +msgstr "Ніколи" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:28 +#, c-format +msgid "%ds" +msgstr "%ds" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:32 +msgid "Fade effect:" +msgstr "Ефект зникнення:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:35 +msgid "EF^None" +msgstr "EF^Немає" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:36 +msgid "Slide" +msgstr "Ковзання" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:37 +msgid "Alpha" +msgstr "Прозорість" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:38 +msgid "EF^Both" +msgstr "EF^Ковзання та прозорість" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:42 +msgid "Weapon icons:" +msgstr "Іконки зброї:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:45 +msgid "Show only owned weapons" +msgstr "Показувати тільки зброю в наявності" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:48 +msgid "Show weapon ID as:" +msgstr "Ідентифікувати зброю за:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:49 +msgid "SHOWAS^None" +msgstr "SHOWAS^Вимкнуто" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:50 +msgid "Number" +msgstr "Номером" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:51 +msgid "Bind" +msgstr "Клавішею" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:54 +msgid "Show Accuracy" +msgstr "Показувати влучність" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:55 +msgid "Show Ammo" +msgstr "Показувати боєзапас" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:58 +msgid "Ammo bar color:" +msgstr "Колір смуги боєприпасів:" + +#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.c:64 +msgid "Ammo bar alpha:" +msgstr "Прозорість смуги боєприпасів:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:4 +msgid "Panel HUD Setup" +msgstr "Налаштування панелі HUD" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:21 +msgid "Panel background defaults:" +msgstr "Фон панелі за замовчуванням:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:23 qcsrc/menu/xonotic/util.qc:587 +msgid "Background:" +msgstr "Фон:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:25 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:37 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:52 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:91 qcsrc/menu/xonotic/util.qc:590 +#: qcsrc/menu/xonotic/util.qc:606 qcsrc/menu/xonotic/util.qc:623 +msgid "Disable" +msgstr "Вимкнути" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:30 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:77 qcsrc/menu/xonotic/util.qc:595 +msgid "Color:" +msgstr "Колір:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:35 qcsrc/menu/xonotic/util.qc:603 +msgid "Border size:" +msgstr "Розмір обвідки:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:50 +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:89 +msgid "Team color:" +msgstr "Колір команди:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:58 qcsrc/menu/xonotic/util.qc:629 +msgid "Test team color in configure mode" +msgstr "Протестувати колір команди у конфігураційному режимі" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:61 qcsrc/menu/xonotic/util.qc:632 +msgid "Padding:" +msgstr "Підкладка:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:68 +msgid "HUD Dock:" +msgstr "Док HUD:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:70 +msgid "DOCK^Disabled" +msgstr "DOCK^Вимкнуто" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:71 +msgid "DOCK^Small" +msgstr "DOCK^Маленький" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:72 +msgid "DOCK^Medium" +msgstr "DOCK^Середній" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:73 +msgid "DOCK^Large" +msgstr "DOCK^Великий" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:96 +msgid "Grid settings:" +msgstr "Налаштування решітки:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:99 +msgid "Snap panels to grid" +msgstr "Прікріпляти панелі до решітки" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:102 +msgid "Grid size:" +msgstr "Розмір решітки:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:103 +msgid "X:" +msgstr "X:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:109 +msgid "Y:" +msgstr "Y:" + +#: qcsrc/menu/xonotic/dialog_hudsetup_exit.c:117 +msgid "Exit setup" +msgstr "Вийти з налаштувань" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:4 +msgid "Multiplayer" +msgstr "Мультиплеєр" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:18 +msgid "Servers" +msgstr "Сервери" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:19 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:5 +msgid "Create" +msgstr "Створити" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:20 +msgid "Demos" +msgstr "Демо" + +#: qcsrc/menu/xonotic/dialog_multiplayer.c:21 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:5 +msgid "Player Setup" +msgstr "Гравець" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:34 +msgid "Game type:" +msgstr "Тип гри:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:46 +msgid "Match settings:" +msgstr "Налаштування матчу:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:49 +msgid "Time limit:" +msgstr "Ліміт часу:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:53 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:61 +msgid "Use map specified default" +msgstr "Використати налаштування мапи" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:56 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:155 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:156 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:157 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:161 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:162 +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:163 +msgid "Point limit:" +msgstr "Ліміт очок:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:64 +msgid "Player slots:" +msgstr "Місць для гравців:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:67 +msgid "Number of bots:" +msgstr "Кількість ботів:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:71 +msgid "Bot skill:" +msgstr "Майстерність ботів:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:74 +msgid "Botlike" +msgstr "Ботоподібний" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:75 +msgid "Beginner" +msgstr "Початківець" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:76 +msgid "You will win" +msgstr "Ви переможете" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:77 +msgid "You can win" +msgstr "Ви можете перемогти" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:78 +msgid "You might win" +msgstr "Ви переможете... можливо" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:79 +msgid "Advanced" +msgstr "Удосконалений" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:80 +msgid "Expert" +msgstr "Експерт" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:81 +msgid "Pro" +msgstr "Професіонал" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:82 +msgid "Assassin" +msgstr "Убивця" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:83 +msgid "Unhuman" +msgstr "Нелюд" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:84 +msgid "Godlike" +msgstr "Богоподібний" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:88 +msgid "Mutators..." +msgstr "Мутатори..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:97 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:57 +msgid "Advanced settings..." +msgstr "Додадкові налаштування:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:104 +msgid "Map list:" +msgstr "Список мап:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:110 +msgid "Select all" +msgstr "Вибрати все" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:113 +msgid "Select none" +msgstr "Вибрати нічого" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:119 +msgid "Start Multiplayer!" +msgstr "Почати Мультиплеєр!" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:154 +msgid "Capture limit:" +msgstr "Ліміт захоплень:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:158 +msgid "Lives:" +msgstr "Життів:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:159 +msgid "Laps:" +msgstr "Кругів:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:160 +msgid "Goals:" +msgstr "Голів:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create.c:164 +msgid "Frag limit:" +msgstr "Ліміт фрагів:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:6 +msgid "Advanced server settings" +msgstr "Додаткові налаштування сервера" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:25 +msgid "Game settings:" +msgstr "Налаштування гри:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:28 +msgid "Allow spectating" +msgstr "Дозволити спостерігання" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:31 +msgid "Spawn shield:" +msgstr "Створювати Щит:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:36 +msgid "Game speed:" +msgstr "Швидкість гри:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:40 +msgid "Teamplay settings:" +msgstr "Налаштування командної гри:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:43 +msgid "Friendly fire scale:" +msgstr "Масштаб дружньої шкоди:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:47 +msgid "Virtual friendly fire (effect only)" +msgstr "Псевдо-дружня шкода (тільки ефект)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:50 +msgid "Friendly fire penalty:" +msgstr "Штраф за дружню шкоду:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:54 +msgid "Virtual penalty (effect only)" +msgstr "Псевдо-штраф (тільки ефект)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:57 +msgid "Teams:" +msgstr "Команди:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:66 +msgid "Map voting:" +msgstr "Голосування щодо мап:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:68 +msgid "No voting" +msgstr "Без голосування" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:69 +msgid "2 choices" +msgstr "2 вибори" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:70 +msgid "3 choices" +msgstr "3 вибори" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:71 +msgid "4 choices" +msgstr "4 вибори" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:72 +msgid "5 choices" +msgstr "5 виборів" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:73 +msgid "6 choices" +msgstr "6 виборів" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:74 +msgid "7 choices" +msgstr "7 виборів" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:75 +msgid "8 choices" +msgstr "8 виборів" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:76 +msgid "9 choices" +msgstr "9 виборів" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c:79 +msgid "Simple majority wins vcall" +msgstr "Проста більшість перемагає в голосуванні" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:5 +msgid "Map Information" +msgstr "Інформація про мапу" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "Full item placement" +msgstr "Вся зброя" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:49 +msgid "MinstaGib only" +msgstr "Тільки МінстаДжиб" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:78 +msgid "Title:" +msgstr "Назва:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:84 +msgid "Author:" +msgstr "Автор:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:90 +msgid "Features:" +msgstr "Деталі:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:95 +msgid "Game types:" +msgstr "Типи гри:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:118 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:314 +msgid "Close" +msgstr "Закрити" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c:121 +msgid "MAP^Play" +msgstr "MAP^Грати" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:7 +msgid "Mutators" +msgstr "Мутатори" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:33 +msgid "All Weapons Arena" +msgstr "Арена зі всією зброєю" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:35 +msgid "Most Weapons Arena" +msgstr "Арена з більшістю зброї" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:56 +#, c-format +msgid "%s Arena" +msgstr "%s Арена" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:68 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:167 +msgid "Dodging" +msgstr "Ухилення" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:70 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:250 +msgid "MinstaGib" +msgstr "МінстаДжиб" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:253 +msgid "NIX" +msgstr "Нікс" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:74 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:205 +msgid "Rocket Flying" +msgstr "Політ за допомогою ракет" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:78 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:264 +msgid "No start weapons" +msgstr "Без стартової зброї" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:80 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:189 +msgid "Low gravity" +msgstr "Низька гравітація" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:82 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:170 +msgid "Cloaked" +msgstr "Маскування" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:84 +msgid "Hook" +msgstr "Гак" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:86 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:173 +msgid "Midair" +msgstr "Мід-ейр" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:88 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:176 +msgid "Vampire" +msgstr "Вампір" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:90 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:208 +msgid "Piñata" +msgstr "Піньята" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:92 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:211 +msgid "Weapons stay" +msgstr "Зброя залишається" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:94 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:180 +msgid "Blood loss" +msgstr "Втрата крові" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:96 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:202 +msgid "Jet pack" +msgstr "Реактивний ранець" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:98 +msgid "MUT^None" +msgstr "MUT^Жодного" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:164 +msgid "Gameplay mutators:" +msgstr "Мутатори ігрового процесу:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:196 +msgid "Weapon & item mutators:" +msgstr "Мутатори зброї та предметів:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:199 +msgid "Grappling hook" +msgstr "Гак" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:215 +msgid "Weapon arenas:" +msgstr "Арени:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:218 +msgid "Regular (no arena)" +msgstr "Звичайно (не арена)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:239 +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:256 +msgid "with laser" +msgstr "з лазером" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:247 +msgid "Special arenas:" +msgstr "Спеціальні арени:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c:260 +msgid "Most weapons" +msgstr "Більшість зброї" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:4 +msgid "Demo" +msgstr "Демо" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:28 +msgid "Record demos while playing" +msgstr "Записувати демо під час гри" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:32 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:28 +msgid "Filter:" +msgstr "Фільтр:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:33 +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:29 +#: qcsrc/menu/xonotic/dialog_settings_input.c:41 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:24 +msgid "Clear" +msgstr "Очистити" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:43 +msgid "Timedemo" +msgstr "Тест продуктивності" + +#: qcsrc/menu/xonotic/dialog_multiplayer_demo.c:46 +msgid "DEMO^Play" +msgstr "DEMO^Переглянути" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:4 +msgid "Join" +msgstr "Приєднатися" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:36 +msgid "SRVS^Empty" +msgstr "SRVS^Порожні" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:40 +msgid "SRVS^Full" +msgstr "SRVS^Повні" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:44 +msgid "Pause" +msgstr "Пауза" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:56 +msgid "Address:" +msgstr "Адреса:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:67 +msgid "Info..." +msgstr "Відомості..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_join.c:72 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:317 +msgid "Join!" +msgstr "Приєднатися!" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:5 +msgid "Server Information" +msgstr "Інформація сервера" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:115 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:116 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:183 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:189 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:199 +msgid "N/A" +msgstr "Н/Д" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:158 +#, c-format +msgid "%d/%d, %d free player slots" +msgstr "%d/%d, %d вільних місць для гравців" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +#, c-format +msgid "%d modified settings" +msgstr "%d змінених налаштувань" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:172 +msgid "Official settings" +msgstr "Офіційні налаштування" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:197 +msgid "N/A (can't connect)" +msgstr "Н/Д (неможливо з'єднатися)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:205 +msgid "not supported (can't connect)" +msgstr "не підтримується (неможливо з'єднатися)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:207 +msgid "not supported (won't encrypt)" +msgstr "не підтримується (не буде шифрувати)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:211 +msgid "supported (will encrypt)" +msgstr "підтримується (буде шифрувати)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:213 +msgid "supported (won't encrypt)" +msgstr "підтримується (не буде шифрувати)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:217 +msgid "requested (will encrypt)" +msgstr "запитано (не буде шифрувати)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:219 +msgid "requested (won't encrypt)" +msgstr "запитано (буде шифрувати)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:223 +msgid "required (can't connect)" +msgstr "обов'язкове (неможливо з'єднатися)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:225 +msgid "required (will encrypt)" +msgstr "обов'язкове (буде шифрувати)" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:246 +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:269 +msgid "Players:" +msgstr "Гравці:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:254 +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:38 +msgid "Type:" +msgstr "Тип:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:259 +msgid "Map:" +msgstr "Мапа:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:264 +msgid "Gameplay:" +msgstr "Ігровий процес:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:274 +msgid "Bots:" +msgstr "Боти:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:279 +msgid "Mod:" +msgstr "Мод:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:284 +msgid "Version:" +msgstr "Версія:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:289 +msgid "Ping:" +msgstr "Пінг:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:295 +msgid "CA:" +msgstr "CA:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:301 +msgid "Key:" +msgstr "Ключ:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c:307 +msgid "Encryption:" +msgstr "Кодування:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:63 +msgid "Model:" +msgstr "Модель:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:88 +msgid "Field of view:" +msgstr "Поле зору:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:92 +msgid "View bobbing:" +msgstr "Гойдання поля зору:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:96 +msgid "Zoom factor:" +msgstr "Сила зуму:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:100 +msgid "Zoom speed:" +msgstr "Швидкість зуму:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:103 +msgid "Weapon settings..." +msgstr "Налаштування зброї..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:110 +msgid "Crosshair:" +msgstr "Приціл:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:111 +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:139 +msgid "Per weapon" +msgstr "Для кожної зброї" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:130 +msgid "Crosshair size:" +msgstr "Розмір прицілу:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:134 +msgid "Crosshair alpha:" +msgstr "Прозорість прицілу:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:138 +msgid "Crosshair color:" +msgstr "Колір прицілу:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:140 +msgid "By health" +msgstr "Залежно від здоров'я" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:143 +msgid "Custom" +msgstr "Вибрати" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:148 +msgid "Enable center dot" +msgstr "Увімкнути центральну крапку" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:151 +msgid "Size:" +msgstr "Розмір:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:158 +msgid "Hit test:" +msgstr "Тест на влучання:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:159 +msgid "HTST^None" +msgstr "HTST^Жодного" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:160 +msgid "TrueAim" +msgstr "TrueAim" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:161 +msgid "Enemies" +msgstr "Вороги" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:164 +msgid "Waypoints setup..." +msgstr "Налаштування дороговказів..." + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:169 +msgid "Enter HUD editor" +msgstr "Редактор HUD" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:174 +msgid "Force models:" +msgstr "Примусово використовувати одну модель:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:175 +msgid "MDL^None" +msgstr "MDL^Жодну" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:176 +msgid "MDL^Custom" +msgstr "MDL^Особливу" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:177 +msgid "MDL^All" +msgstr "MDL^Всі" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:180 +msgid "Disable gore effects" +msgstr "Вимкнути криваві ефекти" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:182 +msgid "Gibs:" +msgstr "Шматки тіл:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:184 +msgid "GIBS^None" +msgstr "GIBS^Вимкнуто" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:185 +msgid "GIBS^Few" +msgstr "GIBS^Мало" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:186 +msgid "GIBS^Many" +msgstr "GIBS^Більше" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:187 +msgid "GIBS^Lots" +msgstr "GIBS^Багато" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:191 +msgid "Damage splash:" +msgstr "Червоний сплеск від шкоди:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c:195 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:173 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:194 +#: qcsrc/menu/xonotic/dialog_settings_input.c:74 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:30 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:41 +#: qcsrc/menu/xonotic/dialog_settings_video.c:109 +msgid "Apply immediately" +msgstr "Вжити негайно" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:5 +msgid "Waypoints" +msgstr "Дороговкази" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:23 +msgid "Show base waypoints" +msgstr "Показувати основні дороговкази" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:25 +msgid "Waypoint scale:" +msgstr "Розмір дороговказів:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:29 +msgid "Waypoint alpha:" +msgstr "Прозорість дороговказів:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:34 +msgid "Show names:" +msgstr "Показувати імена:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:37 +msgid "Teammates" +msgstr "Гравців команди" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c:38 +msgid "All players" +msgstr "Всіх гравців" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:6 +msgid "Weapon settings" +msgstr "Налаштування зброї" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:29 +msgid "Weapon priority list:" +msgstr "Список пріоритетів зброї:" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:34 +msgid "Up" +msgstr "Нагору" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:37 +msgid "Down" +msgstr "Вниз" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:41 +msgid "Use priority list for weapon cycling" +msgstr "Використовувати список приоритетів для прокрутки зброї" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:43 +msgid "Auto switch weapons on pickup" +msgstr "Автоматично перемикатись на підняту зброю" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:45 +msgid "Draw 1st person weapon model" +msgstr "Показувати модель зброї у першій особі" + +#: qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c:55 +msgid "Flip view horizontally" +msgstr "Поміняти місцями вид горизонтально" + +#: qcsrc/menu/xonotic/dialog_news.c:4 +msgid "News" +msgstr "Новини" + +#: qcsrc/menu/xonotic/dialog_news.c:18 +msgid "http://www.xonotic.org/team/blog/" +msgstr "http://www.xonotic.org/team/blog/" + +#: qcsrc/menu/xonotic/dialog_quit.c:4 +msgid "Quit" +msgstr "Вийти" + +#: qcsrc/menu/xonotic/dialog_quit.c:17 +msgid "Are you sure you want to quit?" +msgstr "Ви дійсно хочете вийти?" + +#: qcsrc/menu/xonotic/dialog_quit.c:20 +msgid "Yes" +msgstr "Так" + +#: qcsrc/menu/xonotic/dialog_quit.c:21 +msgid "No" +msgstr "Ні" + +#: qcsrc/menu/xonotic/dialog_settings.c:4 +msgid "Settings" +msgstr "Налаштування" + +#: qcsrc/menu/xonotic/dialog_settings.c:18 +#: qcsrc/menu/xonotic/dialog_settings_input.c:4 +msgid "Input" +msgstr "Керування" + +#: qcsrc/menu/xonotic/dialog_settings.c:19 +#: qcsrc/menu/xonotic/dialog_settings_video.c:4 +msgid "Video" +msgstr "Відео" + +#: qcsrc/menu/xonotic/dialog_settings.c:20 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:4 +msgid "Effects" +msgstr "Ефекти" + +#: qcsrc/menu/xonotic/dialog_settings.c:21 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:4 +msgid "Audio" +msgstr "Звук" + +#: qcsrc/menu/xonotic/dialog_settings.c:22 +#: qcsrc/menu/xonotic/dialog_settings_network.c:4 +msgid "Network" +msgstr "Мережа" + +#: qcsrc/menu/xonotic/dialog_settings.c:23 +#: qcsrc/menu/xonotic/dialog_settings_misc.c:4 +msgid "Misc" +msgstr "Різне" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:27 +msgid "Master:" +msgstr "Гучність:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:33 +msgid "Music:" +msgstr "Музика:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:41 +msgid "VOL^Ambient:" +msgstr "VOL^Навколишні звуки:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:48 +msgid "Info:" +msgstr "Інформація:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:55 +msgid "Items:" +msgstr "Предмети:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:62 +msgid "Pain:" +msgstr "Біль:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:69 +msgid "Player:" +msgstr "Гравці:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:76 +msgid "Shots:" +msgstr "Постріли:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:83 +msgid "Voice:" +msgstr "Голоси:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:91 +msgid "Weapons:" +msgstr "Зброя:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:98 +#: qcsrc/menu/xonotic/dialog_settings_audio.c:156 +msgid "Frequency:" +msgstr "Частота:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:100 +msgid "8 kHz" +msgstr "8 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:101 +msgid "11.025 kHz" +msgstr "11.025 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:102 +msgid "16 kHz" +msgstr "16 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:103 +msgid "22.05 kHz" +msgstr "22.05 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:104 +msgid "24 kHz" +msgstr "24 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:105 +msgid "32 kHz" +msgstr "32 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:106 +msgid "44.1 kHz" +msgstr "44.1 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:107 +msgid "48 kHz" +msgstr "48 kHz" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:110 +msgid "Channels:" +msgstr "Канали:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:112 +msgid "Mono" +msgstr "Моно" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:113 +msgid "Stereo" +msgstr "Стерео" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:114 +msgid "2.1" +msgstr "2.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:115 +msgid "4" +msgstr "4" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:116 +msgid "5" +msgstr "5" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:117 +msgid "5.1" +msgstr "5.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:118 +msgid "6.1" +msgstr "6.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:119 +msgid "7.1" +msgstr "7.1" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:123 +msgid "Swap Stereo" +msgstr "Інвертувати стерео" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:127 +msgid "Headphone friendly mode" +msgstr "Дружній режим для навушників" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:131 +msgid "Spatial voices:" +msgstr "Просторові звуки:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:132 +msgid "VOCS^None" +msgstr "VOCS^Жодних" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:133 +msgid "VOCS^Taunts" +msgstr "VOCS^Глузування" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:134 +msgid "VOCS^All" +msgstr "VOCS^Всі" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:137 +msgid "Taunt range:" +msgstr "Дальність глузувань:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:140 +msgid "RNG^Very short" +msgstr "RNG^Дуже коротка" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:141 +msgid "RNG^Short" +msgstr "RNG^Коротка" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:142 +msgid "RNG^Normal" +msgstr "RNG^Нормальна" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:143 +msgid "RNG^Long" +msgstr "RNG^Велика" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:144 +msgid "RNG^Full" +msgstr "RNG^Повна" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:151 +msgid "Automatic taunts" +msgstr "Автоматичні глузування" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:160 +msgid "Time warning:" +msgstr "Попередження про час:" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:162 +msgid "WRN^None" +msgstr "WRN^Жодного" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:163 +msgid "1 minute" +msgstr "1 хвилина" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:164 +msgid "5 minutes" +msgstr "5 хвилин" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:165 +msgid "WRN^Both" +msgstr "WRN^1 і 5 хвилин" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:168 +msgid "Hit indicator" +msgstr "Покажчик влучень" + +#: qcsrc/menu/xonotic/dialog_settings_audio.c:170 +msgid "Menu sounds" +msgstr "Звуки меню" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:38 +msgid "Quality preset:" +msgstr "Шаблон якості:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:41 +msgid "PRE^OMG!" +msgstr "PRE^О БОЖЕ!" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:42 +msgid "PRE^Low" +msgstr "PRE^Низька" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:43 +msgid "PRE^Medium" +msgstr "PRE^Середня" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:44 +msgid "PRE^Normal" +msgstr "PRE^Нормальна" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:45 +msgid "PRE^High" +msgstr "PRE^Висока" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:46 +msgid "PRE^Ultra" +msgstr "PRE^Ультра" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:48 +msgid "PRE^Ultimate" +msgstr "PRE^Максимальна" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:52 +msgid "Geometry detail:" +msgstr "Деталізація геометрії:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:54 +msgid "DET^Lowest" +msgstr "DET^Найнижча" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:55 +msgid "DET^Low" +msgstr "DET^Низька" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:56 +msgid "DET^Normal" +msgstr "DET^Нормальна" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:57 +msgid "DET^Good" +msgstr "DET^Добра" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:58 +msgid "DET^Best" +msgstr "DET^Найкраща" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:59 +msgid "DET^Insane" +msgstr "DET^Божевільна" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:62 +msgid "Antialiasing:" +msgstr "Антиаліасінг:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:64 +msgid "AA^Disabled" +msgstr "AA^Вимкнуто" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:65 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:103 +msgid "2x" +msgstr "2x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:66 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:104 +msgid "4x" +msgstr "4x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:70 +msgid "Texture resolution:" +msgstr "Роздільність текстур:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:73 +msgid "RES^Leet" +msgstr "RES^Елітна" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:74 +msgid "RES^Lowest" +msgstr "RES^Найнижча" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:75 +msgid "RES^Low" +msgstr "RES^Низька" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:76 +msgid "RES^Normal" +msgstr "RES^Нормальна" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:77 +msgid "RES^Good" +msgstr "RES^Добра" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:78 +msgid "RES^Best" +msgstr "RES^Найкраща" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:91 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:94 +msgid "Avoid lossy texture compression" +msgstr "Уникати компресії текстур із втратами" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:100 +msgid "Anisotropy:" +msgstr "Анізотропна фільтрація:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:102 +msgid "ANISO^Disabled" +msgstr "ANISO^Вимкнуто" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:105 +msgid "8x" +msgstr "8x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:106 +msgid "16x" +msgstr "16x" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:110 +msgid "Particle quality:" +msgstr "Якість часток:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:113 +msgid "Particle distance:" +msgstr "Відстань часток:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:117 +msgid "Decals" +msgstr "Сліди" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:118 +msgid "Decals on models" +msgstr "Сліди на моделях" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:122 +msgid "Distance:" +msgstr "Відстань:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:128 +msgid "Time:" +msgstr "Час:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:134 +msgid "Use lightmaps" +msgstr "Мапи освітлення" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:135 +msgid "Deluxe mapping" +msgstr "Текстурування deluxe" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:137 +msgid "Gloss" +msgstr "Блиск" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:140 +msgid "Offset mapping" +msgstr "Офсетне текстурування" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:142 +msgid "Relief mapping" +msgstr "Рельєфне текстурування" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:145 +msgid "Reflections:" +msgstr "Віддзеркалення:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:148 +msgid "Blurred" +msgstr "Розмиті" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:149 +msgid "REFL^Good" +msgstr "REFL^Добрі" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:150 +msgid "Sharp" +msgstr "Чіткі" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:155 +msgid "Show surfaces" +msgstr "Показувати поверхні" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:157 +msgid "No dynamic lighting" +msgstr "Без динамічного освітлення" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:159 +msgid "Flash blend approximation" +msgstr "Приблинзні розрахунки змішуванянн спалахів" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:161 +msgid "Realtime dynamic lighting" +msgstr "Динамаічне освітлення у реальному часі" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:162 +#: qcsrc/menu/xonotic/dialog_settings_effects.c:166 +msgid "Shadows" +msgstr "Тіні" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:165 +msgid "Realtime world lighting" +msgstr "Освітлення світу у реальному часі" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:170 +msgid "Use normal maps" +msgstr "Використовувати карти нормалів" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:172 +msgid "Soft shadows" +msgstr "М'які тіні" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:175 +msgid "Coronas" +msgstr "Корони" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:176 +msgid "Use Occlusion Queries" +msgstr "Використовувати Occlusion Queries" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:178 +msgid "Bloom" +msgstr "Ефект bloom" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:180 +msgid "High Dynamic Range (HDR)" +msgstr "High Dynamic Range (HDR)" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:184 +msgid "Motion blur:" +msgstr "Ефект motion blur:" + +#: qcsrc/menu/xonotic/dialog_settings_effects.c:189 +msgid "Blur and sharpen postprocessing" +msgstr "Післяобробка" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:26 +msgid "Key bindings:" +msgstr "Клавіши керування:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:31 +msgid "Change key..." +msgstr "Змінити клавішу..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:35 +msgid "Edit..." +msgstr "Редагувати..." + +#: qcsrc/menu/xonotic/dialog_settings_input.c:46 +msgid "Sensitivity:" +msgstr "Чутливість:" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:51 +msgid "UI mouse speed:" +msgstr "Швидкість миші в інтерфейсі" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:55 +msgid "Mouse filter" +msgstr "Фільтр миші" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:57 +msgid "Invert mouse" +msgstr "Інвертувати мишу" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:60 +#: qcsrc/menu/xonotic/dialog_settings_input.c:62 +msgid "Use joystick input" +msgstr "Використовувати джойстик" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:65 +#: qcsrc/menu/xonotic/dialog_settings_input.c:67 +msgid "Turn off OS mouse acceleration" +msgstr "Вимкнути прискорення миші операційною системою" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:69 +msgid "\"enter console\" also closes" +msgstr "\"увійти в консоль\" також закриває консоль" + +#: qcsrc/menu/xonotic/dialog_settings_input.c:72 +msgid "Holding jump key keeps jumping" +msgstr "Утримування клавіши стрибка продовжує стрибання" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:5 +msgid "User defined key bind" +msgstr "Клавіші визначені користувачем" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:42 +msgid "Command when pressed:" +msgstr "Команда коли натиснута:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:45 +msgid "Command when released:" +msgstr "Команда коли відпущена:" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:48 +msgid "Save" +msgstr "Зберегти" + +#: qcsrc/menu/xonotic/dialog_settings_input_userbind.c:51 +msgid "Cancel" +msgstr "Відміна" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:26 +msgid "Menu skins:" +msgstr "Вигляд меню:" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:47 +msgid "Show current time" +msgstr "Показувати поточний час" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:49 +msgid "Show current date" +msgstr "Показувати поточну дату" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:51 +msgid "Show frames per second" +msgstr "Показувати кількість кадрів в секунду" + +#: qcsrc/menu/xonotic/dialog_settings_misc.c:53 +msgid "Minimize input latency" +msgstr "Зменшувати затримку вводу" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:5 +msgid "Advanced settings" +msgstr "Додаткові налаштування" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:23 +msgid "Cvar filter:" +msgstr "Фільтр cvar:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:34 +msgid "Setting:" +msgstr "Налаштування:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:42 +msgid "Value:" +msgstr "Значення:" + +#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.c:56 +msgid "Description:" +msgstr "Опис:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:26 +msgid "Client-side movement prediction" +msgstr "Передбачення руху зі сторони клієнта" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:30 +msgid "Show netgraph" +msgstr "Показувати графік мережі" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:33 +msgid "Network speed:" +msgstr "Швидкість мережі:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:35 +msgid "56k" +msgstr "56k" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:36 +msgid "ISDN" +msgstr "ISDN" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:37 +msgid "Slow ADSL" +msgstr "Повільний ADSL" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:38 +msgid "Fast ADSL" +msgstr "Швидкій ADSL" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:39 +msgid "Broadband" +msgstr "Широкополосний доступ" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:42 +msgid "Input packets/s:" +msgstr "Вхідні пакети:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:46 +msgid "HTTP downloads:" +msgstr "Завантаження через HTTP:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:49 +msgid "Downloads:" +msgstr "Завантажень:" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:53 +msgid "Speed (kB/s):" +msgstr "Швидкість (кб/с):" + +#: qcsrc/menu/xonotic/dialog_settings_network.c:57 +msgid "Client UDP port:" +msgstr "UDP порт клієнта:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:26 +msgid "Resolution:" +msgstr "Роздільність:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:29 +msgid "Font/UI size:" +msgstr "Розмір шрифту/інтерфейсу:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:31 +msgid "SZ^Unreadable" +msgstr "SZ^Нечитабельний" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:32 +msgid "SZ^Tiny" +msgstr "SZ^Дуже маленький" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:33 +msgid "SZ^Little" +msgstr "SZ^Маленький" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:34 +msgid "SZ^Small" +msgstr "SZ^Невеликий" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:35 +msgid "SZ^Medium" +msgstr "SZ^Середній" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:36 +msgid "SZ^Large" +msgstr "SZ^Великий" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:37 +msgid "SZ^Huge" +msgstr "SZ^Величезний" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:38 +msgid "SZ^Gigantic" +msgstr "SZ^Велетенський" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:39 +msgid "SZ^Colossal" +msgstr "SZ^Колосальний" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:42 +msgid "Color depth:" +msgstr "Глибина кольору:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:45 +msgid "Full screen" +msgstr "На повний екран" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:46 +msgid "Vertical Synchronization" +msgstr "Вертикальна синхронізація" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:49 +msgid "Use OpenGL 2.0 shaders (GLSL)" +msgstr "Використовувати шейдери OpenGL 2.0 (GLSL)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:52 +msgid "Use GLSL to handle color control" +msgstr "Використовувати GLSL для управління кольором" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:56 +msgid "Vertex Buffer Objects (VBOs)" +msgstr "Vertex Buffer Objects (VBOs)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:59 +msgid "VBO^Off" +msgstr "VBO^Вимкнуто" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:60 +msgid "Vertices, some Tris (compatible)" +msgstr "Вершини, деякі трикутники (сумісний)" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:63 +msgid "Vertices" +msgstr "Вершини" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:64 +msgid "Vertices and Triangles" +msgstr "Вершини та трикутники" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:67 +msgid "Depth first:" +msgstr "Глибина спершу:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:69 +msgid "DF^Disabled" +msgstr "DF^Вимкнуто" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:70 +msgid "DF^World" +msgstr "DF^Світ" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:71 +msgid "DF^All" +msgstr "DF^Все" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:75 +msgid "Disable multithreaded OpenGL" +msgstr "Вимкнути багатопотоковий OpenGL" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:77 +msgid "Wait for GPU to finish each frame" +msgstr "Чекати поки GPU закінчить кожний кадр" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:80 +msgid "Brightness:" +msgstr "Яскравість:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:83 +msgid "Contrast:" +msgstr "Контраст:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:86 +msgid "Gamma:" +msgstr "Гамма:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:91 +msgid "Contrast boost:" +msgstr "Підсилення контрасту:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:96 +msgid "Saturation:" +msgstr "Насиченість:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:102 +msgid "LIT^Ambient:" +msgstr "Навколишне освітлення:" + +#: qcsrc/menu/xonotic/dialog_settings_video.c:105 +msgid "Intensity:" +msgstr "Інтенсивність:" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:4 +msgid "Singleplayer" +msgstr "Одиночна гра" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:116 +msgid "Instant action! (random map with bots)" +msgstr "Миттєвий бій! (випадкова мапа з ботами)" + +#: qcsrc/menu/xonotic/dialog_singleplayer.c:137 +msgid "Start Singleplayer!" +msgstr "Почати Одиночну гру!" + +#: qcsrc/menu/xonotic/dialog_singleplayer_winner.c:4 +msgid "Winner" +msgstr "Переможець" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:5 +msgid "Team Selection" +msgstr "Вибір команди" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:41 +msgid "join 'best' team (auto-select)" +msgstr "обрати підхожу команду (автовибір)" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:45 +msgid "red" +msgstr "червона" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:46 +msgid "blue" +msgstr "синя" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:47 +msgid "yellow" +msgstr "жовта" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:48 +msgid "pink" +msgstr "рожева" + +#: qcsrc/menu/xonotic/dialog_teamselect.c:51 +msgid "spectate" +msgstr "спостерігати" + +#: qcsrc/menu/xonotic/mainwindow.c:35 qcsrc/menu/xonotic/mainwindow.c:38 +msgid "Do not press this button again!" +msgstr "Більше не натискайте цю клавішу!" + +#: qcsrc/menu/xonotic/maplist.c:278 +msgid "" +"Huh? Can't play this (m is NULL). Refiltering so this won't happen again.\n" +msgstr "" +"Шо? В це неможливо грати (m is NULL). Зроблю фільтрацію ще раз, щоб такого " +"більше не траплялось.\n" + +#: qcsrc/menu/xonotic/maplist.c:286 +#, c-format +msgid "%s's Xonotic Server" +msgstr "Сервер Xonotic від %s" + +#: qcsrc/menu/xonotic/maplist.c:291 +msgid "" +"Huh? Can't play this (invalid game type). Refiltering so this won't happen " +"again.\n" +msgstr "" +"Шо? В це неможливо грати (невірний режим гри). Зроблю фільтрацію ще раз, щоб " +"такого більше не траплялось.\n" + +#: qcsrc/menu/xonotic/playermodel.c:174 +msgid "<no model found>" +msgstr "<модель не знайдена>" + +#: qcsrc/menu/xonotic/serverlist.c:185 +msgid "Remove" +msgstr "Прибрати" + +#: qcsrc/menu/xonotic/serverlist.c:187 +msgid "Bookmark" +msgstr "Закладка" + +#: qcsrc/menu/xonotic/serverlist.c:527 +msgid "Ping" +msgstr "Пінг" + +#: qcsrc/menu/xonotic/serverlist.c:528 +msgid "Host name" +msgstr "Ім'я сервера" + +#: qcsrc/menu/xonotic/serverlist.c:529 +msgid "Map" +msgstr "Мапа" + +#: qcsrc/menu/xonotic/serverlist.c:530 +msgid "Type" +msgstr "Тип" + +#: qcsrc/menu/xonotic/serverlist.c:531 +msgid "Players" +msgstr "Гравці" + +#: qcsrc/menu/xonotic/skinlist.c:105 +msgid "<TITLE>" +msgstr "<Назва>" + +#: qcsrc/menu/xonotic/skinlist.c:106 +msgid "<AUTHOR>" +msgstr "<Автор>" + +#: qcsrc/menu/xonotic/slider_decibels.c:50 +msgid "VOL^OFF" +msgstr "VOL^Вимкнуто" + +#: qcsrc/menu/xonotic/slider_decibels.c:52 +msgid "VOL^MAX" +msgstr "VOL^Максимум" + +#: qcsrc/menu/xonotic/slider_decibels.c:53 +#, c-format +msgid "%s dB" +msgstr "%s дБ" + +#: qcsrc/menu/xonotic/slider_resolution.c:65 +#, c-format +msgid "%dx%d" +msgstr "%dx%d" + +#: qcsrc/menu/xonotic/util.qc:271 +#, c-format +msgid "Received HTTP request data for an invalid id %d.\n" +msgstr "Отримано дані запиту HTTP для невірного id %d.\n" + +#: qcsrc/menu/xonotic/util.qc:286 +#, c-format +msgid "error receiving update notification: status is %d\n" +msgstr "помилка під час отримання сповіщення про оновлення: статус %d\n" + +#: qcsrc/menu/xonotic/util.qc:291 +msgid "error: received HTML instead of an update notification\n" +msgstr "помилка: отримано HTML замість сповіщення про оновлення\n" + +#: qcsrc/menu/xonotic/util.qc:296 +msgid "error: received carriage returns from update notification server\n" +msgstr "" +"помилка: отримані символи повернення каретки від сервера сповіщення про " +"оновлення\n" + +#: qcsrc/menu/xonotic/util.qc:317 +#, c-format +msgid "" +"Update can be downloaded at:\n" +"%s\n" +msgstr "" +"Оновлення можливо завантажити тут:\n" +"%s\n" + +#: qcsrc/menu/xonotic/util.qc:340 +msgid "Autogenerating mapinfo for newly added maps..." +msgstr "Створення відомостей про нові мапи..." + +#: qcsrc/menu/xonotic/util.qc:370 +#, c-format +msgid "^1%s TEST BUILD" +msgstr "^1%s ТЕСТОВА ЗБІРКА" + +#: qcsrc/menu/xonotic/util.qc:428 +#, c-format +msgid "Update to %s now!" +msgstr "Негайно обновіть версію до %s !" + +#: qcsrc/menu/xonotic/util.qc:513 +msgid "" +"^1ERROR: Texture compression is required but not supported.\n" +"^1Expect visual problems.\n" +msgstr "" +"^1Помилка: Компресія текстур обов'язкова але не підтримується.\n" +"^1Очікуйте візуальних проблем.\n" + +#: qcsrc/menu/xonotic/util.qc:535 +msgid "Arena" +msgstr "Арена" + +#: qcsrc/menu/xonotic/util.qc:536 +msgid "Assault" +msgstr "Атака" + +#: qcsrc/menu/xonotic/util.qc:537 +msgid "Capture The Flag" +msgstr "Захоплення прапору" + +#: qcsrc/menu/xonotic/util.qc:538 +msgid "Clan Arena" +msgstr "Арена кланів" + +#: qcsrc/menu/xonotic/util.qc:539 +msgid "Deathmatch" +msgstr "Десматч" + +#: qcsrc/menu/xonotic/util.qc:540 +msgid "Domination" +msgstr "Панування" + +#: qcsrc/menu/xonotic/util.qc:541 +msgid "Freeze Tag" +msgstr "Морозко" + +#: qcsrc/menu/xonotic/util.qc:542 +msgid "Keepaway" +msgstr "Тримання осторонь" + +#: qcsrc/menu/xonotic/util.qc:543 +msgid "Key Hunt" +msgstr "Полювання за ключами" + +#: qcsrc/menu/xonotic/util.qc:544 +msgid "Last Man Standing" +msgstr "Останній виживший" + +#: qcsrc/menu/xonotic/util.qc:545 +msgid "Nexball" +msgstr "Нексбол" + +#: qcsrc/menu/xonotic/util.qc:546 +msgid "Onslaught" +msgstr "Штурм" + +#: qcsrc/menu/xonotic/util.qc:547 +msgid "Race" +msgstr "Гонка" + +#: qcsrc/menu/xonotic/util.qc:548 +msgid "Race CTS" +msgstr "Гонка CTS" + +#: qcsrc/menu/xonotic/util.qc:549 +msgid "Runematch" +msgstr "Рунний матч" + +#: qcsrc/menu/xonotic/util.qc:550 +msgid "Team Deathmatch" +msgstr "Командний десматч" + +#: qcsrc/menu/xonotic/util.qc:569 +#, c-format +msgid "@!#%'n Tuba Throwing" +msgstr "Кидання @!#%'ї Туби" + +#: qcsrc/menu/xonotic/util.qc:589 qcsrc/menu/xonotic/util.qc:605 +#: qcsrc/menu/xonotic/util.qc:614 qcsrc/menu/xonotic/util.qc:622 +#: qcsrc/menu/xonotic/util.qc:634 +msgid "Default" +msgstr "За замовчуванням" + +#: qcsrc/menu/xonotic/util.qc:600 +msgid "Use default" +msgstr "Використовувати за замовчуванням" + +#: qcsrc/menu/xonotic/util.qc:620 +msgid "Team Color:" +msgstr "Колір команди:" + +#: qcsrc/menu/xonotic/util.qh:47 +msgid "Enable panel" +msgstr "Увімкнути панель" + +#: qcsrc/server/w_crylink.qc:2 +msgid "Crylink" +msgstr "Крайлінк" + +#: qcsrc/server/w_crylink.qc:666 +#, c-format +msgid "%s succeeded at self-destructing themself with the Crylink" +msgstr "%s успішно самознищив себе за допомогою Крайлінка" + +#: qcsrc/server/w_crylink.qc:671 +#, c-format +msgid "%s could not hide from %s's Crylink" +msgstr "%s не зміг сховатися від Крайлінка %s's" + +#: qcsrc/server/w_crylink.qc:673 +#, c-format +msgid "%s was too close to %s's Crylink" +msgstr "%s був надто близько до Крайлінка %s's" + +#: qcsrc/server/w_crylink.qc:675 +#, c-format +msgid "%s took a close look at %s's Crylink" +msgstr "%s роздивився Крайлінк %s's з близька" + +#: qcsrc/server/w_electro.qc:2 +msgid "Electro" +msgstr "Електро" + +#: qcsrc/server/w_electro.qc:574 +#, c-format +msgid "%s could not remember where they put plasma" +msgstr "%s не зміг згадати куди вони поклали плазму" + +#: qcsrc/server/w_electro.qc:576 +#, c-format +msgid "%s played with plasma" +msgstr "%s догрався з плазмою" + +#: qcsrc/server/w_electro.qc:583 +#, c-format +msgid "%s just noticed %s's blue ball" +msgstr "%s тільк-но помітив блакитну кулю %s's" + +#: qcsrc/server/w_electro.qc:585 +#, c-format +msgid "%s got in touch with %s's blue ball" +msgstr "%s доторкнувся до блакитної кулі %s's" + +#: qcsrc/server/w_electro.qc:590 +#, c-format +msgid "%s felt the electrifying air of %s's combo" +msgstr "%s відчув наелектризоване повітря від комбо %s's" + +#: qcsrc/server/w_electro.qc:592 +#, c-format +msgid "%s got too close to %s's blue beam" +msgstr "%s опинився надто близько до блакитного проміння %s's" + +#: qcsrc/server/w_electro.qc:594 +#, c-format +msgid "%s was blasted by %s's blue beam" +msgstr "%s був знищений блакитним промінням %s's" + +#: qcsrc/server/w_fireball.qc:2 +msgid "Fireball" +msgstr "Метеор" + +#: qcsrc/server/w_fireball.qc:417 +#, c-format +msgid "%s forgot about some firemine" +msgstr "%s забув про вогняну міну" + +#: qcsrc/server/w_fireball.qc:419 qcsrc/server/w_hlac.qc:240 +#, c-format +msgid "%s should have used a smaller gun" +msgstr "%s треба було використати меншу гармату" + +#: qcsrc/server/w_fireball.qc:426 +#, c-format +msgid "%s tried to catch %s's firemine" +msgstr "%s спробував піймати вогняну міну %s's" + +#: qcsrc/server/w_fireball.qc:428 +#, c-format +msgid "%s fatefully ignored %s's firemine" +msgstr "%s фатально проґавив метеор %s's" + +#: qcsrc/server/w_fireball.qc:435 +#, c-format +msgid "%s could not hide from %s's fireball" +msgstr "%s не зміг сховатися від метеора %s's" + +#: qcsrc/server/w_fireball.qc:437 +#, c-format +msgid "%s saw the pretty lights of %s's fireball" +msgstr "%s побачив гарненькі вогники метеора %s's" + +#: qcsrc/server/w_fireball.qc:440 +#, c-format +msgid "%s got too close to %s's fireball" +msgstr "%s підійшов надто близько до метеора %s's" + +#: qcsrc/server/w_fireball.qc:442 +#, c-format +msgid "%s tasted %s's fireball" +msgstr "%s скуштував метеор %s's" + +#: qcsrc/server/w_grenadelauncher.qc:2 +msgid "Mortar" +msgstr "Мортира" + +#: qcsrc/server/w_grenadelauncher.qc:383 +#, c-format +msgid "%s tried out his own grenade" +msgstr "%s скуштував свою власну гранату" + +#: qcsrc/server/w_grenadelauncher.qc:385 +#, c-format +msgid "%s detonated" +msgstr "%s вибухнув" + +#: qcsrc/server/w_grenadelauncher.qc:391 +#, c-format +msgid "%s didn't see %s's grenade" +msgstr "%s не побачив гранату %s's" + +#: qcsrc/server/w_grenadelauncher.qc:393 +#, c-format +msgid "%s almost dodged %s's grenade" +msgstr "%s майже ухилився від гранати %s's" + +#: qcsrc/server/w_grenadelauncher.qc:395 +#, c-format +msgid "%s ate %s's grenade" +msgstr "%s з'їв гранату %s's" + +#: qcsrc/server/w_hagar.qc:2 +msgid "Hagar" +msgstr "Хейгар" + +#: qcsrc/server/w_hagar.qc:395 qcsrc/server/w_seeker.qc:655 +#, c-format +msgid "%s played with tiny rockets" +msgstr "%s догрався з маленькими ракетами" + +#: qcsrc/server/w_hagar.qc:399 +#, c-format +msgid "%s hoped %s's missiles wouldn't bounce" +msgstr "%s понадіявся що ракета %s's не відскочить" + +#: qcsrc/server/w_hagar.qc:401 qcsrc/server/w_seeker.qc:661 +#, c-format +msgid "%s was pummeled by %s" +msgstr "%s був віддубасений %s" + +#: qcsrc/server/w_hlac.qc:2 +msgid "Heavy Laser Assault Cannon" +msgstr "Важка Лазерна Штурмова Гармата" + +#: qcsrc/server/w_hlac.qc:242 +#, c-format +msgid "%s was cut down by %s" +msgstr "%s був підрізаний %s" + +#: qcsrc/server/w_hook.qc:2 +msgid "Grappling Hook" +msgstr "Гак" + +#: qcsrc/server/w_hook.qc:266 qcsrc/server/w_porto.qc:296 +#, c-format +msgid "%s did the impossible" +msgstr "%s зробив неможливе" + +#: qcsrc/server/w_hook.qc:268 +#, c-format +msgid "%s has run into %s's gravity bomb" +msgstr "%s вбіг у гравітаційну бомбу %s's" + +#: qcsrc/server/w_laser.qc:2 +msgid "Laser" +msgstr "Лазер" + +#: qcsrc/server/w_laser.qc:311 +#, c-format +msgid "%s lasered themself to hell" +msgstr "%s відправив себе лазером прямо в пекло" + +#: qcsrc/server/w_laser.qc:315 +#, c-format +msgid "%s was cut in half by %s's gauntlet" +msgstr "%s був розрізаний навпіл рукавицею %s's" + +#: qcsrc/server/w_laser.qc:317 +#, c-format +msgid "%s was lasered to death by %s" +msgstr "%s згорів від лазеру %s" + +#: qcsrc/server/w_minelayer.qc:2 +msgid "Mine Layer" +msgstr "Міноукладчик" + +#: qcsrc/server/w_minelayer.qc:523 qcsrc/server/w_rocketlauncher.qc:501 +#, c-format +msgid "%s exploded" +msgstr "%s вибухнув" + +#: qcsrc/server/w_minelayer.qc:527 +#, c-format +msgid "%s got too close to %s's mine" +msgstr "%s опинився надто близько до міни %s's" + +#: qcsrc/server/w_minelayer.qc:529 +#, c-format +msgid "%s almost dodged %s's mine" +msgstr "%s майже ухилився від міни %s's" + +#: qcsrc/server/w_minelayer.qc:531 +#, c-format +msgid "%s stepped on %s's mine" +msgstr "%s наступив на міну %s's" + +#: qcsrc/server/w_minstanex.qc:2 +msgid "MinstaNex" +msgstr "МінстаНекс" + +#: qcsrc/server/w_minstanex.qc:293 qcsrc/server/w_nex.qc:253 +#: qcsrc/server/w_shotgun.qc:215 qcsrc/server/w_uzi.qc:317 +#, c-format +msgid "%s is now thinking with portals" +msgstr "%s тепер думає з порталами у голові" + +#: qcsrc/server/w_minstanex.qc:295 qcsrc/server/w_nex.qc:255 +#, c-format +msgid "%s has been vaporized by %s" +msgstr "%s був випаровуваний %s" + +#: qcsrc/server/w_nex.qc:2 +msgid "Nex" +msgstr "Некс" + +#: qcsrc/server/w_porto.qc:2 +msgid "Port-O-Launch" +msgstr "Портал-О-Пуск" + +#: qcsrc/server/w_porto.qc:298 +#, c-format +msgid "%s felt %s doing the impossible to him" +msgstr "%s відчув як %s зробив з ним неможливе" + +#: qcsrc/server/w_rifle.qc:2 +msgid "Rifle" +msgstr "Гвинтівка" + +#: qcsrc/server/w_rifle.qc:233 +#, c-format +msgid "%s shot themself automatically" +msgstr "%s пристрелив себе несвідомо" + +#: qcsrc/server/w_rifle.qc:235 +#, c-format +msgid "%s sniped themself somehow" +msgstr "%s примудрився пристрелити себе" + +#: qcsrc/server/w_rifle.qc:242 +#, c-format +msgid "%s failed to hide from %s's bullet hail" +msgstr "%s не зміг сховатися від граду куль %s's" + +#: qcsrc/server/w_rifle.qc:244 +#, c-format +msgid "%s died in %s's bullet hail" +msgstr "%s помер у граді куль %s's" + +#: qcsrc/server/w_rifle.qc:251 +#, c-format +msgid "%s failed to hide from %s's rifle" +msgstr "%s не зміг сховатися від гвинтівки %s's" + +#: qcsrc/server/w_rifle.qc:256 +#, c-format +msgid "%s got hit in the head by %s" +msgstr "%s втратив голову від кулі %s" + +#: qcsrc/server/w_rifle.qc:258 qcsrc/server/w_uzi.qc:321 +#, c-format +msgid "%s was sniped by %s" +msgstr "%s був підстрелений %s" + +#: qcsrc/server/w_rocketlauncher.qc:2 +msgid "Rocket Launcher" +msgstr "Ракетна гармата" + +#: qcsrc/server/w_rocketlauncher.qc:505 +#, c-format +msgid "%s got too close to %s's rocket" +msgstr "%s опинився надто близько до ракети %s's" + +#: qcsrc/server/w_rocketlauncher.qc:507 +#, c-format +msgid "%s almost dodged %s's rocket" +msgstr "%s майже ухилився від ракети %s's" + +#: qcsrc/server/w_rocketlauncher.qc:509 +#, c-format +msgid "%s ate %s's rocket" +msgstr "%s з'їв ракету %s's" + +#: qcsrc/server/w_seeker.qc:2 +msgid "T.A.G. Seeker" +msgstr "Шукач T.A.G." + +#: qcsrc/server/w_seeker.qc:659 +#, c-format +msgid "%s was tagged by %s" +msgstr "%s був мічений %s" + +#: qcsrc/server/w_shotgun.qc:2 +msgid "Shotgun" +msgstr "Рушниця" + +#: qcsrc/server/w_shotgun.qc:219 +#, c-format +msgid "%2$s ^7slapped %1$s ^7around a bit with a large ^2shotgun" +msgstr "%2$s ^7прибив %1$s ^7великою ^2рушницею" + +#: qcsrc/server/w_shotgun.qc:221 +#, c-format +msgid "%s was gunned by %s" +msgstr "%s був пристрелений %s" + +#: qcsrc/server/w_tuba.qc:2 +#, c-format +msgid "@!#%'n Tuba" +msgstr "@!#%'а Туба" + +#: qcsrc/server/w_tuba.qc:252 +#, c-format +msgid "%s hurt his own ears with the @!#%%'n Tuba" +msgstr "%s шкодить своїм вухам власною @!#%%'ю Тубою" + +#: qcsrc/server/w_tuba.qc:256 +#, c-format +msgid "%s died of %s's great playing on the @!#%%'n Tuba" +msgstr "%s помер від чудової гри %s's на @!#%%'й Тубі" + +#: qcsrc/server/w_uzi.qc:2 +msgid "Machine Gun" +msgstr "Автомат" + +#: qcsrc/server/w_uzi.qc:323 +#, c-format +msgid "%s was riddled full of holes by %s" +msgstr "%s виглядає як решето завдяки %s" + +#~ msgid "Pinata" +#~ msgstr "Піньята" diff --git a/models/casing_bronze.iqm b/models/casing_bronze.iqm new file mode 100644 index 0000000000..e48e20a806 Binary files /dev/null and b/models/casing_bronze.iqm differ diff --git a/models/casing_bronze.mdl b/models/casing_bronze.mdl deleted file mode 100644 index 54cb526e16..0000000000 Binary files a/models/casing_bronze.mdl and /dev/null differ diff --git a/models/casing_bronze.tga b/models/casing_bronze.tga new file mode 100644 index 0000000000..af11786f28 Binary files /dev/null and b/models/casing_bronze.tga differ diff --git a/models/casing_bronze_gloss.tga b/models/casing_bronze_gloss.tga new file mode 100644 index 0000000000..9c06707bec Binary files /dev/null and b/models/casing_bronze_gloss.tga differ diff --git a/models/casing_bronze_norm.tga b/models/casing_bronze_norm.tga new file mode 100644 index 0000000000..77d85bf626 Binary files /dev/null and b/models/casing_bronze_norm.tga differ diff --git a/models/casing_bronze_reflect.tga b/models/casing_bronze_reflect.tga new file mode 100644 index 0000000000..9c06707bec Binary files /dev/null and b/models/casing_bronze_reflect.tga differ diff --git a/models/domination/dom_blue.md3 b/models/domination/dom_blue.md3 index 8fd6b4fc09..6429f48948 100644 Binary files a/models/domination/dom_blue.md3 and b/models/domination/dom_blue.md3 differ diff --git a/models/domination/dom_pink.md3 b/models/domination/dom_pink.md3 index d8a9579cdb..7aa01bf395 100644 Binary files a/models/domination/dom_pink.md3 and b/models/domination/dom_pink.md3 differ diff --git a/models/domination/dom_red.md3 b/models/domination/dom_red.md3 index cb68ce4051..332b0f2395 100644 Binary files a/models/domination/dom_red.md3 and b/models/domination/dom_red.md3 differ diff --git a/models/domination/dom_unclaimed.md3 b/models/domination/dom_unclaimed.md3 index efbcf9cf74..be5aaa9571 100644 Binary files a/models/domination/dom_unclaimed.md3 and b/models/domination/dom_unclaimed.md3 differ diff --git a/models/domination/dom_yellow.md3 b/models/domination/dom_yellow.md3 index bb6ff52fe5..b1da0d1b09 100644 Binary files a/models/domination/dom_yellow.md3 and b/models/domination/dom_yellow.md3 differ diff --git a/models/gibs/chunk.mdl_0.tga b/models/gibs/chunk.mdl_0.tga new file mode 100644 index 0000000000..4192b709db Binary files /dev/null and b/models/gibs/chunk.mdl_0.tga differ diff --git a/models/gibs/gib1.md3 b/models/gibs/gib1.md3 deleted file mode 100644 index 276982da52..0000000000 Binary files a/models/gibs/gib1.md3 and /dev/null differ diff --git a/models/gibs/gib1.mdl b/models/gibs/gib1.mdl deleted file mode 100644 index 8f8501cb06..0000000000 Binary files a/models/gibs/gib1.mdl and /dev/null differ diff --git a/models/gibs/gib2.md3 b/models/gibs/gib2.md3 deleted file mode 100644 index f5a2f73620..0000000000 Binary files a/models/gibs/gib2.md3 and /dev/null differ diff --git a/models/gibs/gib2.mdl b/models/gibs/gib2.mdl deleted file mode 100644 index b4b7425ee8..0000000000 Binary files a/models/gibs/gib2.mdl and /dev/null differ diff --git a/models/gibs/gib3.md3 b/models/gibs/gib3.md3 deleted file mode 100644 index 8a38b42cb8..0000000000 Binary files a/models/gibs/gib3.md3 and /dev/null differ diff --git a/models/gibs/gib3.mdl b/models/gibs/gib3.mdl deleted file mode 100644 index 17279df130..0000000000 Binary files a/models/gibs/gib3.mdl and /dev/null differ diff --git a/models/gibs/gib4.md3 b/models/gibs/gib4.md3 deleted file mode 100644 index dd4c5b53d2..0000000000 Binary files a/models/gibs/gib4.md3 and /dev/null differ diff --git a/models/gibs/gib5.md3 b/models/gibs/gib5.md3 deleted file mode 100644 index 6a51eb220d..0000000000 Binary files a/models/gibs/gib5.md3 and /dev/null differ diff --git a/models/gibs/gib6.md3 b/models/gibs/gib6.md3 deleted file mode 100644 index 956c9022bf..0000000000 Binary files a/models/gibs/gib6.md3 and /dev/null differ diff --git a/models/items/5hp.tga b/models/items/5hp.tga new file mode 100644 index 0000000000..e731fe4fe2 Binary files /dev/null and b/models/items/5hp.tga differ diff --git a/models/items/5hp_gloss.tga b/models/items/5hp_gloss.tga new file mode 100644 index 0000000000..4e4b32b629 Binary files /dev/null and b/models/items/5hp_gloss.tga differ diff --git a/models/items/5hp_glow.tga b/models/items/5hp_glow.tga new file mode 100644 index 0000000000..f1ae8f20a1 Binary files /dev/null and b/models/items/5hp_glow.tga differ diff --git a/models/items/5hp_norm.tga b/models/items/5hp_norm.tga new file mode 100644 index 0000000000..78eb7c34dc Binary files /dev/null and b/models/items/5hp_norm.tga differ diff --git a/models/items/5hp_reflect.tga b/models/items/5hp_reflect.tga new file mode 100644 index 0000000000..e880795a02 Binary files /dev/null and b/models/items/5hp_reflect.tga differ diff --git a/models/items/g_h1.md3 b/models/items/g_h1.md3 index 3b6e7e9707..9e6da7569b 100644 Binary files a/models/items/g_h1.md3 and b/models/items/g_h1.md3 differ diff --git a/models/items/g_h100.md3 b/models/items/g_h100.md3 index 1893bc5387..f589d08bc0 100644 Binary files a/models/items/g_h100.md3 and b/models/items/g_h100.md3 differ diff --git a/models/items/g_h25.md3 b/models/items/g_h25.md3 index 09ca47b04f..06419c9443 100644 Binary files a/models/items/g_h25.md3 and b/models/items/g_h25.md3 differ diff --git a/models/items/g_h50.md3 b/models/items/g_h50.md3 index 9d26a56761..90a91f2a59 100644 Binary files a/models/items/g_h50.md3 and b/models/items/g_h50.md3 differ diff --git a/models/items/glass_gloss.tga b/models/items/glass_gloss.tga new file mode 100644 index 0000000000..55e3793097 Binary files /dev/null and b/models/items/glass_gloss.tga differ diff --git a/models/items/h25.tga b/models/items/h25.tga new file mode 100644 index 0000000000..377c6e491c Binary files /dev/null and b/models/items/h25.tga differ diff --git a/models/items/h25_gloss.tga b/models/items/h25_gloss.tga new file mode 100644 index 0000000000..73e16a1539 Binary files /dev/null and b/models/items/h25_gloss.tga differ diff --git a/models/items/h25_glow.tga b/models/items/h25_glow.tga new file mode 100644 index 0000000000..d76a2bca3a Binary files /dev/null and b/models/items/h25_glow.tga differ diff --git a/models/items/h25_norm.tga b/models/items/h25_norm.tga new file mode 100644 index 0000000000..769d3884a0 Binary files /dev/null and b/models/items/h25_norm.tga differ diff --git a/models/items/h25_reflect.tga b/models/items/h25_reflect.tga new file mode 100644 index 0000000000..73e16a1539 Binary files /dev/null and b/models/items/h25_reflect.tga differ diff --git a/models/items/h50.tga b/models/items/h50.tga new file mode 100644 index 0000000000..36cdbe0c04 Binary files /dev/null and b/models/items/h50.tga differ diff --git a/models/items/h50_gloss.tga b/models/items/h50_gloss.tga new file mode 100644 index 0000000000..4a52e3f61c Binary files /dev/null and b/models/items/h50_gloss.tga differ diff --git a/models/items/h50_glow.tga b/models/items/h50_glow.tga new file mode 100644 index 0000000000..0b6efb0f28 Binary files /dev/null and b/models/items/h50_glow.tga differ diff --git a/models/items/h50_norm.tga b/models/items/h50_norm.tga new file mode 100644 index 0000000000..4ef747579e Binary files /dev/null and b/models/items/h50_norm.tga differ diff --git a/models/items/h50_reflect.tga b/models/items/h50_reflect.tga new file mode 100644 index 0000000000..272b07ed80 Binary files /dev/null and b/models/items/h50_reflect.tga differ diff --git a/models/items/h_mega.tga b/models/items/h_mega.tga new file mode 100644 index 0000000000..2c56ea290d Binary files /dev/null and b/models/items/h_mega.tga differ diff --git a/models/items/h_mega_gloss.tga b/models/items/h_mega_gloss.tga new file mode 100644 index 0000000000..26cb0310e9 Binary files /dev/null and b/models/items/h_mega_gloss.tga differ diff --git a/models/items/h_mega_glow.tga b/models/items/h_mega_glow.tga new file mode 100644 index 0000000000..ede6462fe8 Binary files /dev/null and b/models/items/h_mega_glow.tga differ diff --git a/models/items/h_mega_norm.tga b/models/items/h_mega_norm.tga new file mode 100644 index 0000000000..39a88d7f74 Binary files /dev/null and b/models/items/h_mega_norm.tga differ diff --git a/models/items/h_mega_reflect.tga b/models/items/h_mega_reflect.tga new file mode 100644 index 0000000000..6fc8a8b2f9 Binary files /dev/null and b/models/items/h_mega_reflect.tga differ diff --git a/models/items/red.tga b/models/items/red.tga new file mode 100644 index 0000000000..07ce79a10d Binary files /dev/null and b/models/items/red.tga differ diff --git a/models/items/red_gloss.tga b/models/items/red_gloss.tga new file mode 100644 index 0000000000..55e3793097 Binary files /dev/null and b/models/items/red_gloss.tga differ diff --git a/models/items/red_reflect.tga b/models/items/red_reflect.tga new file mode 100644 index 0000000000..e8eaf4f9e0 Binary files /dev/null and b/models/items/red_reflect.tga differ diff --git a/models/keys/key.md3 b/models/keys/key.md3 new file mode 100644 index 0000000000..097c90ce47 Binary files /dev/null and b/models/keys/key.md3 differ diff --git a/models/keys/key.tga b/models/keys/key.tga new file mode 100644 index 0000000000..5e70fa304a Binary files /dev/null and b/models/keys/key.tga differ diff --git a/models/player/erebus.iqm b/models/player/erebus.iqm index ebd112b84a..bdfc95832d 100644 Binary files a/models/player/erebus.iqm and b/models/player/erebus.iqm differ diff --git a/models/player/erebus.iqm.framegroups b/models/player/erebus.iqm.framegroups index 16b3e92c79..6432971bbe 100644 --- a/models/player/erebus.iqm.framegroups +++ b/models/player/erebus.iqm.framegroups @@ -1,23 +1,31 @@ -0 36 15.000000 0 // dieone -36 20 15.000000 0 // dietwo -56 15 15.000000 1 // draw +0 36 30.000000 0 // dieone +36 20 25.000000 0 // dietwo +56 15 30.000000 1 // draw 71 20 15.000000 1 // duck -91 21 30.000000 1 // duckwalk +91 20 32.000000 1 // duckwalk 112 16 15.000000 0 // duckjump -128 15 5.000000 1 // duckidle +128 15 10.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 24.000000 0 // painone +359 17 34.000000 0 // paintwo +376 3 3.000000 0 // shoot +379 21 15.000000 1 // taunt +400 20 29.000000 1 // run +421 20 29.000000 1 // runbackwards +442 20 29.000000 1 // strafeleft +463 20 29.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 20 29.000000 1 // forwardright +509 20 29.000000 1 // forwardleft +530 20 29.000000 1 // backright +551 20 29.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +656 20 32.000000 1 // duckwalkforwardright +677 20 32.000000 1 // duckwalkforwardleft +698 20 32.000000 1 // duckwalkbackright +719 20 32.000000 1 // duckwalkbackleft diff --git a/models/player/erebus.iqm_1.skin b/models/player/erebus.iqm_1.skin deleted file mode 100644 index 4597ceff1e..0000000000 --- a/models/player/erebus.iqm_1.skin +++ /dev/null @@ -1,2 +0,0 @@ -erebus,erebusfullbright -erebus.001,shadowhead diff --git a/models/player/erebus.iqm_1.sounds b/models/player/erebus.iqm_1.sounds deleted file mode 100644 index a97a073b95..0000000000 --- a/models/player/erebus.iqm_1.sounds +++ /dev/null @@ -1,32 +0,0 @@ -//TAG: soldier -//affirmative sound/player/carni-lycan/player/affirmative 0 -attack sound/player/soldier/coms/attack 0 -//attacking sound/player/carni-lycan/player/attacking 0 -attackinfive sound/player/soldier/coms/attackinfive 0 -coverme sound/player/soldier/coms/coverme 0 -defend sound/player/soldier/coms/defend 0 -//defending sound/player/carni-lycan/player/defending 0 -//droppedflag sound/player/carni-lycan/player/droppedflag 0 -flagcarriertakingdamage sound/player/soldier/coms/flagcarriertakingdamage 0 -freelance sound/player/soldier/coms/freelance 2 -getflag sound/player/soldier/coms/getflag 0 -incoming sound/player/soldier/coms/incoming 0 -meet sound/player/soldier/coms/meet 0 -needhelp sound/player/soldier/coms/needhelp 2 -//negative sound/player/carni-lycan/player/negative 0 -//onmyway sound/player/carni-lycan/player/onmyway 0 -//roaming sound/player/carni-lycan/player/roaming 0 -//seenenemy sound/player/carni-lycan/player/seenenemy 0 -seenflag sound/player/soldier/coms/seenflag 0 -taunt sound/player/soldier/coms/taunt 3 -teamshoot sound/player/soldier/coms/teamshoot 3 -death sound/player/soldier/player/death 3 -drown sound/player/soldier/player/drown 0 -fall sound/player/soldier/player/fall 0 -falling sound/player/soldier/player/falling 0 -gasp sound/player/soldier/player/gasp 0 -jump sound/player/soldier/player/jump 0 -pain25 sound/player/soldier/player/pain25 0 -pain50 sound/player/soldier/player/pain50 0 -pain75 sound/player/soldier/player/pain75 0 -pain100 sound/player/soldier/player/pain100 0 diff --git a/models/player/erebus.iqm_1.tga b/models/player/erebus.iqm_1.tga deleted file mode 100644 index bf151b5d22..0000000000 Binary files a/models/player/erebus.iqm_1.tga and /dev/null differ diff --git a/models/player/erebus.iqm_1.txt b/models/player/erebus.iqm_1.txt deleted file mode 100644 index 7b8389b40f..0000000000 --- a/models/player/erebus.iqm_1.txt +++ /dev/null @@ -1,7 +0,0 @@ -name Glowing Erebus -species human -sex Male -weight 106 -age 26 - -Heavyweight Xonotic Solider with LEDs diff --git a/models/player/erebus_lod1.iqm b/models/player/erebus_lod1.iqm index 21cd3d431e..5a9ec52554 100644 Binary files a/models/player/erebus_lod1.iqm and b/models/player/erebus_lod1.iqm differ diff --git a/models/player/erebus_lod1.iqm.framegroups b/models/player/erebus_lod1.iqm.framegroups index 16b3e92c79..6432971bbe 100644 --- a/models/player/erebus_lod1.iqm.framegroups +++ b/models/player/erebus_lod1.iqm.framegroups @@ -1,23 +1,31 @@ -0 36 15.000000 0 // dieone -36 20 15.000000 0 // dietwo -56 15 15.000000 1 // draw +0 36 30.000000 0 // dieone +36 20 25.000000 0 // dietwo +56 15 30.000000 1 // draw 71 20 15.000000 1 // duck -91 21 30.000000 1 // duckwalk +91 20 32.000000 1 // duckwalk 112 16 15.000000 0 // duckjump -128 15 5.000000 1 // duckidle +128 15 10.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 24.000000 0 // painone +359 17 34.000000 0 // paintwo +376 3 3.000000 0 // shoot +379 21 15.000000 1 // taunt +400 20 29.000000 1 // run +421 20 29.000000 1 // runbackwards +442 20 29.000000 1 // strafeleft +463 20 29.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 20 29.000000 1 // forwardright +509 20 29.000000 1 // forwardleft +530 20 29.000000 1 // backright +551 20 29.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +656 20 32.000000 1 // duckwalkforwardright +677 20 32.000000 1 // duckwalkforwardleft +698 20 32.000000 1 // duckwalkbackright +719 20 32.000000 1 // duckwalkbackleft diff --git a/models/player/erebus_lod1.iqm_1.skin b/models/player/erebus_lod1.iqm_1.skin deleted file mode 100644 index 4597ceff1e..0000000000 --- a/models/player/erebus_lod1.iqm_1.skin +++ /dev/null @@ -1,2 +0,0 @@ -erebus,erebusfullbright -erebus.001,shadowhead diff --git a/models/player/erebus_lod2.iqm b/models/player/erebus_lod2.iqm index 34e7e8014c..add024d0f8 100644 Binary files a/models/player/erebus_lod2.iqm and b/models/player/erebus_lod2.iqm differ diff --git a/models/player/erebus_lod2.iqm.framegroups b/models/player/erebus_lod2.iqm.framegroups index 16b3e92c79..6432971bbe 100644 --- a/models/player/erebus_lod2.iqm.framegroups +++ b/models/player/erebus_lod2.iqm.framegroups @@ -1,23 +1,31 @@ -0 36 15.000000 0 // dieone -36 20 15.000000 0 // dietwo -56 15 15.000000 1 // draw +0 36 30.000000 0 // dieone +36 20 25.000000 0 // dietwo +56 15 30.000000 1 // draw 71 20 15.000000 1 // duck -91 21 30.000000 1 // duckwalk +91 20 32.000000 1 // duckwalk 112 16 15.000000 0 // duckjump -128 15 5.000000 1 // duckidle +128 15 10.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 24.000000 0 // painone +359 17 34.000000 0 // paintwo +376 3 3.000000 0 // shoot +379 21 15.000000 1 // taunt +400 20 29.000000 1 // run +421 20 29.000000 1 // runbackwards +442 20 29.000000 1 // strafeleft +463 20 29.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 20 29.000000 1 // forwardright +509 20 29.000000 1 // forwardleft +530 20 29.000000 1 // backright +551 20 29.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +656 20 32.000000 1 // duckwalkforwardright +677 20 32.000000 1 // duckwalkforwardleft +698 20 32.000000 1 // duckwalkbackright +719 20 32.000000 1 // duckwalkbackleft diff --git a/models/player/erebus_lod2.iqm_1.skin b/models/player/erebus_lod2.iqm_1.skin deleted file mode 100644 index 4597ceff1e..0000000000 --- a/models/player/erebus_lod2.iqm_1.skin +++ /dev/null @@ -1,2 +0,0 @@ -erebus,erebusfullbright -erebus.001,shadowhead diff --git a/models/player/gak.iqm b/models/player/gak.iqm index dccf325bca..275921e1dc 100644 Binary files a/models/player/gak.iqm and b/models/player/gak.iqm differ diff --git a/models/player/gak.iqm.framegroups b/models/player/gak.iqm.framegroups index 16b3e92c79..98eabd70b5 100644 --- a/models/player/gak.iqm.framegroups +++ b/models/player/gak.iqm.framegroups @@ -6,18 +6,26 @@ 112 16 15.000000 0 // duckjump 128 15 5.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 15.000000 0 // painone +359 17 15.000000 0 // paintwo +376 3 15.000000 0 // shoot +379 21 15.000000 1 // taunt +400 21 35.000000 1 // run +421 21 35.000000 1 // runbackwards +442 21 35.000000 1 // strafeleft +463 21 35.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 21 35.000000 1 // forwardright +509 21 35.000000 1 // forwardleft +530 21 35.000000 1 // backright +551 21 30.000000 1 // backleft +572 21 20.000000 0 // melee +593 21 30.000000 1 // duckwalkbackwards +91 21 30.000000 1 // duckwalkstrafeleft +91 21 30.000000 1 // duckwalkstraferight +91 21 30.000000 1 // duckwalkforwardright +91 21 30.000000 1 // duckwalkforwardleft +593 21 30.000000 1 // duckwalkbackright +593 21 30.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/gak_lod1.iqm b/models/player/gak_lod1.iqm new file mode 100644 index 0000000000..a9e08062af Binary files /dev/null and b/models/player/gak_lod1.iqm differ diff --git a/models/player/gak_lod1.iqm.framegroups b/models/player/gak_lod1.iqm.framegroups new file mode 100644 index 0000000000..98eabd70b5 --- /dev/null +++ b/models/player/gak_lod1.iqm.framegroups @@ -0,0 +1,31 @@ +0 36 15.000000 0 // dieone +36 20 15.000000 0 // dietwo +56 15 15.000000 1 // draw +71 20 15.000000 1 // duck +91 21 30.000000 1 // duckwalk +112 16 15.000000 0 // duckjump +128 15 5.000000 1 // duckidle +143 41 5.000000 1 // idle +184 160 25.000000 0 // jump +344 15 15.000000 0 // painone +359 17 15.000000 0 // paintwo +376 3 15.000000 0 // shoot +379 21 15.000000 1 // taunt +400 21 35.000000 1 // run +421 21 35.000000 1 // runbackwards +442 21 35.000000 1 // strafeleft +463 21 35.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 21 35.000000 1 // forwardright +509 21 35.000000 1 // forwardleft +530 21 35.000000 1 // backright +551 21 30.000000 1 // backleft +572 21 20.000000 0 // melee +593 21 30.000000 1 // duckwalkbackwards +91 21 30.000000 1 // duckwalkstrafeleft +91 21 30.000000 1 // duckwalkstraferight +91 21 30.000000 1 // duckwalkforwardright +91 21 30.000000 1 // duckwalkforwardleft +593 21 30.000000 1 // duckwalkbackright +593 21 30.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/gak_lod2.iqm b/models/player/gak_lod2.iqm new file mode 100644 index 0000000000..d7033e8d01 Binary files /dev/null and b/models/player/gak_lod2.iqm differ diff --git a/models/player/gak_lod2.iqm.framegroups b/models/player/gak_lod2.iqm.framegroups new file mode 100644 index 0000000000..98eabd70b5 --- /dev/null +++ b/models/player/gak_lod2.iqm.framegroups @@ -0,0 +1,31 @@ +0 36 15.000000 0 // dieone +36 20 15.000000 0 // dietwo +56 15 15.000000 1 // draw +71 20 15.000000 1 // duck +91 21 30.000000 1 // duckwalk +112 16 15.000000 0 // duckjump +128 15 5.000000 1 // duckidle +143 41 5.000000 1 // idle +184 160 25.000000 0 // jump +344 15 15.000000 0 // painone +359 17 15.000000 0 // paintwo +376 3 15.000000 0 // shoot +379 21 15.000000 1 // taunt +400 21 35.000000 1 // run +421 21 35.000000 1 // runbackwards +442 21 35.000000 1 // strafeleft +463 21 35.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 21 35.000000 1 // forwardright +509 21 35.000000 1 // forwardleft +530 21 35.000000 1 // backright +551 21 30.000000 1 // backleft +572 21 20.000000 0 // melee +593 21 30.000000 1 // duckwalkbackwards +91 21 30.000000 1 // duckwalkstrafeleft +91 21 30.000000 1 // duckwalkstraferight +91 21 30.000000 1 // duckwalkforwardright +91 21 30.000000 1 // duckwalkforwardleft +593 21 30.000000 1 // duckwalkbackright +593 21 30.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/gakarmored.iqm b/models/player/gakarmored.iqm index c4b574a074..824e52ae6c 100644 Binary files a/models/player/gakarmored.iqm and b/models/player/gakarmored.iqm differ diff --git a/models/player/gakarmored.iqm.framegroups b/models/player/gakarmored.iqm.framegroups index 16b3e92c79..98eabd70b5 100644 --- a/models/player/gakarmored.iqm.framegroups +++ b/models/player/gakarmored.iqm.framegroups @@ -6,18 +6,26 @@ 112 16 15.000000 0 // duckjump 128 15 5.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 15.000000 0 // painone +359 17 15.000000 0 // paintwo +376 3 15.000000 0 // shoot +379 21 15.000000 1 // taunt +400 21 35.000000 1 // run +421 21 35.000000 1 // runbackwards +442 21 35.000000 1 // strafeleft +463 21 35.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 21 35.000000 1 // forwardright +509 21 35.000000 1 // forwardleft +530 21 35.000000 1 // backright +551 21 30.000000 1 // backleft +572 21 20.000000 0 // melee +593 21 30.000000 1 // duckwalkbackwards +91 21 30.000000 1 // duckwalkstrafeleft +91 21 30.000000 1 // duckwalkstraferight +91 21 30.000000 1 // duckwalkforwardright +91 21 30.000000 1 // duckwalkforwardleft +593 21 30.000000 1 // duckwalkbackright +593 21 30.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/gakarmored_lod1.iqm b/models/player/gakarmored_lod1.iqm new file mode 100644 index 0000000000..bbf00f7018 Binary files /dev/null and b/models/player/gakarmored_lod1.iqm differ diff --git a/models/player/gakarmored_lod1.iqm.framegroups b/models/player/gakarmored_lod1.iqm.framegroups new file mode 100644 index 0000000000..98eabd70b5 --- /dev/null +++ b/models/player/gakarmored_lod1.iqm.framegroups @@ -0,0 +1,31 @@ +0 36 15.000000 0 // dieone +36 20 15.000000 0 // dietwo +56 15 15.000000 1 // draw +71 20 15.000000 1 // duck +91 21 30.000000 1 // duckwalk +112 16 15.000000 0 // duckjump +128 15 5.000000 1 // duckidle +143 41 5.000000 1 // idle +184 160 25.000000 0 // jump +344 15 15.000000 0 // painone +359 17 15.000000 0 // paintwo +376 3 15.000000 0 // shoot +379 21 15.000000 1 // taunt +400 21 35.000000 1 // run +421 21 35.000000 1 // runbackwards +442 21 35.000000 1 // strafeleft +463 21 35.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 21 35.000000 1 // forwardright +509 21 35.000000 1 // forwardleft +530 21 35.000000 1 // backright +551 21 30.000000 1 // backleft +572 21 20.000000 0 // melee +593 21 30.000000 1 // duckwalkbackwards +91 21 30.000000 1 // duckwalkstrafeleft +91 21 30.000000 1 // duckwalkstraferight +91 21 30.000000 1 // duckwalkforwardright +91 21 30.000000 1 // duckwalkforwardleft +593 21 30.000000 1 // duckwalkbackright +593 21 30.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/gakarmored_lod2.iqm b/models/player/gakarmored_lod2.iqm new file mode 100644 index 0000000000..8fdbceffad Binary files /dev/null and b/models/player/gakarmored_lod2.iqm differ diff --git a/models/player/gakarmored_lod2.iqm.framegroups b/models/player/gakarmored_lod2.iqm.framegroups new file mode 100644 index 0000000000..98eabd70b5 --- /dev/null +++ b/models/player/gakarmored_lod2.iqm.framegroups @@ -0,0 +1,31 @@ +0 36 15.000000 0 // dieone +36 20 15.000000 0 // dietwo +56 15 15.000000 1 // draw +71 20 15.000000 1 // duck +91 21 30.000000 1 // duckwalk +112 16 15.000000 0 // duckjump +128 15 5.000000 1 // duckidle +143 41 5.000000 1 // idle +184 160 25.000000 0 // jump +344 15 15.000000 0 // painone +359 17 15.000000 0 // paintwo +376 3 15.000000 0 // shoot +379 21 15.000000 1 // taunt +400 21 35.000000 1 // run +421 21 35.000000 1 // runbackwards +442 21 35.000000 1 // strafeleft +463 21 35.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 21 35.000000 1 // forwardright +509 21 35.000000 1 // forwardleft +530 21 35.000000 1 // backright +551 21 30.000000 1 // backleft +572 21 20.000000 0 // melee +593 21 30.000000 1 // duckwalkbackwards +91 21 30.000000 1 // duckwalkstrafeleft +91 21 30.000000 1 // duckwalkstraferight +91 21 30.000000 1 // duckwalkforwardright +91 21 30.000000 1 // duckwalkforwardleft +593 21 30.000000 1 // duckwalkbackright +593 21 30.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/gakmasked.iqm b/models/player/gakmasked.iqm index 646c628f86..ac94551a64 100644 Binary files a/models/player/gakmasked.iqm and b/models/player/gakmasked.iqm differ diff --git a/models/player/gakmasked.iqm.framegroups b/models/player/gakmasked.iqm.framegroups index 16b3e92c79..98eabd70b5 100644 --- a/models/player/gakmasked.iqm.framegroups +++ b/models/player/gakmasked.iqm.framegroups @@ -6,18 +6,26 @@ 112 16 15.000000 0 // duckjump 128 15 5.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 15.000000 0 // painone +359 17 15.000000 0 // paintwo +376 3 15.000000 0 // shoot +379 21 15.000000 1 // taunt +400 21 35.000000 1 // run +421 21 35.000000 1 // runbackwards +442 21 35.000000 1 // strafeleft +463 21 35.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 21 35.000000 1 // forwardright +509 21 35.000000 1 // forwardleft +530 21 35.000000 1 // backright +551 21 30.000000 1 // backleft +572 21 20.000000 0 // melee +593 21 30.000000 1 // duckwalkbackwards +91 21 30.000000 1 // duckwalkstrafeleft +91 21 30.000000 1 // duckwalkstraferight +91 21 30.000000 1 // duckwalkforwardright +91 21 30.000000 1 // duckwalkforwardleft +593 21 30.000000 1 // duckwalkbackright +593 21 30.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/gakmasked_lod1.iqm b/models/player/gakmasked_lod1.iqm new file mode 100644 index 0000000000..444dab1d6d Binary files /dev/null and b/models/player/gakmasked_lod1.iqm differ diff --git a/models/player/gakmasked_lod1.iqm.framegroups b/models/player/gakmasked_lod1.iqm.framegroups new file mode 100644 index 0000000000..98eabd70b5 --- /dev/null +++ b/models/player/gakmasked_lod1.iqm.framegroups @@ -0,0 +1,31 @@ +0 36 15.000000 0 // dieone +36 20 15.000000 0 // dietwo +56 15 15.000000 1 // draw +71 20 15.000000 1 // duck +91 21 30.000000 1 // duckwalk +112 16 15.000000 0 // duckjump +128 15 5.000000 1 // duckidle +143 41 5.000000 1 // idle +184 160 25.000000 0 // jump +344 15 15.000000 0 // painone +359 17 15.000000 0 // paintwo +376 3 15.000000 0 // shoot +379 21 15.000000 1 // taunt +400 21 35.000000 1 // run +421 21 35.000000 1 // runbackwards +442 21 35.000000 1 // strafeleft +463 21 35.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 21 35.000000 1 // forwardright +509 21 35.000000 1 // forwardleft +530 21 35.000000 1 // backright +551 21 30.000000 1 // backleft +572 21 20.000000 0 // melee +593 21 30.000000 1 // duckwalkbackwards +91 21 30.000000 1 // duckwalkstrafeleft +91 21 30.000000 1 // duckwalkstraferight +91 21 30.000000 1 // duckwalkforwardright +91 21 30.000000 1 // duckwalkforwardleft +593 21 30.000000 1 // duckwalkbackright +593 21 30.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/gakmasked_lod2.iqm b/models/player/gakmasked_lod2.iqm new file mode 100644 index 0000000000..466e3a5d0e Binary files /dev/null and b/models/player/gakmasked_lod2.iqm differ diff --git a/models/player/gakmasked_lod2.iqm.framegroups b/models/player/gakmasked_lod2.iqm.framegroups new file mode 100644 index 0000000000..98eabd70b5 --- /dev/null +++ b/models/player/gakmasked_lod2.iqm.framegroups @@ -0,0 +1,31 @@ +0 36 15.000000 0 // dieone +36 20 15.000000 0 // dietwo +56 15 15.000000 1 // draw +71 20 15.000000 1 // duck +91 21 30.000000 1 // duckwalk +112 16 15.000000 0 // duckjump +128 15 5.000000 1 // duckidle +143 41 5.000000 1 // idle +184 160 25.000000 0 // jump +344 15 15.000000 0 // painone +359 17 15.000000 0 // paintwo +376 3 15.000000 0 // shoot +379 21 15.000000 1 // taunt +400 21 35.000000 1 // run +421 21 35.000000 1 // runbackwards +442 21 35.000000 1 // strafeleft +463 21 35.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 21 35.000000 1 // forwardright +509 21 35.000000 1 // forwardleft +530 21 35.000000 1 // backright +551 21 30.000000 1 // backleft +572 21 20.000000 0 // melee +593 21 30.000000 1 // duckwalkbackwards +91 21 30.000000 1 // duckwalkstrafeleft +91 21 30.000000 1 // duckwalkstraferight +91 21 30.000000 1 // duckwalkforwardright +91 21 30.000000 1 // duckwalkforwardleft +593 21 30.000000 1 // duckwalkbackright +593 21 30.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/ignis.iqm b/models/player/ignis.iqm index 2e47493464..3e65b336a7 100644 Binary files a/models/player/ignis.iqm and b/models/player/ignis.iqm differ diff --git a/models/player/ignis.iqm.framegroups b/models/player/ignis.iqm.framegroups index 16b3e92c79..6432971bbe 100644 --- a/models/player/ignis.iqm.framegroups +++ b/models/player/ignis.iqm.framegroups @@ -1,23 +1,31 @@ -0 36 15.000000 0 // dieone -36 20 15.000000 0 // dietwo -56 15 15.000000 1 // draw +0 36 30.000000 0 // dieone +36 20 25.000000 0 // dietwo +56 15 30.000000 1 // draw 71 20 15.000000 1 // duck -91 21 30.000000 1 // duckwalk +91 20 32.000000 1 // duckwalk 112 16 15.000000 0 // duckjump -128 15 5.000000 1 // duckidle +128 15 10.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 24.000000 0 // painone +359 17 34.000000 0 // paintwo +376 3 3.000000 0 // shoot +379 21 15.000000 1 // taunt +400 20 29.000000 1 // run +421 20 29.000000 1 // runbackwards +442 20 29.000000 1 // strafeleft +463 20 29.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 20 29.000000 1 // forwardright +509 20 29.000000 1 // forwardleft +530 20 29.000000 1 // backright +551 20 29.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +656 20 32.000000 1 // duckwalkforwardright +677 20 32.000000 1 // duckwalkforwardleft +698 20 32.000000 1 // duckwalkbackright +719 20 32.000000 1 // duckwalkbackleft diff --git a/models/player/ignis_lod1.iqm b/models/player/ignis_lod1.iqm index 38a6b3be2c..d1f5c4524e 100644 Binary files a/models/player/ignis_lod1.iqm and b/models/player/ignis_lod1.iqm differ diff --git a/models/player/ignis_lod1.iqm.framegroups b/models/player/ignis_lod1.iqm.framegroups index 16b3e92c79..6432971bbe 100644 --- a/models/player/ignis_lod1.iqm.framegroups +++ b/models/player/ignis_lod1.iqm.framegroups @@ -1,23 +1,31 @@ -0 36 15.000000 0 // dieone -36 20 15.000000 0 // dietwo -56 15 15.000000 1 // draw +0 36 30.000000 0 // dieone +36 20 25.000000 0 // dietwo +56 15 30.000000 1 // draw 71 20 15.000000 1 // duck -91 21 30.000000 1 // duckwalk +91 20 32.000000 1 // duckwalk 112 16 15.000000 0 // duckjump -128 15 5.000000 1 // duckidle +128 15 10.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 24.000000 0 // painone +359 17 34.000000 0 // paintwo +376 3 3.000000 0 // shoot +379 21 15.000000 1 // taunt +400 20 29.000000 1 // run +421 20 29.000000 1 // runbackwards +442 20 29.000000 1 // strafeleft +463 20 29.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 20 29.000000 1 // forwardright +509 20 29.000000 1 // forwardleft +530 20 29.000000 1 // backright +551 20 29.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +656 20 32.000000 1 // duckwalkforwardright +677 20 32.000000 1 // duckwalkforwardleft +698 20 32.000000 1 // duckwalkbackright +719 20 32.000000 1 // duckwalkbackleft diff --git a/models/player/ignis_lod2.iqm b/models/player/ignis_lod2.iqm index ac9a40653a..cbe75b6f4e 100644 Binary files a/models/player/ignis_lod2.iqm and b/models/player/ignis_lod2.iqm differ diff --git a/models/player/ignis_lod2.iqm.framegroups b/models/player/ignis_lod2.iqm.framegroups index 16b3e92c79..6432971bbe 100644 --- a/models/player/ignis_lod2.iqm.framegroups +++ b/models/player/ignis_lod2.iqm.framegroups @@ -1,23 +1,31 @@ -0 36 15.000000 0 // dieone -36 20 15.000000 0 // dietwo -56 15 15.000000 1 // draw +0 36 30.000000 0 // dieone +36 20 25.000000 0 // dietwo +56 15 30.000000 1 // draw 71 20 15.000000 1 // duck -91 21 30.000000 1 // duckwalk +91 20 32.000000 1 // duckwalk 112 16 15.000000 0 // duckjump -128 15 5.000000 1 // duckidle +128 15 10.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 24.000000 0 // painone +359 17 34.000000 0 // paintwo +376 3 3.000000 0 // shoot +379 21 15.000000 1 // taunt +400 20 29.000000 1 // run +421 20 29.000000 1 // runbackwards +442 20 29.000000 1 // strafeleft +463 20 29.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 20 29.000000 1 // forwardright +509 20 29.000000 1 // forwardleft +530 20 29.000000 1 // backright +551 20 29.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +656 20 32.000000 1 // duckwalkforwardright +677 20 32.000000 1 // duckwalkforwardleft +698 20 32.000000 1 // duckwalkbackright +719 20 32.000000 1 // duckwalkbackleft diff --git a/models/player/ignishalfmasked.iqm b/models/player/ignishalfmasked.iqm index 7f5a51295e..7b11d80edb 100644 Binary files a/models/player/ignishalfmasked.iqm and b/models/player/ignishalfmasked.iqm differ diff --git a/models/player/ignishalfmasked.iqm.framegroups b/models/player/ignishalfmasked.iqm.framegroups index 16b3e92c79..6432971bbe 100644 --- a/models/player/ignishalfmasked.iqm.framegroups +++ b/models/player/ignishalfmasked.iqm.framegroups @@ -1,23 +1,31 @@ -0 36 15.000000 0 // dieone -36 20 15.000000 0 // dietwo -56 15 15.000000 1 // draw +0 36 30.000000 0 // dieone +36 20 25.000000 0 // dietwo +56 15 30.000000 1 // draw 71 20 15.000000 1 // duck -91 21 30.000000 1 // duckwalk +91 20 32.000000 1 // duckwalk 112 16 15.000000 0 // duckjump -128 15 5.000000 1 // duckidle +128 15 10.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 24.000000 0 // painone +359 17 34.000000 0 // paintwo +376 3 3.000000 0 // shoot +379 21 15.000000 1 // taunt +400 20 29.000000 1 // run +421 20 29.000000 1 // runbackwards +442 20 29.000000 1 // strafeleft +463 20 29.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 20 29.000000 1 // forwardright +509 20 29.000000 1 // forwardleft +530 20 29.000000 1 // backright +551 20 29.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +656 20 32.000000 1 // duckwalkforwardright +677 20 32.000000 1 // duckwalkforwardleft +698 20 32.000000 1 // duckwalkbackright +719 20 32.000000 1 // duckwalkbackleft diff --git a/models/player/ignishalfmasked_lod1.iqm b/models/player/ignishalfmasked_lod1.iqm index c3b3fa4871..e3877a753c 100644 Binary files a/models/player/ignishalfmasked_lod1.iqm and b/models/player/ignishalfmasked_lod1.iqm differ diff --git a/models/player/ignishalfmasked_lod1.iqm.framegroups b/models/player/ignishalfmasked_lod1.iqm.framegroups index 16b3e92c79..6432971bbe 100644 --- a/models/player/ignishalfmasked_lod1.iqm.framegroups +++ b/models/player/ignishalfmasked_lod1.iqm.framegroups @@ -1,23 +1,31 @@ -0 36 15.000000 0 // dieone -36 20 15.000000 0 // dietwo -56 15 15.000000 1 // draw +0 36 30.000000 0 // dieone +36 20 25.000000 0 // dietwo +56 15 30.000000 1 // draw 71 20 15.000000 1 // duck -91 21 30.000000 1 // duckwalk +91 20 32.000000 1 // duckwalk 112 16 15.000000 0 // duckjump -128 15 5.000000 1 // duckidle +128 15 10.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 24.000000 0 // painone +359 17 34.000000 0 // paintwo +376 3 3.000000 0 // shoot +379 21 15.000000 1 // taunt +400 20 29.000000 1 // run +421 20 29.000000 1 // runbackwards +442 20 29.000000 1 // strafeleft +463 20 29.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 20 29.000000 1 // forwardright +509 20 29.000000 1 // forwardleft +530 20 29.000000 1 // backright +551 20 29.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +656 20 32.000000 1 // duckwalkforwardright +677 20 32.000000 1 // duckwalkforwardleft +698 20 32.000000 1 // duckwalkbackright +719 20 32.000000 1 // duckwalkbackleft diff --git a/models/player/ignishalfmasked_lod2.iqm b/models/player/ignishalfmasked_lod2.iqm index 3ad25e9c41..48b0696de9 100644 Binary files a/models/player/ignishalfmasked_lod2.iqm and b/models/player/ignishalfmasked_lod2.iqm differ diff --git a/models/player/ignishalfmasked_lod2.iqm.framegroups b/models/player/ignishalfmasked_lod2.iqm.framegroups index 16b3e92c79..6432971bbe 100644 --- a/models/player/ignishalfmasked_lod2.iqm.framegroups +++ b/models/player/ignishalfmasked_lod2.iqm.framegroups @@ -1,23 +1,31 @@ -0 36 15.000000 0 // dieone -36 20 15.000000 0 // dietwo -56 15 15.000000 1 // draw +0 36 30.000000 0 // dieone +36 20 25.000000 0 // dietwo +56 15 30.000000 1 // draw 71 20 15.000000 1 // duck -91 21 30.000000 1 // duckwalk +91 20 32.000000 1 // duckwalk 112 16 15.000000 0 // duckjump -128 15 5.000000 1 // duckidle +128 15 10.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 24.000000 0 // painone +359 17 34.000000 0 // paintwo +376 3 3.000000 0 // shoot +379 21 15.000000 1 // taunt +400 20 29.000000 1 // run +421 20 29.000000 1 // runbackwards +442 20 29.000000 1 // strafeleft +463 20 29.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 20 29.000000 1 // forwardright +509 20 29.000000 1 // forwardleft +530 20 29.000000 1 // backright +551 20 29.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +656 20 32.000000 1 // duckwalkforwardright +677 20 32.000000 1 // duckwalkforwardleft +698 20 32.000000 1 // duckwalkbackright +719 20 32.000000 1 // duckwalkbackleft diff --git a/models/player/ignismasked.iqm b/models/player/ignismasked.iqm index fbf2b00fae..43b17c488c 100644 Binary files a/models/player/ignismasked.iqm and b/models/player/ignismasked.iqm differ diff --git a/models/player/ignismasked.iqm.framegroups b/models/player/ignismasked.iqm.framegroups index 16b3e92c79..6432971bbe 100644 --- a/models/player/ignismasked.iqm.framegroups +++ b/models/player/ignismasked.iqm.framegroups @@ -1,23 +1,31 @@ -0 36 15.000000 0 // dieone -36 20 15.000000 0 // dietwo -56 15 15.000000 1 // draw +0 36 30.000000 0 // dieone +36 20 25.000000 0 // dietwo +56 15 30.000000 1 // draw 71 20 15.000000 1 // duck -91 21 30.000000 1 // duckwalk +91 20 32.000000 1 // duckwalk 112 16 15.000000 0 // duckjump -128 15 5.000000 1 // duckidle +128 15 10.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 24.000000 0 // painone +359 17 34.000000 0 // paintwo +376 3 3.000000 0 // shoot +379 21 15.000000 1 // taunt +400 20 29.000000 1 // run +421 20 29.000000 1 // runbackwards +442 20 29.000000 1 // strafeleft +463 20 29.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 20 29.000000 1 // forwardright +509 20 29.000000 1 // forwardleft +530 20 29.000000 1 // backright +551 20 29.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +656 20 32.000000 1 // duckwalkforwardright +677 20 32.000000 1 // duckwalkforwardleft +698 20 32.000000 1 // duckwalkbackright +719 20 32.000000 1 // duckwalkbackleft diff --git a/models/player/ignismasked_lod1.iqm b/models/player/ignismasked_lod1.iqm index 44633d5146..10e4fc4165 100644 Binary files a/models/player/ignismasked_lod1.iqm and b/models/player/ignismasked_lod1.iqm differ diff --git a/models/player/ignismasked_lod1.iqm.framegroups b/models/player/ignismasked_lod1.iqm.framegroups index 16b3e92c79..6432971bbe 100644 --- a/models/player/ignismasked_lod1.iqm.framegroups +++ b/models/player/ignismasked_lod1.iqm.framegroups @@ -1,23 +1,31 @@ -0 36 15.000000 0 // dieone -36 20 15.000000 0 // dietwo -56 15 15.000000 1 // draw +0 36 30.000000 0 // dieone +36 20 25.000000 0 // dietwo +56 15 30.000000 1 // draw 71 20 15.000000 1 // duck -91 21 30.000000 1 // duckwalk +91 20 32.000000 1 // duckwalk 112 16 15.000000 0 // duckjump -128 15 5.000000 1 // duckidle +128 15 10.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 24.000000 0 // painone +359 17 34.000000 0 // paintwo +376 3 3.000000 0 // shoot +379 21 15.000000 1 // taunt +400 20 29.000000 1 // run +421 20 29.000000 1 // runbackwards +442 20 29.000000 1 // strafeleft +463 20 29.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 20 29.000000 1 // forwardright +509 20 29.000000 1 // forwardleft +530 20 29.000000 1 // backright +551 20 29.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +656 20 32.000000 1 // duckwalkforwardright +677 20 32.000000 1 // duckwalkforwardleft +698 20 32.000000 1 // duckwalkbackright +719 20 32.000000 1 // duckwalkbackleft diff --git a/models/player/ignismasked_lod2.iqm b/models/player/ignismasked_lod2.iqm index a91323112b..823915ed6d 100644 Binary files a/models/player/ignismasked_lod2.iqm and b/models/player/ignismasked_lod2.iqm differ diff --git a/models/player/ignismasked_lod2.iqm.framegroups b/models/player/ignismasked_lod2.iqm.framegroups index 16b3e92c79..6432971bbe 100644 --- a/models/player/ignismasked_lod2.iqm.framegroups +++ b/models/player/ignismasked_lod2.iqm.framegroups @@ -1,23 +1,31 @@ -0 36 15.000000 0 // dieone -36 20 15.000000 0 // dietwo -56 15 15.000000 1 // draw +0 36 30.000000 0 // dieone +36 20 25.000000 0 // dietwo +56 15 30.000000 1 // draw 71 20 15.000000 1 // duck -91 21 30.000000 1 // duckwalk +91 20 32.000000 1 // duckwalk 112 16 15.000000 0 // duckjump -128 15 5.000000 1 // duckidle +128 15 10.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 24.000000 0 // painone +359 17 34.000000 0 // paintwo +376 3 3.000000 0 // shoot +379 21 15.000000 1 // taunt +400 20 29.000000 1 // run +421 20 29.000000 1 // runbackwards +442 20 29.000000 1 // strafeleft +463 20 29.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 20 29.000000 1 // forwardright +509 20 29.000000 1 // forwardleft +530 20 29.000000 1 // backright +551 20 29.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +656 20 32.000000 1 // duckwalkforwardright +677 20 32.000000 1 // duckwalkforwardleft +698 20 32.000000 1 // duckwalkbackright +719 20 32.000000 1 // duckwalkbackleft diff --git a/models/player/megaerebus.iqm b/models/player/megaerebus.iqm new file mode 100644 index 0000000000..5033b64111 Binary files /dev/null and b/models/player/megaerebus.iqm differ diff --git a/models/player/megaerebus.iqm.framegroups b/models/player/megaerebus.iqm.framegroups new file mode 100644 index 0000000000..6432971bbe --- /dev/null +++ b/models/player/megaerebus.iqm.framegroups @@ -0,0 +1,31 @@ +0 36 30.000000 0 // dieone +36 20 25.000000 0 // dietwo +56 15 30.000000 1 // draw +71 20 15.000000 1 // duck +91 20 32.000000 1 // duckwalk +112 16 15.000000 0 // duckjump +128 15 10.000000 1 // duckidle +143 41 5.000000 1 // idle +184 160 25.000000 0 // jump +344 15 24.000000 0 // painone +359 17 34.000000 0 // paintwo +376 3 3.000000 0 // shoot +379 21 15.000000 1 // taunt +400 20 29.000000 1 // run +421 20 29.000000 1 // runbackwards +442 20 29.000000 1 // strafeleft +463 20 29.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 20 29.000000 1 // forwardright +509 20 29.000000 1 // forwardleft +530 20 29.000000 1 // backright +551 20 29.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +656 20 32.000000 1 // duckwalkforwardright +677 20 32.000000 1 // duckwalkforwardleft +698 20 32.000000 1 // duckwalkbackright +719 20 32.000000 1 // duckwalkbackleft diff --git a/models/player/megaerebus.iqm_0.skin b/models/player/megaerebus.iqm_0.skin new file mode 100644 index 0000000000..4597ceff1e --- /dev/null +++ b/models/player/megaerebus.iqm_0.skin @@ -0,0 +1,2 @@ +erebus,erebusfullbright +erebus.001,shadowhead diff --git a/models/player/megaerebus.iqm_0.sounds b/models/player/megaerebus.iqm_0.sounds new file mode 100644 index 0000000000..a97a073b95 --- /dev/null +++ b/models/player/megaerebus.iqm_0.sounds @@ -0,0 +1,32 @@ +//TAG: soldier +//affirmative sound/player/carni-lycan/player/affirmative 0 +attack sound/player/soldier/coms/attack 0 +//attacking sound/player/carni-lycan/player/attacking 0 +attackinfive sound/player/soldier/coms/attackinfive 0 +coverme sound/player/soldier/coms/coverme 0 +defend sound/player/soldier/coms/defend 0 +//defending sound/player/carni-lycan/player/defending 0 +//droppedflag sound/player/carni-lycan/player/droppedflag 0 +flagcarriertakingdamage sound/player/soldier/coms/flagcarriertakingdamage 0 +freelance sound/player/soldier/coms/freelance 2 +getflag sound/player/soldier/coms/getflag 0 +incoming sound/player/soldier/coms/incoming 0 +meet sound/player/soldier/coms/meet 0 +needhelp sound/player/soldier/coms/needhelp 2 +//negative sound/player/carni-lycan/player/negative 0 +//onmyway sound/player/carni-lycan/player/onmyway 0 +//roaming sound/player/carni-lycan/player/roaming 0 +//seenenemy sound/player/carni-lycan/player/seenenemy 0 +seenflag sound/player/soldier/coms/seenflag 0 +taunt sound/player/soldier/coms/taunt 3 +teamshoot sound/player/soldier/coms/teamshoot 3 +death sound/player/soldier/player/death 3 +drown sound/player/soldier/player/drown 0 +fall sound/player/soldier/player/fall 0 +falling sound/player/soldier/player/falling 0 +gasp sound/player/soldier/player/gasp 0 +jump sound/player/soldier/player/jump 0 +pain25 sound/player/soldier/player/pain25 0 +pain50 sound/player/soldier/player/pain50 0 +pain75 sound/player/soldier/player/pain75 0 +pain100 sound/player/soldier/player/pain100 0 diff --git a/models/player/megaerebus.iqm_0.tga b/models/player/megaerebus.iqm_0.tga new file mode 100644 index 0000000000..81649e3d48 Binary files /dev/null and b/models/player/megaerebus.iqm_0.tga differ diff --git a/models/player/megaerebus.iqm_0.txt b/models/player/megaerebus.iqm_0.txt new file mode 100644 index 0000000000..b4e2aa85af --- /dev/null +++ b/models/player/megaerebus.iqm_0.txt @@ -0,0 +1,7 @@ +name Mega Erebus +species human +sex Male +weight 210 +age 26 + +Heavyweight Xonotic Solider diff --git a/models/player/megaerebus_lod1.iqm b/models/player/megaerebus_lod1.iqm new file mode 100644 index 0000000000..3054e6a217 Binary files /dev/null and b/models/player/megaerebus_lod1.iqm differ diff --git a/models/player/megaerebus_lod1.iqm.framegroups b/models/player/megaerebus_lod1.iqm.framegroups new file mode 100644 index 0000000000..6432971bbe --- /dev/null +++ b/models/player/megaerebus_lod1.iqm.framegroups @@ -0,0 +1,31 @@ +0 36 30.000000 0 // dieone +36 20 25.000000 0 // dietwo +56 15 30.000000 1 // draw +71 20 15.000000 1 // duck +91 20 32.000000 1 // duckwalk +112 16 15.000000 0 // duckjump +128 15 10.000000 1 // duckidle +143 41 5.000000 1 // idle +184 160 25.000000 0 // jump +344 15 24.000000 0 // painone +359 17 34.000000 0 // paintwo +376 3 3.000000 0 // shoot +379 21 15.000000 1 // taunt +400 20 29.000000 1 // run +421 20 29.000000 1 // runbackwards +442 20 29.000000 1 // strafeleft +463 20 29.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 20 29.000000 1 // forwardright +509 20 29.000000 1 // forwardleft +530 20 29.000000 1 // backright +551 20 29.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +656 20 32.000000 1 // duckwalkforwardright +677 20 32.000000 1 // duckwalkforwardleft +698 20 32.000000 1 // duckwalkbackright +719 20 32.000000 1 // duckwalkbackleft diff --git a/models/player/megaerebus_lod1.iqm_0.skin b/models/player/megaerebus_lod1.iqm_0.skin new file mode 100644 index 0000000000..4597ceff1e --- /dev/null +++ b/models/player/megaerebus_lod1.iqm_0.skin @@ -0,0 +1,2 @@ +erebus,erebusfullbright +erebus.001,shadowhead diff --git a/models/player/megaerebus_lod2.iqm b/models/player/megaerebus_lod2.iqm new file mode 100644 index 0000000000..70d59851de Binary files /dev/null and b/models/player/megaerebus_lod2.iqm differ diff --git a/models/player/megaerebus_lod2.iqm.framegroups b/models/player/megaerebus_lod2.iqm.framegroups new file mode 100644 index 0000000000..6432971bbe --- /dev/null +++ b/models/player/megaerebus_lod2.iqm.framegroups @@ -0,0 +1,31 @@ +0 36 30.000000 0 // dieone +36 20 25.000000 0 // dietwo +56 15 30.000000 1 // draw +71 20 15.000000 1 // duck +91 20 32.000000 1 // duckwalk +112 16 15.000000 0 // duckjump +128 15 10.000000 1 // duckidle +143 41 5.000000 1 // idle +184 160 25.000000 0 // jump +344 15 24.000000 0 // painone +359 17 34.000000 0 // paintwo +376 3 3.000000 0 // shoot +379 21 15.000000 1 // taunt +400 20 29.000000 1 // run +421 20 29.000000 1 // runbackwards +442 20 29.000000 1 // strafeleft +463 20 29.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 20 29.000000 1 // forwardright +509 20 29.000000 1 // forwardleft +530 20 29.000000 1 // backright +551 20 29.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +656 20 32.000000 1 // duckwalkforwardright +677 20 32.000000 1 // duckwalkforwardleft +698 20 32.000000 1 // duckwalkbackright +719 20 32.000000 1 // duckwalkbackleft diff --git a/models/player/megaerebus_lod2.iqm_0.skin b/models/player/megaerebus_lod2.iqm_0.skin new file mode 100644 index 0000000000..4597ceff1e --- /dev/null +++ b/models/player/megaerebus_lod2.iqm_0.skin @@ -0,0 +1,2 @@ +erebus,erebusfullbright +erebus.001,shadowhead diff --git a/models/player/nyx.iqm b/models/player/nyx.iqm index 505fcb9f19..5e2217836e 100644 Binary files a/models/player/nyx.iqm and b/models/player/nyx.iqm differ diff --git a/models/player/nyx.iqm.framegroups b/models/player/nyx.iqm.framegroups index 16b3e92c79..70edc357e6 100644 --- a/models/player/nyx.iqm.framegroups +++ b/models/player/nyx.iqm.framegroups @@ -2,22 +2,30 @@ 36 20 15.000000 0 // dietwo 56 15 15.000000 1 // draw 71 20 15.000000 1 // duck -91 21 30.000000 1 // duckwalk +91 20 32.000000 1 // duckwalk 112 16 15.000000 0 // duckjump -128 15 5.000000 1 // duckidle +128 15 8.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 15.000000 0 // painone +359 17 15.000000 0 // paintwo +376 3 15.000000 0 // shoot +379 21 15.000000 1 // taunt +400 21 35.000000 1 // run +421 21 35.000000 1 // runbackwards +442 21 35.000000 1 // strafeleft +463 21 35.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 21 35.000000 1 // forwardright +509 21 35.000000 1 // forwardleft +530 21 35.000000 1 // backright +551 21 30.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +91 20 32.000000 1 // duckwalkforwardright +91 20 32.000000 1 // duckwalkforwardleft +593 20 32.000000 1 // duckwalkbackright +593 20 32.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/nyx_lod1.iqm b/models/player/nyx_lod1.iqm new file mode 100644 index 0000000000..c7561d985c Binary files /dev/null and b/models/player/nyx_lod1.iqm differ diff --git a/models/player/nyx_lod1.iqm.framegroups b/models/player/nyx_lod1.iqm.framegroups new file mode 100644 index 0000000000..70edc357e6 --- /dev/null +++ b/models/player/nyx_lod1.iqm.framegroups @@ -0,0 +1,31 @@ +0 36 15.000000 0 // dieone +36 20 15.000000 0 // dietwo +56 15 15.000000 1 // draw +71 20 15.000000 1 // duck +91 20 32.000000 1 // duckwalk +112 16 15.000000 0 // duckjump +128 15 8.000000 1 // duckidle +143 41 5.000000 1 // idle +184 160 25.000000 0 // jump +344 15 15.000000 0 // painone +359 17 15.000000 0 // paintwo +376 3 15.000000 0 // shoot +379 21 15.000000 1 // taunt +400 21 35.000000 1 // run +421 21 35.000000 1 // runbackwards +442 21 35.000000 1 // strafeleft +463 21 35.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 21 35.000000 1 // forwardright +509 21 35.000000 1 // forwardleft +530 21 35.000000 1 // backright +551 21 30.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +91 20 32.000000 1 // duckwalkforwardright +91 20 32.000000 1 // duckwalkforwardleft +593 20 32.000000 1 // duckwalkbackright +593 20 32.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/nyx_lod2.iqm b/models/player/nyx_lod2.iqm new file mode 100644 index 0000000000..5a67b35562 Binary files /dev/null and b/models/player/nyx_lod2.iqm differ diff --git a/models/player/nyx_lod2.iqm.framegroups b/models/player/nyx_lod2.iqm.framegroups new file mode 100644 index 0000000000..70edc357e6 --- /dev/null +++ b/models/player/nyx_lod2.iqm.framegroups @@ -0,0 +1,31 @@ +0 36 15.000000 0 // dieone +36 20 15.000000 0 // dietwo +56 15 15.000000 1 // draw +71 20 15.000000 1 // duck +91 20 32.000000 1 // duckwalk +112 16 15.000000 0 // duckjump +128 15 8.000000 1 // duckidle +143 41 5.000000 1 // idle +184 160 25.000000 0 // jump +344 15 15.000000 0 // painone +359 17 15.000000 0 // paintwo +376 3 15.000000 0 // shoot +379 21 15.000000 1 // taunt +400 21 35.000000 1 // run +421 21 35.000000 1 // runbackwards +442 21 35.000000 1 // strafeleft +463 21 35.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 21 35.000000 1 // forwardright +509 21 35.000000 1 // forwardleft +530 21 35.000000 1 // backright +551 21 30.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +91 20 32.000000 1 // duckwalkforwardright +91 20 32.000000 1 // duckwalkforwardleft +593 20 32.000000 1 // duckwalkbackright +593 20 32.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/pyria.iqm b/models/player/pyria.iqm index ef2ef05092..c8c47c0599 100644 Binary files a/models/player/pyria.iqm and b/models/player/pyria.iqm differ diff --git a/models/player/pyria.iqm.framegroups b/models/player/pyria.iqm.framegroups index a257a2469e..73cd958b0c 100644 --- a/models/player/pyria.iqm.framegroups +++ b/models/player/pyria.iqm.framegroups @@ -6,18 +6,26 @@ 109 16 15.000000 0 // duckjump 125 15 5.000000 1 // duckidle 140 16 5.000000 1 // idle -156 16 15.000000 0 // jump -172 15 15.000000 0 // painone -187 17 15.000000 0 // paintwo -204 5 15.000000 0 // shoot -209 21 15.000000 1 // taunt -230 21 40.000000 1 // run -251 21 40.000000 1 // runbackwards -272 21 40.000000 1 // strafeleft -293 21 40.000000 1 // straferight -314 2 15.000000 0 // deadone -316 2 15.000000 0 // deadtwo -318 21 40.000000 1 // forwardright -339 21 40.000000 1 // forwardleft -360 21 40.000000 1 // backright -381 21 40.000000 1 // backleft +156 160 25.000000 0 // jump +316 15 15.000000 0 // painone +331 17 15.000000 0 // paintwo +348 5 15.000000 0 // shoot +353 21 15.000000 1 // taunt +374 21 40.000000 1 // run +395 21 40.000000 1 // runbackwards +416 21 40.000000 1 // strafeleft +437 21 40.000000 1 // straferight +458 2 15.000000 0 // deadone +460 2 15.000000 0 // deadtwo +462 21 40.000000 1 // forwardright +483 21 40.000000 1 // forwardleft +504 21 40.000000 1 // backright +525 21 40.000000 1 // backleft +546 21 20.000000 0 // melee +567 11 15.000000 1 // duckwalkbackwards +98 11 15.000000 1 // duckwalkstrafeleft +98 11 15.000000 1 // duckwalkstraferight +98 11 15.000000 1 // duckwalkforwardright +98 11 15.000000 1 // duckwalkforwardleft +567 11 15.000000 1 // duckwalkbackright +567 11 15.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/pyria_lod1.iqm b/models/player/pyria_lod1.iqm new file mode 100644 index 0000000000..590b7faa96 Binary files /dev/null and b/models/player/pyria_lod1.iqm differ diff --git a/models/player/pyria_lod1.iqm.framegroups b/models/player/pyria_lod1.iqm.framegroups new file mode 100644 index 0000000000..73cd958b0c --- /dev/null +++ b/models/player/pyria_lod1.iqm.framegroups @@ -0,0 +1,31 @@ +0 36 20.000000 0 // dieone +36 27 20.000000 0 // dietwo +63 15 15.000000 1 // draw +78 20 15.000000 1 // duck +98 11 15.000000 1 // duckwalk +109 16 15.000000 0 // duckjump +125 15 5.000000 1 // duckidle +140 16 5.000000 1 // idle +156 160 25.000000 0 // jump +316 15 15.000000 0 // painone +331 17 15.000000 0 // paintwo +348 5 15.000000 0 // shoot +353 21 15.000000 1 // taunt +374 21 40.000000 1 // run +395 21 40.000000 1 // runbackwards +416 21 40.000000 1 // strafeleft +437 21 40.000000 1 // straferight +458 2 15.000000 0 // deadone +460 2 15.000000 0 // deadtwo +462 21 40.000000 1 // forwardright +483 21 40.000000 1 // forwardleft +504 21 40.000000 1 // backright +525 21 40.000000 1 // backleft +546 21 20.000000 0 // melee +567 11 15.000000 1 // duckwalkbackwards +98 11 15.000000 1 // duckwalkstrafeleft +98 11 15.000000 1 // duckwalkstraferight +98 11 15.000000 1 // duckwalkforwardright +98 11 15.000000 1 // duckwalkforwardleft +567 11 15.000000 1 // duckwalkbackright +567 11 15.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/pyria_lod2.iqm b/models/player/pyria_lod2.iqm new file mode 100644 index 0000000000..4d93562028 Binary files /dev/null and b/models/player/pyria_lod2.iqm differ diff --git a/models/player/pyria_lod2.iqm.framegroups b/models/player/pyria_lod2.iqm.framegroups new file mode 100644 index 0000000000..73cd958b0c --- /dev/null +++ b/models/player/pyria_lod2.iqm.framegroups @@ -0,0 +1,31 @@ +0 36 20.000000 0 // dieone +36 27 20.000000 0 // dietwo +63 15 15.000000 1 // draw +78 20 15.000000 1 // duck +98 11 15.000000 1 // duckwalk +109 16 15.000000 0 // duckjump +125 15 5.000000 1 // duckidle +140 16 5.000000 1 // idle +156 160 25.000000 0 // jump +316 15 15.000000 0 // painone +331 17 15.000000 0 // paintwo +348 5 15.000000 0 // shoot +353 21 15.000000 1 // taunt +374 21 40.000000 1 // run +395 21 40.000000 1 // runbackwards +416 21 40.000000 1 // strafeleft +437 21 40.000000 1 // straferight +458 2 15.000000 0 // deadone +460 2 15.000000 0 // deadtwo +462 21 40.000000 1 // forwardright +483 21 40.000000 1 // forwardleft +504 21 40.000000 1 // backright +525 21 40.000000 1 // backleft +546 21 20.000000 0 // melee +567 11 15.000000 1 // duckwalkbackwards +98 11 15.000000 1 // duckwalkstrafeleft +98 11 15.000000 1 // duckwalkstraferight +98 11 15.000000 1 // duckwalkforwardright +98 11 15.000000 1 // duckwalkforwardleft +567 11 15.000000 1 // duckwalkbackright +567 11 15.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/seraphina.iqm b/models/player/seraphina.iqm index 7e6dbc224a..66f54687ec 100644 Binary files a/models/player/seraphina.iqm and b/models/player/seraphina.iqm differ diff --git a/models/player/seraphina.iqm.framegroups b/models/player/seraphina.iqm.framegroups index 16b3e92c79..70edc357e6 100644 --- a/models/player/seraphina.iqm.framegroups +++ b/models/player/seraphina.iqm.framegroups @@ -2,22 +2,30 @@ 36 20 15.000000 0 // dietwo 56 15 15.000000 1 // draw 71 20 15.000000 1 // duck -91 21 30.000000 1 // duckwalk +91 20 32.000000 1 // duckwalk 112 16 15.000000 0 // duckjump -128 15 5.000000 1 // duckidle +128 15 8.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 15.000000 0 // painone +359 17 15.000000 0 // paintwo +376 3 15.000000 0 // shoot +379 21 15.000000 1 // taunt +400 21 35.000000 1 // run +421 21 35.000000 1 // runbackwards +442 21 35.000000 1 // strafeleft +463 21 35.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 21 35.000000 1 // forwardright +509 21 35.000000 1 // forwardleft +530 21 35.000000 1 // backright +551 21 30.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +91 20 32.000000 1 // duckwalkforwardright +91 20 32.000000 1 // duckwalkforwardleft +593 20 32.000000 1 // duckwalkbackright +593 20 32.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/seraphina_lod1.iqm b/models/player/seraphina_lod1.iqm index d16f225276..5faffe632c 100644 Binary files a/models/player/seraphina_lod1.iqm and b/models/player/seraphina_lod1.iqm differ diff --git a/models/player/seraphina_lod1.iqm.framegroups b/models/player/seraphina_lod1.iqm.framegroups index 16b3e92c79..70edc357e6 100644 --- a/models/player/seraphina_lod1.iqm.framegroups +++ b/models/player/seraphina_lod1.iqm.framegroups @@ -2,22 +2,30 @@ 36 20 15.000000 0 // dietwo 56 15 15.000000 1 // draw 71 20 15.000000 1 // duck -91 21 30.000000 1 // duckwalk +91 20 32.000000 1 // duckwalk 112 16 15.000000 0 // duckjump -128 15 5.000000 1 // duckidle +128 15 8.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 15.000000 0 // painone +359 17 15.000000 0 // paintwo +376 3 15.000000 0 // shoot +379 21 15.000000 1 // taunt +400 21 35.000000 1 // run +421 21 35.000000 1 // runbackwards +442 21 35.000000 1 // strafeleft +463 21 35.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 21 35.000000 1 // forwardright +509 21 35.000000 1 // forwardleft +530 21 35.000000 1 // backright +551 21 30.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +91 20 32.000000 1 // duckwalkforwardright +91 20 32.000000 1 // duckwalkforwardleft +593 20 32.000000 1 // duckwalkbackright +593 20 32.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/seraphina_lod2.iqm b/models/player/seraphina_lod2.iqm index f6ca53a0d1..f880197c6c 100644 Binary files a/models/player/seraphina_lod2.iqm and b/models/player/seraphina_lod2.iqm differ diff --git a/models/player/seraphina_lod2.iqm.framegroups b/models/player/seraphina_lod2.iqm.framegroups index 16b3e92c79..70edc357e6 100644 --- a/models/player/seraphina_lod2.iqm.framegroups +++ b/models/player/seraphina_lod2.iqm.framegroups @@ -2,22 +2,30 @@ 36 20 15.000000 0 // dietwo 56 15 15.000000 1 // draw 71 20 15.000000 1 // duck -91 21 30.000000 1 // duckwalk +91 20 32.000000 1 // duckwalk 112 16 15.000000 0 // duckjump -128 15 5.000000 1 // duckidle +128 15 8.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 15.000000 0 // painone +359 17 15.000000 0 // paintwo +376 3 15.000000 0 // shoot +379 21 15.000000 1 // taunt +400 21 35.000000 1 // run +421 21 35.000000 1 // runbackwards +442 21 35.000000 1 // strafeleft +463 21 35.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 21 35.000000 1 // forwardright +509 21 35.000000 1 // forwardleft +530 21 35.000000 1 // backright +551 21 30.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +91 20 32.000000 1 // duckwalkforwardright +91 20 32.000000 1 // duckwalkforwardleft +593 20 32.000000 1 // duckwalkbackright +593 20 32.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/seraphinamasked.iqm b/models/player/seraphinamasked.iqm index f65dce6f0a..47f243d91d 100644 Binary files a/models/player/seraphinamasked.iqm and b/models/player/seraphinamasked.iqm differ diff --git a/models/player/seraphinamasked.iqm.framegroups b/models/player/seraphinamasked.iqm.framegroups index 16b3e92c79..70edc357e6 100644 --- a/models/player/seraphinamasked.iqm.framegroups +++ b/models/player/seraphinamasked.iqm.framegroups @@ -2,22 +2,30 @@ 36 20 15.000000 0 // dietwo 56 15 15.000000 1 // draw 71 20 15.000000 1 // duck -91 21 30.000000 1 // duckwalk +91 20 32.000000 1 // duckwalk 112 16 15.000000 0 // duckjump -128 15 5.000000 1 // duckidle +128 15 8.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 15.000000 0 // painone +359 17 15.000000 0 // paintwo +376 3 15.000000 0 // shoot +379 21 15.000000 1 // taunt +400 21 35.000000 1 // run +421 21 35.000000 1 // runbackwards +442 21 35.000000 1 // strafeleft +463 21 35.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 21 35.000000 1 // forwardright +509 21 35.000000 1 // forwardleft +530 21 35.000000 1 // backright +551 21 30.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +91 20 32.000000 1 // duckwalkforwardright +91 20 32.000000 1 // duckwalkforwardleft +593 20 32.000000 1 // duckwalkbackright +593 20 32.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/seraphinamasked_lod1.iqm b/models/player/seraphinamasked_lod1.iqm index 5a9952430f..d8e40ab7f6 100644 Binary files a/models/player/seraphinamasked_lod1.iqm and b/models/player/seraphinamasked_lod1.iqm differ diff --git a/models/player/seraphinamasked_lod1.iqm.framegroups b/models/player/seraphinamasked_lod1.iqm.framegroups index 16b3e92c79..70edc357e6 100644 --- a/models/player/seraphinamasked_lod1.iqm.framegroups +++ b/models/player/seraphinamasked_lod1.iqm.framegroups @@ -2,22 +2,30 @@ 36 20 15.000000 0 // dietwo 56 15 15.000000 1 // draw 71 20 15.000000 1 // duck -91 21 30.000000 1 // duckwalk +91 20 32.000000 1 // duckwalk 112 16 15.000000 0 // duckjump -128 15 5.000000 1 // duckidle +128 15 8.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 15.000000 0 // painone +359 17 15.000000 0 // paintwo +376 3 15.000000 0 // shoot +379 21 15.000000 1 // taunt +400 21 35.000000 1 // run +421 21 35.000000 1 // runbackwards +442 21 35.000000 1 // strafeleft +463 21 35.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 21 35.000000 1 // forwardright +509 21 35.000000 1 // forwardleft +530 21 35.000000 1 // backright +551 21 30.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +91 20 32.000000 1 // duckwalkforwardright +91 20 32.000000 1 // duckwalkforwardleft +593 20 32.000000 1 // duckwalkbackright +593 20 32.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/seraphinamasked_lod2.iqm b/models/player/seraphinamasked_lod2.iqm index 927d56ce82..acad8aa1f0 100644 Binary files a/models/player/seraphinamasked_lod2.iqm and b/models/player/seraphinamasked_lod2.iqm differ diff --git a/models/player/seraphinamasked_lod2.iqm.framegroups b/models/player/seraphinamasked_lod2.iqm.framegroups index 16b3e92c79..70edc357e6 100644 --- a/models/player/seraphinamasked_lod2.iqm.framegroups +++ b/models/player/seraphinamasked_lod2.iqm.framegroups @@ -2,22 +2,30 @@ 36 20 15.000000 0 // dietwo 56 15 15.000000 1 // draw 71 20 15.000000 1 // duck -91 21 30.000000 1 // duckwalk +91 20 32.000000 1 // duckwalk 112 16 15.000000 0 // duckjump -128 15 5.000000 1 // duckidle +128 15 8.000000 1 // duckidle 143 41 5.000000 1 // idle -184 21 25.000000 0 // jump -205 15 15.000000 0 // painone -220 17 15.000000 0 // paintwo -237 3 15.000000 0 // shoot -240 21 15.000000 1 // taunt -261 21 35.000000 1 // run -282 21 35.000000 1 // runbackwards -303 21 35.000000 1 // strafeleft -324 21 35.000000 1 // straferight -345 2 15.000000 0 // deadone -347 2 15.000000 0 // deadtwo -349 21 35.000000 1 // forwardright -370 21 35.000000 1 // forwardleft -391 21 35.000000 1 // backright -412 21 30.000000 1 // backleft +184 160 25.000000 0 // jump +344 15 15.000000 0 // painone +359 17 15.000000 0 // paintwo +376 3 15.000000 0 // shoot +379 21 15.000000 1 // taunt +400 21 35.000000 1 // run +421 21 35.000000 1 // runbackwards +442 21 35.000000 1 // strafeleft +463 21 35.000000 1 // straferight +484 2 15.000000 0 // deadone +486 2 15.000000 0 // deadtwo +488 21 35.000000 1 // forwardright +509 21 35.000000 1 // forwardleft +530 21 35.000000 1 // backright +551 21 30.000000 1 // backleft +572 21 20.000000 0 // melee +593 20 32.000000 1 // duckwalkbackwards +614 20 32.000000 1 // duckwalkstrafeleft +635 20 32.000000 1 // duckwalkstraferight +91 20 32.000000 1 // duckwalkforwardright +91 20 32.000000 1 // duckwalkforwardleft +593 20 32.000000 1 // duckwalkbackright +593 20 32.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/umbra.iqm b/models/player/umbra.iqm index f43ad6778e..17ce3dd099 100644 Binary files a/models/player/umbra.iqm and b/models/player/umbra.iqm differ diff --git a/models/player/umbra.iqm.framegroups b/models/player/umbra.iqm.framegroups index a257a2469e..73cd958b0c 100644 --- a/models/player/umbra.iqm.framegroups +++ b/models/player/umbra.iqm.framegroups @@ -6,18 +6,26 @@ 109 16 15.000000 0 // duckjump 125 15 5.000000 1 // duckidle 140 16 5.000000 1 // idle -156 16 15.000000 0 // jump -172 15 15.000000 0 // painone -187 17 15.000000 0 // paintwo -204 5 15.000000 0 // shoot -209 21 15.000000 1 // taunt -230 21 40.000000 1 // run -251 21 40.000000 1 // runbackwards -272 21 40.000000 1 // strafeleft -293 21 40.000000 1 // straferight -314 2 15.000000 0 // deadone -316 2 15.000000 0 // deadtwo -318 21 40.000000 1 // forwardright -339 21 40.000000 1 // forwardleft -360 21 40.000000 1 // backright -381 21 40.000000 1 // backleft +156 160 25.000000 0 // jump +316 15 15.000000 0 // painone +331 17 15.000000 0 // paintwo +348 5 15.000000 0 // shoot +353 21 15.000000 1 // taunt +374 21 40.000000 1 // run +395 21 40.000000 1 // runbackwards +416 21 40.000000 1 // strafeleft +437 21 40.000000 1 // straferight +458 2 15.000000 0 // deadone +460 2 15.000000 0 // deadtwo +462 21 40.000000 1 // forwardright +483 21 40.000000 1 // forwardleft +504 21 40.000000 1 // backright +525 21 40.000000 1 // backleft +546 21 20.000000 0 // melee +567 11 15.000000 1 // duckwalkbackwards +98 11 15.000000 1 // duckwalkstrafeleft +98 11 15.000000 1 // duckwalkstraferight +98 11 15.000000 1 // duckwalkforwardright +98 11 15.000000 1 // duckwalkforwardleft +567 11 15.000000 1 // duckwalkbackright +567 11 15.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/umbra_lod1.iqm b/models/player/umbra_lod1.iqm new file mode 100644 index 0000000000..281f949da0 Binary files /dev/null and b/models/player/umbra_lod1.iqm differ diff --git a/models/player/umbra_lod1.iqm.framegroups b/models/player/umbra_lod1.iqm.framegroups new file mode 100644 index 0000000000..73cd958b0c --- /dev/null +++ b/models/player/umbra_lod1.iqm.framegroups @@ -0,0 +1,31 @@ +0 36 20.000000 0 // dieone +36 27 20.000000 0 // dietwo +63 15 15.000000 1 // draw +78 20 15.000000 1 // duck +98 11 15.000000 1 // duckwalk +109 16 15.000000 0 // duckjump +125 15 5.000000 1 // duckidle +140 16 5.000000 1 // idle +156 160 25.000000 0 // jump +316 15 15.000000 0 // painone +331 17 15.000000 0 // paintwo +348 5 15.000000 0 // shoot +353 21 15.000000 1 // taunt +374 21 40.000000 1 // run +395 21 40.000000 1 // runbackwards +416 21 40.000000 1 // strafeleft +437 21 40.000000 1 // straferight +458 2 15.000000 0 // deadone +460 2 15.000000 0 // deadtwo +462 21 40.000000 1 // forwardright +483 21 40.000000 1 // forwardleft +504 21 40.000000 1 // backright +525 21 40.000000 1 // backleft +546 21 20.000000 0 // melee +567 11 15.000000 1 // duckwalkbackwards +98 11 15.000000 1 // duckwalkstrafeleft +98 11 15.000000 1 // duckwalkstraferight +98 11 15.000000 1 // duckwalkforwardright +98 11 15.000000 1 // duckwalkforwardleft +567 11 15.000000 1 // duckwalkbackright +567 11 15.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/player/umbra_lod2.iqm b/models/player/umbra_lod2.iqm new file mode 100644 index 0000000000..e90367714e Binary files /dev/null and b/models/player/umbra_lod2.iqm differ diff --git a/models/player/umbra_lod2.iqm.framegroups b/models/player/umbra_lod2.iqm.framegroups new file mode 100644 index 0000000000..73cd958b0c --- /dev/null +++ b/models/player/umbra_lod2.iqm.framegroups @@ -0,0 +1,31 @@ +0 36 20.000000 0 // dieone +36 27 20.000000 0 // dietwo +63 15 15.000000 1 // draw +78 20 15.000000 1 // duck +98 11 15.000000 1 // duckwalk +109 16 15.000000 0 // duckjump +125 15 5.000000 1 // duckidle +140 16 5.000000 1 // idle +156 160 25.000000 0 // jump +316 15 15.000000 0 // painone +331 17 15.000000 0 // paintwo +348 5 15.000000 0 // shoot +353 21 15.000000 1 // taunt +374 21 40.000000 1 // run +395 21 40.000000 1 // runbackwards +416 21 40.000000 1 // strafeleft +437 21 40.000000 1 // straferight +458 2 15.000000 0 // deadone +460 2 15.000000 0 // deadtwo +462 21 40.000000 1 // forwardright +483 21 40.000000 1 // forwardleft +504 21 40.000000 1 // backright +525 21 40.000000 1 // backleft +546 21 20.000000 0 // melee +567 11 15.000000 1 // duckwalkbackwards +98 11 15.000000 1 // duckwalkstrafeleft +98 11 15.000000 1 // duckwalkstraferight +98 11 15.000000 1 // duckwalkforwardright +98 11 15.000000 1 // duckwalkforwardleft +567 11 15.000000 1 // duckwalkbackright +567 11 15.000000 1 // duckwalkbackleft \ No newline at end of file diff --git a/models/relics/relic.md3 b/models/relics/relic.md3 new file mode 100644 index 0000000000..7e65e4c3cb Binary files /dev/null and b/models/relics/relic.md3 differ diff --git a/models/relics/relic.md3.framegroups b/models/relics/relic.md3.framegroups new file mode 100644 index 0000000000..4e33f6f0df --- /dev/null +++ b/models/relics/relic.md3.framegroups @@ -0,0 +1 @@ +0 99 30 1 \ No newline at end of file diff --git a/models/relics/relic.md3_0.skin b/models/relics/relic.md3_0.skin new file mode 100644 index 0000000000..f4d914fa28 --- /dev/null +++ b/models/relics/relic.md3_0.skin @@ -0,0 +1,3 @@ +ring,models/relics/relic_ring +mesh,models/relics/relic +sign,models/relics/sign_resistance \ No newline at end of file diff --git a/models/relics/relic.md3_1.skin b/models/relics/relic.md3_1.skin new file mode 100644 index 0000000000..f391db0884 --- /dev/null +++ b/models/relics/relic.md3_1.skin @@ -0,0 +1,3 @@ +ring,models/relics/relic_ring +mesh,models/relics/relic +sign,models/relics/sign_regeneration \ No newline at end of file diff --git a/models/relics/relic.md3_10.skin b/models/relics/relic.md3_10.skin new file mode 100644 index 0000000000..8276637c08 --- /dev/null +++ b/models/relics/relic.md3_10.skin @@ -0,0 +1,3 @@ +ring,models/relics/relic_ring +mesh,models/relics/relic +sign,models/relics/sign_jump \ No newline at end of file diff --git a/models/relics/relic.md3_11.skin b/models/relics/relic.md3_11.skin new file mode 100644 index 0000000000..4b88dde045 --- /dev/null +++ b/models/relics/relic.md3_11.skin @@ -0,0 +1,3 @@ +ring,models/relics/relic_ring +mesh,models/relics/relic +sign,models/relics/sign_flight \ No newline at end of file diff --git a/models/relics/relic.md3_12.skin b/models/relics/relic.md3_12.skin new file mode 100644 index 0000000000..9f2525884d --- /dev/null +++ b/models/relics/relic.md3_12.skin @@ -0,0 +1,3 @@ +ring,models/relics/relic_ring +mesh,models/relics/relic +sign,models/relics/sign_invisible \ No newline at end of file diff --git a/models/relics/relic.md3_13.skin b/models/relics/relic.md3_13.skin new file mode 100644 index 0000000000..8fb743571b --- /dev/null +++ b/models/relics/relic.md3_13.skin @@ -0,0 +1,3 @@ +ring,models/relics/relic_ring +mesh,models/relics/relic +sign,models/relics/sign_radioactive \ No newline at end of file diff --git a/models/relics/relic.md3_14.skin b/models/relics/relic.md3_14.skin new file mode 100644 index 0000000000..c6efd38ccf --- /dev/null +++ b/models/relics/relic.md3_14.skin @@ -0,0 +1,3 @@ +ring,models/relics/relic_ring +mesh,models/relics/relic +sign,models/relics/sign_resurrection \ No newline at end of file diff --git a/models/relics/relic.md3_15.skin b/models/relics/relic.md3_15.skin new file mode 100644 index 0000000000..5b188bebc2 --- /dev/null +++ b/models/relics/relic.md3_15.skin @@ -0,0 +1,3 @@ +ring,models/relics/relic_ring +mesh,models/relics/relic +sign,models/relics/sign_vengeance \ No newline at end of file diff --git a/models/relics/relic.md3_2.skin b/models/relics/relic.md3_2.skin new file mode 100644 index 0000000000..299176685f --- /dev/null +++ b/models/relics/relic.md3_2.skin @@ -0,0 +1,3 @@ +ring,models/relics/relic_ring +mesh,models/relics/relic +sign,models/relics/sign_vampire \ No newline at end of file diff --git a/models/relics/relic.md3_3.skin b/models/relics/relic.md3_3.skin new file mode 100644 index 0000000000..5a2a694c51 --- /dev/null +++ b/models/relics/relic.md3_3.skin @@ -0,0 +1,3 @@ +ring,models/relics/relic_ring +mesh,models/relics/relic +sign,models/relics/sign_ammo \ No newline at end of file diff --git a/models/relics/relic.md3_4.skin b/models/relics/relic.md3_4.skin new file mode 100644 index 0000000000..d9c45c3223 --- /dev/null +++ b/models/relics/relic.md3_4.skin @@ -0,0 +1,3 @@ +ring,models/relics/relic_ring +mesh,models/relics/relic +sign,models/relics/sign_damage \ No newline at end of file diff --git a/models/relics/relic.md3_5.skin b/models/relics/relic.md3_5.skin new file mode 100644 index 0000000000..a74c20f038 --- /dev/null +++ b/models/relics/relic.md3_5.skin @@ -0,0 +1,3 @@ +ring,models/relics/relic_ring +mesh,models/relics/relic +sign,models/relics/sign_splashdamage \ No newline at end of file diff --git a/models/relics/relic.md3_6.skin b/models/relics/relic.md3_6.skin new file mode 100644 index 0000000000..5ebfd3feda --- /dev/null +++ b/models/relics/relic.md3_6.skin @@ -0,0 +1,3 @@ +ring,models/relics/relic_ring +mesh,models/relics/relic +sign,models/relics/sign_firingspeed \ No newline at end of file diff --git a/models/relics/relic.md3_7.skin b/models/relics/relic.md3_7.skin new file mode 100644 index 0000000000..ce6fb9f415 --- /dev/null +++ b/models/relics/relic.md3_7.skin @@ -0,0 +1,3 @@ +ring,models/relics/relic_ring +mesh,models/relics/relic +sign,models/relics/sign_disability \ No newline at end of file diff --git a/models/relics/relic.md3_8.skin b/models/relics/relic.md3_8.skin new file mode 100644 index 0000000000..2381a4cab3 --- /dev/null +++ b/models/relics/relic.md3_8.skin @@ -0,0 +1,3 @@ +ring,models/relics/relic_ring +mesh,models/relics/relic +sign,models/relics/sign_teamboost \ No newline at end of file diff --git a/models/relics/relic.md3_9.skin b/models/relics/relic.md3_9.skin new file mode 100644 index 0000000000..3358e23f74 --- /dev/null +++ b/models/relics/relic.md3_9.skin @@ -0,0 +1,3 @@ +ring,models/relics/relic_ring +mesh,models/relics/relic +sign,models/relics/sign_speed \ No newline at end of file diff --git a/models/relics/relic.tga b/models/relics/relic.tga new file mode 100644 index 0000000000..be9b7470eb Binary files /dev/null and b/models/relics/relic.tga differ diff --git a/models/relics/relic_gloss.tga b/models/relics/relic_gloss.tga new file mode 100644 index 0000000000..975cd2dd65 Binary files /dev/null and b/models/relics/relic_gloss.tga differ diff --git a/models/relics/relic_glow.tga b/models/relics/relic_glow.tga new file mode 100644 index 0000000000..aba79cf230 Binary files /dev/null and b/models/relics/relic_glow.tga differ diff --git a/models/relics/relic_norm.tga b/models/relics/relic_norm.tga new file mode 100644 index 0000000000..5712ac4cae Binary files /dev/null and b/models/relics/relic_norm.tga differ diff --git a/models/relics/relic_reflect.tga b/models/relics/relic_reflect.tga new file mode 100644 index 0000000000..eb867b54af Binary files /dev/null and b/models/relics/relic_reflect.tga differ diff --git a/models/relics/relic_ring.tga b/models/relics/relic_ring.tga new file mode 100644 index 0000000000..612c819c3a Binary files /dev/null and b/models/relics/relic_ring.tga differ diff --git a/models/relics/relic_ring_glow.tga b/models/relics/relic_ring_glow.tga new file mode 100644 index 0000000000..4c30f89db1 Binary files /dev/null and b/models/relics/relic_ring_glow.tga differ diff --git a/models/relics/sign_ammo.tga b/models/relics/sign_ammo.tga new file mode 100644 index 0000000000..b6227f6327 Binary files /dev/null and b/models/relics/sign_ammo.tga differ diff --git a/models/relics/sign_ammo_glow.tga b/models/relics/sign_ammo_glow.tga new file mode 100644 index 0000000000..8849e924c7 Binary files /dev/null and b/models/relics/sign_ammo_glow.tga differ diff --git a/models/relics/sign_damage.tga b/models/relics/sign_damage.tga new file mode 100644 index 0000000000..a5658aa3f6 Binary files /dev/null and b/models/relics/sign_damage.tga differ diff --git a/models/relics/sign_damage_glow.tga b/models/relics/sign_damage_glow.tga new file mode 100644 index 0000000000..b595139cd0 Binary files /dev/null and b/models/relics/sign_damage_glow.tga differ diff --git a/models/relics/sign_disability.tga b/models/relics/sign_disability.tga new file mode 100644 index 0000000000..e858a8a1af Binary files /dev/null and b/models/relics/sign_disability.tga differ diff --git a/models/relics/sign_disability_glow.tga b/models/relics/sign_disability_glow.tga new file mode 100644 index 0000000000..e858a8a1af Binary files /dev/null and b/models/relics/sign_disability_glow.tga differ diff --git a/models/relics/sign_firingspeed.tga b/models/relics/sign_firingspeed.tga new file mode 100644 index 0000000000..5d975bcecf Binary files /dev/null and b/models/relics/sign_firingspeed.tga differ diff --git a/models/relics/sign_firingspeed_glow.tga b/models/relics/sign_firingspeed_glow.tga new file mode 100644 index 0000000000..61e24b58ab Binary files /dev/null and b/models/relics/sign_firingspeed_glow.tga differ diff --git a/models/relics/sign_flight.tga b/models/relics/sign_flight.tga new file mode 100644 index 0000000000..790bfe17e6 Binary files /dev/null and b/models/relics/sign_flight.tga differ diff --git a/models/relics/sign_flight_glow.tga b/models/relics/sign_flight_glow.tga new file mode 100644 index 0000000000..b3f45a927b Binary files /dev/null and b/models/relics/sign_flight_glow.tga differ diff --git a/models/relics/sign_invisible.tga b/models/relics/sign_invisible.tga new file mode 100644 index 0000000000..1388f49bdb Binary files /dev/null and b/models/relics/sign_invisible.tga differ diff --git a/models/relics/sign_invisible_glow.tga b/models/relics/sign_invisible_glow.tga new file mode 100644 index 0000000000..4def2fa19a Binary files /dev/null and b/models/relics/sign_invisible_glow.tga differ diff --git a/models/relics/sign_jump.tga b/models/relics/sign_jump.tga new file mode 100644 index 0000000000..c17e35ae29 Binary files /dev/null and b/models/relics/sign_jump.tga differ diff --git a/models/relics/sign_jump_glow.tga b/models/relics/sign_jump_glow.tga new file mode 100644 index 0000000000..c17e35ae29 Binary files /dev/null and b/models/relics/sign_jump_glow.tga differ diff --git a/models/relics/sign_radioactive.tga b/models/relics/sign_radioactive.tga new file mode 100644 index 0000000000..463149c784 Binary files /dev/null and b/models/relics/sign_radioactive.tga differ diff --git a/models/relics/sign_radioactive_glow.tga b/models/relics/sign_radioactive_glow.tga new file mode 100644 index 0000000000..86c014c68b Binary files /dev/null and b/models/relics/sign_radioactive_glow.tga differ diff --git a/models/relics/sign_regeneration.tga b/models/relics/sign_regeneration.tga new file mode 100644 index 0000000000..318aece371 Binary files /dev/null and b/models/relics/sign_regeneration.tga differ diff --git a/models/relics/sign_regeneration_glow.tga b/models/relics/sign_regeneration_glow.tga new file mode 100644 index 0000000000..4da50d8880 Binary files /dev/null and b/models/relics/sign_regeneration_glow.tga differ diff --git a/models/relics/sign_resistance.tga b/models/relics/sign_resistance.tga new file mode 100644 index 0000000000..e494857a1c Binary files /dev/null and b/models/relics/sign_resistance.tga differ diff --git a/models/relics/sign_resistance_glow.tga b/models/relics/sign_resistance_glow.tga new file mode 100644 index 0000000000..cdacba8c7e Binary files /dev/null and b/models/relics/sign_resistance_glow.tga differ diff --git a/models/relics/sign_resurrection.tga b/models/relics/sign_resurrection.tga new file mode 100644 index 0000000000..1dbbeb422e Binary files /dev/null and b/models/relics/sign_resurrection.tga differ diff --git a/models/relics/sign_resurrection_glow.tga b/models/relics/sign_resurrection_glow.tga new file mode 100644 index 0000000000..0bd6e93585 Binary files /dev/null and b/models/relics/sign_resurrection_glow.tga differ diff --git a/models/relics/sign_speed.tga b/models/relics/sign_speed.tga new file mode 100644 index 0000000000..ca84dbe091 Binary files /dev/null and b/models/relics/sign_speed.tga differ diff --git a/models/relics/sign_speed_glow.tga b/models/relics/sign_speed_glow.tga new file mode 100644 index 0000000000..ca84dbe091 Binary files /dev/null and b/models/relics/sign_speed_glow.tga differ diff --git a/models/relics/sign_splashdamage.tga b/models/relics/sign_splashdamage.tga new file mode 100644 index 0000000000..228dfc151c Binary files /dev/null and b/models/relics/sign_splashdamage.tga differ diff --git a/models/relics/sign_splashdamage_glow.tga b/models/relics/sign_splashdamage_glow.tga new file mode 100644 index 0000000000..482a2b2e04 Binary files /dev/null and b/models/relics/sign_splashdamage_glow.tga differ diff --git a/models/relics/sign_teamboost.tga b/models/relics/sign_teamboost.tga new file mode 100644 index 0000000000..b7961d08d9 Binary files /dev/null and b/models/relics/sign_teamboost.tga differ diff --git a/models/relics/sign_teamboost_glow.tga b/models/relics/sign_teamboost_glow.tga new file mode 100644 index 0000000000..60bbbab963 Binary files /dev/null and b/models/relics/sign_teamboost_glow.tga differ diff --git a/models/relics/sign_vampire.tga b/models/relics/sign_vampire.tga new file mode 100644 index 0000000000..2f070c9771 Binary files /dev/null and b/models/relics/sign_vampire.tga differ diff --git a/models/relics/sign_vampire_glow.tga b/models/relics/sign_vampire_glow.tga new file mode 100644 index 0000000000..abb8ede824 Binary files /dev/null and b/models/relics/sign_vampire_glow.tga differ diff --git a/models/relics/sign_vengeance.tga b/models/relics/sign_vengeance.tga new file mode 100644 index 0000000000..bb142d4308 Binary files /dev/null and b/models/relics/sign_vengeance.tga differ diff --git a/models/relics/sign_vengeance_glow.tga b/models/relics/sign_vengeance_glow.tga new file mode 100644 index 0000000000..bb142d4308 Binary files /dev/null and b/models/relics/sign_vengeance_glow.tga differ diff --git a/models/sprites/make-sprites.sh b/models/sprites/make-sprites.sh index 87f24a6d0b..9f08c21f9b 100644 --- a/models/sprites/make-sprites.sh +++ b/models/sprites/make-sprites.sh @@ -206,3 +206,5 @@ sprite item-fuelregen "Fuel regen" ff8000 000000 0.5 ff8000 ffff00 0.5 sprite item-jetpack "Jet Pack" 808080 000000 0.5 808080 ffff00 0.5 sprite freezetag_frozen "Frozen!" 40e6ff 000000 0.0 # bright cyan + +sprite tagged-target "Tagged" 80ff0f 000000 0.25 80ff0f ffff80 0.25 diff --git a/models/sprites/tagged-target_frame0.tga b/models/sprites/tagged-target_frame0.tga new file mode 100644 index 0000000000..3ff6c2fe7c Binary files /dev/null and b/models/sprites/tagged-target_frame0.tga differ diff --git a/models/sprites/tagged-target_frame1.tga b/models/sprites/tagged-target_frame1.tga new file mode 100644 index 0000000000..60881fcd46 Binary files /dev/null and b/models/sprites/tagged-target_frame1.tga differ diff --git a/models/sprites/vehicle_frame0.tga b/models/sprites/vehicle_frame0.tga new file mode 100644 index 0000000000..0864bcb80e Binary files /dev/null and b/models/sprites/vehicle_frame0.tga differ diff --git a/models/sprites/vehicle_frame1.tga b/models/sprites/vehicle_frame1.tga new file mode 100644 index 0000000000..073354de34 Binary files /dev/null and b/models/sprites/vehicle_frame1.tga differ diff --git a/models/turrets/base.tga b/models/turrets/base.tga index a48d18d590..a4f47c05ba 100644 Binary files a/models/turrets/base.tga and b/models/turrets/base.tga differ diff --git a/models/turrets/base_shirt.tga b/models/turrets/base_shirt.tga new file mode 100644 index 0000000000..2f4810e6c1 Binary files /dev/null and b/models/turrets/base_shirt.tga differ diff --git a/models/turrets/ewheel-base.tga b/models/turrets/ewheel-base.tga index e556750903..93a3d35236 100644 Binary files a/models/turrets/ewheel-base.tga and b/models/turrets/ewheel-base.tga differ diff --git a/models/turrets/ewheel-base_glow.tga b/models/turrets/ewheel-base_glow.tga new file mode 100644 index 0000000000..6ca7016946 Binary files /dev/null and b/models/turrets/ewheel-base_glow.tga differ diff --git a/models/turrets/ewheel-base_shirt.tga b/models/turrets/ewheel-base_shirt.tga new file mode 100644 index 0000000000..67c05feaed Binary files /dev/null and b/models/turrets/ewheel-base_shirt.tga differ diff --git a/models/turrets/mggun.tga b/models/turrets/mggun.tga index fb31d6735a..be039a4ea8 100644 Binary files a/models/turrets/mggun.tga and b/models/turrets/mggun.tga differ diff --git a/models/turrets/mggun_shirt.tga b/models/turrets/mggun_shirt.tga new file mode 100644 index 0000000000..67102a2bca Binary files /dev/null and b/models/turrets/mggun_shirt.tga differ diff --git a/models/turrets/mlrs.tga b/models/turrets/mlrs.tga index ddddb07fc0..c1da397fb8 100644 Binary files a/models/turrets/mlrs.tga and b/models/turrets/mlrs.tga differ diff --git a/models/turrets/mlrs_glow.tga b/models/turrets/mlrs_glow.tga index c84fa13507..c29c16f9d6 100644 Binary files a/models/turrets/mlrs_glow.tga and b/models/turrets/mlrs_glow.tga differ diff --git a/models/turrets/phaserbody.tga b/models/turrets/phaserbody.tga index f63f5e959c..3cb227403b 100644 Binary files a/models/turrets/phaserbody.tga and b/models/turrets/phaserbody.tga differ diff --git a/models/turrets/phaserbody_glow.tga b/models/turrets/phaserbody_glow.tga index d877e73a27..6f704f0a6e 100644 Binary files a/models/turrets/phaserbody_glow.tga and b/models/turrets/phaserbody_glow.tga differ diff --git a/models/turrets/phasermag.tga b/models/turrets/phasermag.tga index 2d5b1f9889..cb48d5eb7f 100644 Binary files a/models/turrets/phasermag.tga and b/models/turrets/phasermag.tga differ diff --git a/models/turrets/phasermag_glow.tga b/models/turrets/phasermag_glow.tga index b30b540ebb..fcf104fb7f 100644 Binary files a/models/turrets/phasermag_glow.tga and b/models/turrets/phasermag_glow.tga differ diff --git a/models/turrets/plasmagun.tga b/models/turrets/plasmagun.tga index 31a4ab8b15..cb9726712d 100644 Binary files a/models/turrets/plasmagun.tga and b/models/turrets/plasmagun.tga differ diff --git a/models/turrets/plasmagun_glow.tga b/models/turrets/plasmagun_glow.tga index 881b116d51..20e09fbfee 100644 Binary files a/models/turrets/plasmagun_glow.tga and b/models/turrets/plasmagun_glow.tga differ diff --git a/models/turrets/plasmagun_shirt.tga b/models/turrets/plasmagun_shirt.tga new file mode 100644 index 0000000000..c56f8ebbe9 Binary files /dev/null and b/models/turrets/plasmagun_shirt.tga differ diff --git a/models/turrets/reactor.tga b/models/turrets/reactor.tga index c7df0397c0..9d95692935 100644 Binary files a/models/turrets/reactor.tga and b/models/turrets/reactor.tga differ diff --git a/models/turrets/reactor_glow.tga b/models/turrets/reactor_glow.tga index 720fa2e57c..573e0c03b8 100644 Binary files a/models/turrets/reactor_glow.tga and b/models/turrets/reactor_glow.tga differ diff --git a/models/turrets/rocket.tga b/models/turrets/rocket.tga index e2217d1816..cadfcba9cb 100644 Binary files a/models/turrets/rocket.tga and b/models/turrets/rocket.tga differ diff --git a/models/turrets/rocket_glow.tga b/models/turrets/rocket_glow.tga index b1a84a4ed0..33019c2c56 100644 Binary files a/models/turrets/rocket_glow.tga and b/models/turrets/rocket_glow.tga differ diff --git a/models/turrets/tesla.tga b/models/turrets/tesla.tga index cb952b0f1f..b9a5e2ec99 100644 Binary files a/models/turrets/tesla.tga and b/models/turrets/tesla.tga differ diff --git a/models/turrets/tesla_glow.tga b/models/turrets/tesla_glow.tga index 82f4e9bfa7..d33dec20c5 100644 Binary files a/models/turrets/tesla_glow.tga and b/models/turrets/tesla_glow.tga differ diff --git a/models/turrets/walker_base.tga b/models/turrets/walker_base.tga index 2381003110..41ce98375a 100644 Binary files a/models/turrets/walker_base.tga and b/models/turrets/walker_base.tga differ diff --git a/models/turrets/walker_base_glow.tga b/models/turrets/walker_base_glow.tga index bfe8dfeb05..bc4ebd01ee 100644 Binary files a/models/turrets/walker_base_glow.tga and b/models/turrets/walker_base_glow.tga differ diff --git a/models/vehicles/bomblet.md3 b/models/vehicles/bomblet.md3 new file mode 100644 index 0000000000..55ca725514 Binary files /dev/null and b/models/vehicles/bomblet.md3 differ diff --git a/models/vehicles/bumblebee.tga b/models/vehicles/bumblebee.tga new file mode 100644 index 0000000000..a20e851d10 Binary files /dev/null and b/models/vehicles/bumblebee.tga differ diff --git a/models/vehicles/bumblebee_body.dpm b/models/vehicles/bumblebee_body.dpm new file mode 100644 index 0000000000..9962dd764a Binary files /dev/null and b/models/vehicles/bumblebee_body.dpm differ diff --git a/models/vehicles/bumblebee_gloss.tga b/models/vehicles/bumblebee_gloss.tga new file mode 100644 index 0000000000..bbfb176885 Binary files /dev/null and b/models/vehicles/bumblebee_gloss.tga differ diff --git a/models/vehicles/bumblebee_glow.tga b/models/vehicles/bumblebee_glow.tga new file mode 100644 index 0000000000..c6881685af Binary files /dev/null and b/models/vehicles/bumblebee_glow.tga differ diff --git a/models/vehicles/bumblebee_norm.tga b/models/vehicles/bumblebee_norm.tga new file mode 100644 index 0000000000..0ab707c886 Binary files /dev/null and b/models/vehicles/bumblebee_norm.tga differ diff --git a/models/vehicles/bumblebee_pants.tga b/models/vehicles/bumblebee_pants.tga new file mode 100644 index 0000000000..32d0aa584c Binary files /dev/null and b/models/vehicles/bumblebee_pants.tga differ diff --git a/models/vehicles/bumblebee_plasma_left.dpm b/models/vehicles/bumblebee_plasma_left.dpm new file mode 100644 index 0000000000..57df41a258 Binary files /dev/null and b/models/vehicles/bumblebee_plasma_left.dpm differ diff --git a/models/vehicles/bumblebee_plasma_right.dpm b/models/vehicles/bumblebee_plasma_right.dpm new file mode 100644 index 0000000000..1689979fcf Binary files /dev/null and b/models/vehicles/bumblebee_plasma_right.dpm differ diff --git a/models/vehicles/bumblebee_ray.dpm b/models/vehicles/bumblebee_ray.dpm new file mode 100644 index 0000000000..2e36eb5345 Binary files /dev/null and b/models/vehicles/bumblebee_ray.dpm differ diff --git a/models/vehicles/clusterbomb.md3 b/models/vehicles/clusterbomb.md3 new file mode 100644 index 0000000000..c0842dfeef Binary files /dev/null and b/models/vehicles/clusterbomb.md3 differ diff --git a/models/vehicles/clusterbomb_folded.md3 b/models/vehicles/clusterbomb_folded.md3 new file mode 100644 index 0000000000..f1b65a6c5c Binary files /dev/null and b/models/vehicles/clusterbomb_folded.md3 differ diff --git a/models/vehicles/clusterbomb_fragment.md3 b/models/vehicles/clusterbomb_fragment.md3 new file mode 100644 index 0000000000..516da16244 Binary files /dev/null and b/models/vehicles/clusterbomb_fragment.md3 differ diff --git a/models/vehicles/raptor.dpm b/models/vehicles/raptor.dpm index 83518c5c62..bbd758a1c7 100644 Binary files a/models/vehicles/raptor.dpm and b/models/vehicles/raptor.dpm differ diff --git a/models/vehicles/raptor_body.dpm b/models/vehicles/raptor_body.dpm new file mode 100644 index 0000000000..2a283175f1 Binary files /dev/null and b/models/vehicles/raptor_body.dpm differ diff --git a/models/vehicles/raptor_cockpit.dpm b/models/vehicles/raptor_cockpit.dpm index fe933e4e42..d321f37d3d 100644 Binary files a/models/vehicles/raptor_cockpit.dpm and b/models/vehicles/raptor_cockpit.dpm differ diff --git a/models/vehicles/rocket01.md3 b/models/vehicles/rocket01.md3 new file mode 100644 index 0000000000..1d9aab9392 Binary files /dev/null and b/models/vehicles/rocket01.md3 differ diff --git a/models/vehicles/rocket02.md3 b/models/vehicles/rocket02.md3 new file mode 100644 index 0000000000..0a3eef0496 Binary files /dev/null and b/models/vehicles/rocket02.md3 differ diff --git a/models/vehicles/rockets.tga b/models/vehicles/rockets.tga new file mode 100644 index 0000000000..a6b873c4d9 Binary files /dev/null and b/models/vehicles/rockets.tga differ diff --git a/models/vehicles/rockets_gloss.tga b/models/vehicles/rockets_gloss.tga new file mode 100644 index 0000000000..22616da9b1 Binary files /dev/null and b/models/vehicles/rockets_gloss.tga differ diff --git a/models/vehicles/rockets_glow.tga b/models/vehicles/rockets_glow.tga new file mode 100644 index 0000000000..14c9f3045e Binary files /dev/null and b/models/vehicles/rockets_glow.tga differ diff --git a/models/vehicles/rockets_reflect.tga b/models/vehicles/rockets_reflect.tga new file mode 100644 index 0000000000..3cad23f56d Binary files /dev/null and b/models/vehicles/rockets_reflect.tga differ diff --git a/models/vehicles/spiderbot.dpm b/models/vehicles/spiderbot.dpm index eeb5e92e7e..2b5624f03c 100644 Binary files a/models/vehicles/spiderbot.dpm and b/models/vehicles/spiderbot.dpm differ diff --git a/models/vehicles/spiderbot.dpm.framegroups b/models/vehicles/spiderbot.dpm.framegroups index f9db7221e4..835bd3bd17 100644 --- a/models/vehicles/spiderbot.dpm.framegroups +++ b/models/vehicles/spiderbot.dpm.framegroups @@ -1,6 +1,17 @@ -1 30 20 1 // forward -32 30 20 1 // backward -63 30 20 1 // left -94 30 20 1 // right -125 30 20 0 // jump -0 1 20 0 // idle +/* +Generated framegroups file for spiderbot +Used by DarkPlaces to simulate frame groups in DPM models. +*/ + +1 31 30 1 // spiderbot forward +32 31 30 1 // spiderbot backwards +63 31 20 1 // spiderbot left +94 31 20 1 // spiderbot right +125 31 20 0 // spiderbot jump +156 1 1 0 // spiderbot idle +157 12 20 0 // spiderbot jump2 +169 7 20 0 // spiderbot jump_charge +176 11 15 0 // spiderbot jump_fly +187 21 20 0 // spiderbot jump_land +208 51 15 0 // spiderbot death +259 3 1 0 // spiderbot dead diff --git a/models/vehicles/spiderbot_cockpit.dpm b/models/vehicles/spiderbot_cockpit.dpm index 8d64449d3c..a851f3e083 100644 Binary files a/models/vehicles/spiderbot_cockpit.dpm and b/models/vehicles/spiderbot_cockpit.dpm differ diff --git a/models/vehicles/spiderbot_top.dpm b/models/vehicles/spiderbot_top.dpm index 5085e6be2e..e9209ba9c7 100644 Binary files a/models/vehicles/spiderbot_top.dpm and b/models/vehicles/spiderbot_top.dpm differ diff --git a/models/vehicles/spinner.dpm b/models/vehicles/spinner.dpm index d3d83b44b3..7e453f2011 100644 Binary files a/models/vehicles/spinner.dpm and b/models/vehicles/spinner.dpm differ diff --git a/models/vehicles/tracer.md3 b/models/vehicles/tracer.md3 new file mode 100644 index 0000000000..81ef34b286 Binary files /dev/null and b/models/vehicles/tracer.md3 differ diff --git a/models/vehicles/tracercore.tga b/models/vehicles/tracercore.tga new file mode 100644 index 0000000000..811db463da Binary files /dev/null and b/models/vehicles/tracercore.tga differ diff --git a/models/vehicles/tracertrail.tga b/models/vehicles/tracertrail.tga new file mode 100644 index 0000000000..38a4f0393e Binary files /dev/null and b/models/vehicles/tracertrail.tga differ diff --git a/models/vehicles/tracertrail_glow.tga b/models/vehicles/tracertrail_glow.tga new file mode 100644 index 0000000000..75ff134b35 Binary files /dev/null and b/models/vehicles/tracertrail_glow.tga differ diff --git a/models/weapons/akordeon.tga b/models/weapons/akordeon.tga new file mode 100644 index 0000000000..68b0ae0dfa Binary files /dev/null and b/models/weapons/akordeon.tga differ diff --git a/models/weapons/akordeon_gloss.tga b/models/weapons/akordeon_gloss.tga new file mode 100644 index 0000000000..b03c089188 Binary files /dev/null and b/models/weapons/akordeon_gloss.tga differ diff --git a/models/weapons/akordeon_reflect.tga b/models/weapons/akordeon_reflect.tga new file mode 100644 index 0000000000..2f3eba9b6a Binary files /dev/null and b/models/weapons/akordeon_reflect.tga differ diff --git a/models/weapons/g_crylink.md3 b/models/weapons/g_crylink.md3 index 8634feaeb0..b325c9c2be 100644 Binary files a/models/weapons/g_crylink.md3 and b/models/weapons/g_crylink.md3 differ diff --git a/models/weapons/g_hlac.md3 b/models/weapons/g_hlac.md3 index ae76ba7655..6e76885b39 100644 Binary files a/models/weapons/g_hlac.md3 and b/models/weapons/g_hlac.md3 differ diff --git a/models/weapons/g_laser.md3 b/models/weapons/g_laser.md3 index b31e260343..d1f168a61c 100644 Binary files a/models/weapons/g_laser.md3 and b/models/weapons/g_laser.md3 differ diff --git a/models/weapons/g_minelayer.md3 b/models/weapons/g_minelayer.md3 index 60caa4125a..898c13233f 100644 Binary files a/models/weapons/g_minelayer.md3 and b/models/weapons/g_minelayer.md3 differ diff --git a/models/weapons/g_minstanex.md3 b/models/weapons/g_minstanex.md3 index 4575e9be4d..847e3149ca 100644 Binary files a/models/weapons/g_minstanex.md3 and b/models/weapons/g_minstanex.md3 differ diff --git a/models/weapons/g_nex.md3 b/models/weapons/g_nex.md3 index 5594558b85..6ecb0aaba2 100644 Binary files a/models/weapons/g_nex.md3 and b/models/weapons/g_nex.md3 differ diff --git a/models/weapons/g_porto.md3 b/models/weapons/g_porto.md3 index f0dce9dc42..78163a9032 100644 Binary files a/models/weapons/g_porto.md3 and b/models/weapons/g_porto.md3 differ diff --git a/models/weapons/h_akordeon.iqm b/models/weapons/h_akordeon.iqm new file mode 100644 index 0000000000..523ef998a8 Binary files /dev/null and b/models/weapons/h_akordeon.iqm differ diff --git a/models/weapons/h_campingrifle.iqm b/models/weapons/h_campingrifle.iqm index c7da48ea12..6ab7548880 100644 Binary files a/models/weapons/h_campingrifle.iqm and b/models/weapons/h_campingrifle.iqm differ diff --git a/models/weapons/h_crylink.iqm b/models/weapons/h_crylink.iqm index 2aadd39912..d8de4644f5 100644 Binary files a/models/weapons/h_crylink.iqm and b/models/weapons/h_crylink.iqm differ diff --git a/models/weapons/h_electro.iqm b/models/weapons/h_electro.iqm index 8ae8898d5a..a726b33f24 100644 Binary files a/models/weapons/h_electro.iqm and b/models/weapons/h_electro.iqm differ diff --git a/models/weapons/h_fireball.iqm b/models/weapons/h_fireball.iqm index 9fb4af5015..40a6b06a83 100644 Binary files a/models/weapons/h_fireball.iqm and b/models/weapons/h_fireball.iqm differ diff --git a/models/weapons/h_gl.iqm b/models/weapons/h_gl.iqm index 33fab126fe..5ddc2784b5 100644 Binary files a/models/weapons/h_gl.iqm and b/models/weapons/h_gl.iqm differ diff --git a/models/weapons/h_hagar.iqm b/models/weapons/h_hagar.iqm index e3a4d57eed..a51c6c4f5e 100644 Binary files a/models/weapons/h_hagar.iqm and b/models/weapons/h_hagar.iqm differ diff --git a/models/weapons/h_hlac.iqm b/models/weapons/h_hlac.iqm index 157a56bb7a..3d73557d58 100644 Binary files a/models/weapons/h_hlac.iqm and b/models/weapons/h_hlac.iqm differ diff --git a/models/weapons/h_hookgun.iqm b/models/weapons/h_hookgun.iqm index 0492d0afdc..003ebad37d 100644 Binary files a/models/weapons/h_hookgun.iqm and b/models/weapons/h_hookgun.iqm differ diff --git a/models/weapons/h_laser.iqm b/models/weapons/h_laser.iqm index 0ca28e9800..25fefcaf8a 100644 Binary files a/models/weapons/h_laser.iqm and b/models/weapons/h_laser.iqm differ diff --git a/models/weapons/h_minelayer.iqm b/models/weapons/h_minelayer.iqm index 0c6ed41f16..0246e23a6e 100644 Binary files a/models/weapons/h_minelayer.iqm and b/models/weapons/h_minelayer.iqm differ diff --git a/models/weapons/h_minstanex.iqm b/models/weapons/h_minstanex.iqm index 77d677529e..82b0b23303 100644 Binary files a/models/weapons/h_minstanex.iqm and b/models/weapons/h_minstanex.iqm differ diff --git a/models/weapons/h_minstanex.iqm.framegroups b/models/weapons/h_minstanex.iqm.framegroups index 0a59625b6a..9c7e7021cf 100644 --- a/models/weapons/h_minstanex.iqm.framegroups +++ b/models/weapons/h_minstanex.iqm.framegroups @@ -1,4 +1,10 @@ -1 8 20 0 // fire -9 5 20 0 // fire2 -15 200 20 1 // idle -215 40 20 0 // reload +/* +Generated framegroups file for h_uzi +Used by DarkPlaces to simulate frame groups in DPM models. +*/ + +1 16 30 0 // h_uzi mgafire +17 16 30 0 // h_uzi mgafire2 +33 101 3 1 // h_uzi mgaidle +134 61 30 0 // h_uzi mgareload +195 16 30 0 // h_uzi mgafire diff --git a/models/weapons/h_nex.iqm b/models/weapons/h_nex.iqm index 8b52897ffa..39857cf795 100644 Binary files a/models/weapons/h_nex.iqm and b/models/weapons/h_nex.iqm differ diff --git a/models/weapons/h_porto.iqm b/models/weapons/h_porto.iqm index 0c6ed41f16..0246e23a6e 100644 Binary files a/models/weapons/h_porto.iqm and b/models/weapons/h_porto.iqm differ diff --git a/models/weapons/h_rl.iqm b/models/weapons/h_rl.iqm index 21b7225549..ffcb1a69e6 100644 Binary files a/models/weapons/h_rl.iqm and b/models/weapons/h_rl.iqm differ diff --git a/models/weapons/h_seeker.iqm b/models/weapons/h_seeker.iqm index 9fb4af5015..40a6b06a83 100644 Binary files a/models/weapons/h_seeker.iqm and b/models/weapons/h_seeker.iqm differ diff --git a/models/weapons/h_shotgun.iqm b/models/weapons/h_shotgun.iqm index 89b121b90d..9c4a29dbbc 100644 Binary files a/models/weapons/h_shotgun.iqm and b/models/weapons/h_shotgun.iqm differ diff --git a/models/weapons/h_tuba.iqm b/models/weapons/h_tuba.iqm index 523bbb1ffe..523ef998a8 100644 Binary files a/models/weapons/h_tuba.iqm and b/models/weapons/h_tuba.iqm differ diff --git a/models/weapons/h_uzi.iqm b/models/weapons/h_uzi.iqm index 523bbb1ffe..523ef998a8 100644 Binary files a/models/weapons/h_uzi.iqm and b/models/weapons/h_uzi.iqm differ diff --git a/models/weapons/mnex.tga b/models/weapons/mnex.tga new file mode 100644 index 0000000000..b4df2a394f Binary files /dev/null and b/models/weapons/mnex.tga differ diff --git a/models/weapons/mnex_bump.tga b/models/weapons/mnex_bump.tga new file mode 100644 index 0000000000..98b3a5c788 Binary files /dev/null and b/models/weapons/mnex_bump.tga differ diff --git a/models/weapons/mnex_gloss.tga b/models/weapons/mnex_gloss.tga new file mode 100644 index 0000000000..8750a0e278 Binary files /dev/null and b/models/weapons/mnex_gloss.tga differ diff --git a/models/weapons/mnex_glow.tga b/models/weapons/mnex_glow.tga new file mode 100644 index 0000000000..aa5402963e Binary files /dev/null and b/models/weapons/mnex_glow.tga differ diff --git a/models/weapons/mnex_reflect.tga b/models/weapons/mnex_reflect.tga new file mode 100644 index 0000000000..f7fa7c8954 Binary files /dev/null and b/models/weapons/mnex_reflect.tga differ diff --git a/models/weapons/mnex_shirt.tga b/models/weapons/mnex_shirt.tga new file mode 100644 index 0000000000..dd371d612f Binary files /dev/null and b/models/weapons/mnex_shirt.tga differ diff --git a/models/weapons/v_akordeon.md3 b/models/weapons/v_akordeon.md3 new file mode 100644 index 0000000000..3990797417 Binary files /dev/null and b/models/weapons/v_akordeon.md3 differ diff --git a/models/weapons/v_crylink.md3 b/models/weapons/v_crylink.md3 index af34658d79..c3b9f3ca83 100644 Binary files a/models/weapons/v_crylink.md3 and b/models/weapons/v_crylink.md3 differ diff --git a/models/weapons/v_hlac.md3 b/models/weapons/v_hlac.md3 index 3bbc34d567..887c2a7964 100644 Binary files a/models/weapons/v_hlac.md3 and b/models/weapons/v_hlac.md3 differ diff --git a/models/weapons/v_hookgun.md3 b/models/weapons/v_hookgun.md3 index 4ca6a130e8..8b96df0382 100644 Binary files a/models/weapons/v_hookgun.md3 and b/models/weapons/v_hookgun.md3 differ diff --git a/models/weapons/v_laser.md3 b/models/weapons/v_laser.md3 index 836ad36b39..dc5e267450 100644 Binary files a/models/weapons/v_laser.md3 and b/models/weapons/v_laser.md3 differ diff --git a/models/weapons/v_minelayer.md3 b/models/weapons/v_minelayer.md3 index 648b0f1a74..529f02fcf9 100644 Binary files a/models/weapons/v_minelayer.md3 and b/models/weapons/v_minelayer.md3 differ diff --git a/models/weapons/v_minstanex.md3 b/models/weapons/v_minstanex.md3 index d583e1a616..d08b8feff5 100644 Binary files a/models/weapons/v_minstanex.md3 and b/models/weapons/v_minstanex.md3 differ diff --git a/models/weapons/v_nex.md3 b/models/weapons/v_nex.md3 index 1d45edb793..4cafdd10ff 100644 Binary files a/models/weapons/v_nex.md3 and b/models/weapons/v_nex.md3 differ diff --git a/models/weapons/v_porto.md3 b/models/weapons/v_porto.md3 index 5d06b3c066..b72113aa55 100644 Binary files a/models/weapons/v_porto.md3 and b/models/weapons/v_porto.md3 differ diff --git a/particles/particlefont.tga b/particles/particlefont.tga index 8ee89adb08..a23348225e 100644 Binary files a/particles/particlefont.tga and b/particles/particlefont.tga differ diff --git a/physicsCPMA.cfg b/physicsCPMA.cfg index 2ae8d2d6b8..620ec882e5 100644 --- a/physicsCPMA.cfg +++ b/physicsCPMA.cfg @@ -13,6 +13,7 @@ sv_wateraccelerate 4 sv_waterfriction 1 sv_airaccel_sideways_friction 0 sv_airaccel_qw 1 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 2.5 sv_airstrafeaccelerate 70 sv_maxairstrafespeed 30 @@ -30,4 +31,4 @@ sv_doublejump 0 sv_jumpspeedcap_min "" sv_jumpspeedcap_max "" sv_jumpspeedcap_max_disable_on_ramps 0 -g_teleport_maxspeed 320 +g_teleport_maxspeed 400 diff --git a/physicsFruit.cfg b/physicsFruit.cfg index 6467afad4c..1afb26330c 100644 --- a/physicsFruit.cfg +++ b/physicsFruit.cfg @@ -13,6 +13,7 @@ sv_wateraccelerate -1 sv_waterfriction -1 sv_airaccel_sideways_friction 0 // breaks strafing? sv_airaccel_qw 0.92 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 2.5 sv_airstrafeaccelerate 20 sv_maxairstrafespeed 100 diff --git a/physicsHavoc.cfg b/physicsHavoc.cfg index a19617d93f..d78346e1b6 100644 --- a/physicsHavoc.cfg +++ b/physicsHavoc.cfg @@ -13,6 +13,7 @@ sv_wateraccelerate -1 sv_waterfriction -1 sv_airaccel_sideways_friction 0.65 sv_airaccel_qw 0.95 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 0 sv_airstrafeaccelerate 0 sv_maxairstrafespeed 0 diff --git a/physicsLeeStricklin-ModdedFruit.cfg b/physicsLeeStricklin-ModdedFruit.cfg index c3329426e1..21bafef57c 100644 --- a/physicsLeeStricklin-ModdedFruit.cfg +++ b/physicsLeeStricklin-ModdedFruit.cfg @@ -20,6 +20,7 @@ sv_wateraccelerate -1 sv_waterfriction -1 sv_airaccel_sideways_friction 0 // breaks strafing? sv_airaccel_qw -0.8 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate -0.95 sv_airstrafeaccelerate 24 diff --git a/physicsLeeStricklin.cfg b/physicsLeeStricklin.cfg index 2f23ae763d..3c740da337 100644 --- a/physicsLeeStricklin.cfg +++ b/physicsLeeStricklin.cfg @@ -20,6 +20,7 @@ sv_wateraccelerate -1 sv_waterfriction -1 sv_airaccel_sideways_friction 0 sv_airaccel_qw -0.8 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 3 sv_airstrafeaccelerate 24 diff --git a/physicsLeeStricklinOld.cfg b/physicsLeeStricklinOld.cfg index bb6133a8b7..d240d991b3 100644 --- a/physicsLeeStricklinOld.cfg +++ b/physicsLeeStricklinOld.cfg @@ -15,6 +15,7 @@ sv_wateraccelerate -1 sv_waterfriction -1 sv_airaccel_sideways_friction 0 // pain in the ass to tweak without screwing up the strafing sv_airaccel_qw -0.93 //given a negative value to combat potential cheats, was told by divVerent not to mess with it +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 0 sv_airstrafeaccelerate 0 diff --git a/physicsLzd.cfg b/physicsLzd.cfg index 01e446e8ba..86b4bdcf02 100644 --- a/physicsLzd.cfg +++ b/physicsLzd.cfg @@ -14,6 +14,7 @@ sv_wateraccelerate -1 sv_waterfriction -1 sv_airaccel_sideways_friction 0.35 sv_airaccel_qw 0.95 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 0 sv_airstrafeaccelerate 0 sv_maxairstrafespeed 0 diff --git a/physicsNexuiz10.cfg b/physicsNexuiz10.cfg index de2ff25912..a6673a28e2 100644 --- a/physicsNexuiz10.cfg +++ b/physicsNexuiz10.cfg @@ -13,6 +13,7 @@ sv_wateraccelerate -1 sv_waterfriction -1 sv_airaccel_sideways_friction 0 sv_airaccel_qw 0 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 0 sv_airstrafeaccelerate 0 sv_maxairstrafespeed 0 diff --git a/physicsNexuiz11.cfg b/physicsNexuiz11.cfg index 64ac7b019c..60459c3747 100644 --- a/physicsNexuiz11.cfg +++ b/physicsNexuiz11.cfg @@ -13,6 +13,7 @@ sv_wateraccelerate -1 sv_waterfriction -1 sv_airaccel_sideways_friction 0 sv_airaccel_qw 0 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 0 sv_airstrafeaccelerate 0 sv_maxairstrafespeed 0 diff --git a/physicsNexuiz151.cfg b/physicsNexuiz151.cfg index c527b29efb..b099d4cf34 100644 --- a/physicsNexuiz151.cfg +++ b/physicsNexuiz151.cfg @@ -13,6 +13,7 @@ sv_wateraccelerate -1 sv_waterfriction -1 sv_airaccel_sideways_friction 0 sv_airaccel_qw 0 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 0 sv_airstrafeaccelerate 0 sv_maxairstrafespeed 0 diff --git a/physicsNexuiz151b.cfg b/physicsNexuiz151b.cfg index aa2f530cdf..8821b5a319 100644 --- a/physicsNexuiz151b.cfg +++ b/physicsNexuiz151b.cfg @@ -13,6 +13,7 @@ sv_wateraccelerate -1 sv_waterfriction -1 sv_airaccel_sideways_friction 0 sv_airaccel_qw 0 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 0 sv_airstrafeaccelerate 0 sv_maxairstrafespeed 0 diff --git a/physicsNexuiz16rc1.cfg b/physicsNexuiz16rc1.cfg index 0622e1a481..ff6343f781 100644 --- a/physicsNexuiz16rc1.cfg +++ b/physicsNexuiz16rc1.cfg @@ -13,6 +13,7 @@ sv_wateraccelerate -1 sv_waterfriction -1 sv_airaccel_sideways_friction 0 sv_airaccel_qw 0 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 0 sv_airstrafeaccelerate 0 sv_maxairstrafespeed 0 diff --git a/physicsNexuiz20.cfg b/physicsNexuiz20.cfg index 1d15fe1d67..0834bb5aa6 100644 --- a/physicsNexuiz20.cfg +++ b/physicsNexuiz20.cfg @@ -13,6 +13,7 @@ sv_wateraccelerate -1 sv_waterfriction -1 sv_airaccel_sideways_friction 0.3 sv_airaccel_qw 0.93 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 0 sv_airstrafeaccelerate 0 sv_maxairstrafespeed 0 diff --git a/physicsNexuiz25.cfg b/physicsNexuiz25.cfg index 5b6db6b944..8c5ab5e851 100644 --- a/physicsNexuiz25.cfg +++ b/physicsNexuiz25.cfg @@ -13,6 +13,7 @@ sv_wateraccelerate -1 sv_waterfriction -1 sv_airaccel_sideways_friction 0.35 sv_airaccel_qw 0.95 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 0 sv_airstrafeaccelerate 0 sv_maxairstrafespeed 0 diff --git a/physicsNexuiz26.cfg b/physicsNexuiz26.cfg index f7661523ea..4e104d1aa9 100644 --- a/physicsNexuiz26.cfg +++ b/physicsNexuiz26.cfg @@ -13,6 +13,7 @@ sv_wateraccelerate -1 sv_waterfriction -1 sv_airaccel_sideways_friction 0.35 sv_airaccel_qw 0.95 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 0 sv_airstrafeaccelerate 0 sv_maxairstrafespeed 0 diff --git a/physicsNoQWBunny-nexbased.cfg b/physicsNoQWBunny-nexbased.cfg index 2f12a4ebce..e74b332ede 100644 --- a/physicsNoQWBunny-nexbased.cfg +++ b/physicsNoQWBunny-nexbased.cfg @@ -21,6 +21,7 @@ sv_wateraccelerate -1 sv_waterfriction -1 sv_airaccel_sideways_friction 0 sv_airaccel_qw -0.9475 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 3 sv_airstrafeaccelerate 24 diff --git a/physicsQ.cfg b/physicsQ.cfg index 509310843b..1eb53ab383 100644 --- a/physicsQ.cfg +++ b/physicsQ.cfg @@ -14,6 +14,7 @@ sv_wateraccelerate -1 sv_waterfriction -1 sv_airaccel_sideways_friction 0 sv_airaccel_qw 1 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 0 sv_airstrafeaccelerate 0 sv_maxairstrafespeed 0 diff --git a/physicsQ2.cfg b/physicsQ2.cfg index dc580a5119..2e3c0af6f3 100644 --- a/physicsQ2.cfg +++ b/physicsQ2.cfg @@ -13,6 +13,7 @@ sv_wateraccelerate -1 sv_waterfriction 1 sv_airaccel_sideways_friction 0 sv_airaccel_qw 1 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 0 sv_airstrafeaccelerate 0 sv_maxairstrafespeed 0 diff --git a/physicsQ2a.cfg b/physicsQ2a.cfg index c5f21116ec..2d223a2051 100644 --- a/physicsQ2a.cfg +++ b/physicsQ2a.cfg @@ -14,6 +14,7 @@ sv_wateraccelerate -1 sv_waterfriction 1 sv_airaccel_sideways_friction 0 sv_airaccel_qw 1 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 0 sv_airstrafeaccelerate 0 sv_maxairstrafespeed 0 diff --git a/physicsQ3.cfg b/physicsQ3.cfg index a50427155e..b3fdf41a82 100644 --- a/physicsQ3.cfg +++ b/physicsQ3.cfg @@ -13,6 +13,7 @@ sv_wateraccelerate 4 sv_waterfriction 1 sv_airaccel_sideways_friction 0 sv_airaccel_qw 1 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 0 sv_airstrafeaccelerate 0 sv_maxairstrafespeed 0 diff --git a/physicsQBF.cfg b/physicsQBF.cfg index 9725e8cc4a..390cb968ad 100644 --- a/physicsQBF.cfg +++ b/physicsQBF.cfg @@ -13,6 +13,7 @@ sv_wateraccelerate -1 sv_waterfriction -1 sv_airaccel_sideways_friction 0.8 sv_airaccel_qw 1 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 0 sv_airstrafeaccelerate 0 sv_maxairstrafespeed 0 diff --git a/physicsQBFplus.cfg b/physicsQBFplus.cfg index 75c70c1818..8c1a78f3b9 100644 --- a/physicsQBFplus.cfg +++ b/physicsQBFplus.cfg @@ -13,6 +13,7 @@ sv_wateraccelerate -1 sv_waterfriction -1 sv_airaccel_sideways_friction 0.5 sv_airaccel_qw 0.93 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 0 sv_airstrafeaccelerate 0 sv_maxairstrafespeed 0 diff --git a/physicsSamual.cfg b/physicsSamual.cfg index 731b1482e6..178eed0aed 100644 --- a/physicsSamual.cfg +++ b/physicsSamual.cfg @@ -13,6 +13,7 @@ sv_wateraccelerate -1 sv_waterfriction -1 sv_airaccel_sideways_friction 0.3 sv_airaccel_qw 0.93 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 0 sv_airstrafeaccelerate 0 sv_maxairstrafespeed 0 diff --git a/physicsWarsow.cfg b/physicsWarsow.cfg index 068d22ce67..6cae75a797 100644 --- a/physicsWarsow.cfg +++ b/physicsWarsow.cfg @@ -13,6 +13,7 @@ sv_wateraccelerate 10 sv_waterfriction 1 sv_airaccel_sideways_friction 0 sv_airaccel_qw 1 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 2.5 sv_airstrafeaccelerate 70 sv_maxairstrafespeed 30 diff --git a/physicsWarsowClassicBunny.cfg b/physicsWarsowClassicBunny.cfg index 72ca9ffcae..5c0c81c8fb 100644 --- a/physicsWarsowClassicBunny.cfg +++ b/physicsWarsowClassicBunny.cfg @@ -13,6 +13,7 @@ sv_wateraccelerate 10 sv_waterfriction 1 sv_airaccel_sideways_friction 0 sv_airaccel_qw 1 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 2.5 sv_airstrafeaccelerate 70 sv_maxairstrafespeed 30 diff --git a/physicsWarsowDev.cfg b/physicsWarsowDev.cfg index 051775de9a..0c30fcd9a0 100644 --- a/physicsWarsowDev.cfg +++ b/physicsWarsowDev.cfg @@ -13,6 +13,7 @@ sv_wateraccelerate 10 sv_waterfriction 1 sv_airaccel_sideways_friction 0 sv_airaccel_qw 1 +sv_airaccel_qw_stretchfactor 0 sv_airstopaccelerate 2 sv_airstrafeaccelerate 70 sv_maxairstrafespeed 30 diff --git a/physicsX.cfg b/physicsX.cfg new file mode 100644 index 0000000000..7a78d3726b --- /dev/null +++ b/physicsX.cfg @@ -0,0 +1,48 @@ +// current Xonotic physics +sv_gravity 800 +sv_maxspeed 360 +sv_maxairspeed 360 + +sv_stopspeed 100 +sv_accelerate 15 +sv_airaccelerate 2 +sv_friction 8 +edgefriction 1 +sv_stepheight 26 +// Q1: 16+2 +// Nex: 32+2 +// we try: 24+2 + +// actually, what we want is 266.6666 for 180bpm +// but 260 takes same amount of frames and is nicer to mappers +// jump height == sv_jumpvelocity^2 / (2*sv_gravity) +// in this case: 42.25 qu +// player: 24+45 qu +// total: 111.25qu +// this is smaller than 112 qu, so a 112 qu high corridor (7 of 8 grid units in +// the 16 grid, and the 8th unit used for wall/floor) just lets a player jump! +sv_jumpvelocity 260 +sv_wateraccelerate -1 +sv_waterfriction -1 +sv_airaccel_sideways_friction 0 +sv_airaccel_qw -0.8 +sv_airaccel_qw_stretchfactor 2 + +sv_airstopaccelerate 3 +sv_airstrafeaccelerate 24 +sv_maxairstrafespeed 100 +sv_airstrafeaccel_qw -0.95 +sv_aircontrol 125 +sv_aircontrol_penalty 180 +sv_aircontrol_power 2 +sv_airspeedlimit_nonqw 800 +sv_warsowbunny_turnaccel 0 +sv_warsowbunny_accel 0.1593 +sv_warsowbunny_topspeed 925 +sv_warsowbunny_backtosideratio 0.8 +sv_friction_on_land 0 +sv_doublejump 0 +sv_jumpspeedcap_min "" +sv_jumpspeedcap_max "" +sv_jumpspeedcap_max_disable_on_ramps 1 +g_teleport_maxspeed 0 diff --git a/physicsX0.cfg b/physicsX0.cfg deleted file mode 100644 index 8fec026866..0000000000 --- a/physicsX0.cfg +++ /dev/null @@ -1,41 +0,0 @@ -// "NoQWBunny" physics based on XPM -sv_gravity 800 -sv_maxspeed 360 -sv_maxairspeed 400 - -sv_stopspeed 100 -sv_accelerate 15 -sv_airaccelerate 2 -sv_friction 8 -edgefriction 1 -sv_stepheight 26 -// Q1: 16+2 -// Nex: 32+2 -// we try: 24+2 - -// actually, what we want is 266.6666 for 180bpm -// but 260 takes same amount of frames and is nicer to mappers -sv_jumpvelocity 260 -sv_wateraccelerate -1 -sv_waterfriction -1 -sv_airaccel_sideways_friction 0 -sv_airaccel_qw -0.8 - -sv_airstopaccelerate 3 -sv_airstrafeaccelerate 24 -sv_maxairstrafespeed 100 -sv_airstrafeaccel_qw -0.95 -sv_aircontrol 125 -sv_aircontrol_penalty 150 -sv_aircontrol_power 2 -sv_airspeedlimit_nonqw 800 -sv_warsowbunny_turnaccel 0 -sv_warsowbunny_accel 0.1593 -sv_warsowbunny_topspeed 925 -sv_warsowbunny_backtosideratio 0.8 -sv_friction_on_land 0 -sv_doublejump 0 -sv_jumpspeedcap_min "" -sv_jumpspeedcap_max "" -sv_jumpspeedcap_max_disable_on_ramps 1 -g_teleport_maxspeed 0 diff --git a/physicsX010.cfg b/physicsX010.cfg new file mode 100644 index 0000000000..bda6272711 --- /dev/null +++ b/physicsX010.cfg @@ -0,0 +1,42 @@ +// Xonotic 0.1.0preview physics +sv_gravity 800 +sv_maxspeed 360 +sv_maxairspeed 400 + +sv_stopspeed 100 +sv_accelerate 15 +sv_airaccelerate 2 +sv_friction 8 +edgefriction 1 +sv_stepheight 26 +// Q1: 16+2 +// Nex: 32+2 +// we try: 24+2 + +// actually, what we want is 266.6666 for 180bpm +// but 260 takes same amount of frames and is nicer to mappers +sv_jumpvelocity 260 +sv_wateraccelerate -1 +sv_waterfriction -1 +sv_airaccel_sideways_friction 0 +sv_airaccel_qw -0.8 +sv_airaccel_qw_stretchfactor 0 + +sv_airstopaccelerate 3 +sv_airstrafeaccelerate 24 +sv_maxairstrafespeed 100 +sv_airstrafeaccel_qw -0.95 +sv_aircontrol 125 +sv_aircontrol_penalty 150 +sv_aircontrol_power 2 +sv_airspeedlimit_nonqw 800 +sv_warsowbunny_turnaccel 0 +sv_warsowbunny_accel 0.1593 +sv_warsowbunny_topspeed 925 +sv_warsowbunny_backtosideratio 0.8 +sv_friction_on_land 0 +sv_doublejump 0 +sv_jumpspeedcap_min "" +sv_jumpspeedcap_max "" +sv_jumpspeedcap_max_disable_on_ramps 1 +g_teleport_maxspeed 0 diff --git a/physicsXPM.cfg b/physicsXPM.cfg index 9191ab8e83..f781539485 100644 --- a/physicsXPM.cfg +++ b/physicsXPM.cfg @@ -16,6 +16,7 @@ sv_wateraccelerate 4 sv_waterfriction 1 sv_airaccel_sideways_friction 0 sv_airaccel_qw 0.95 +sv_airaccel_qw_stretchfactor 0 // CPMA: 1 sv_airstopaccelerate 2.5 sv_airstrafeaccelerate 70 @@ -34,4 +35,4 @@ sv_doublejump 1 sv_jumpspeedcap_min 0 sv_jumpspeedcap_max 0.5 sv_jumpspeedcap_max_disable_on_ramps 1 -g_teleport_maxspeed 320 +g_teleport_maxspeed 400 diff --git a/physicsXPMLight.cfg b/physicsXPMLight.cfg index 3e7ee55570..3a8b8e1503 100644 --- a/physicsXPMLight.cfg +++ b/physicsXPMLight.cfg @@ -16,6 +16,8 @@ sv_wateraccelerate 4 sv_waterfriction 1 sv_airaccel_sideways_friction 0 sv_airaccel_qw -0.9146875 +sv_airaccel_qw_stretchfactor 0 +sv_airaccel_qw_stretchfactor 0 // CPMA: 1 sv_airstopaccelerate 6.5625 // matches strafe-stopping speed sv_airstrafeaccelerate 14 diff --git a/qcsrc/Makefile b/qcsrc/Makefile new file mode 100644 index 0000000000..a05d13ff84 --- /dev/null +++ b/qcsrc/Makefile @@ -0,0 +1,47 @@ +SCM := $(shell if [ -d .svn ]; then echo svn; elif [ -d ../.git ]; then echo git; fi) +FTEQCC ?= fteqcc +PERL ?= perl + +FTEQCCFLAGS_WATERMARK ?= -DWATERMARK='"$(shell git describe)"' -DCVAR_POPCON +FTEQCCFLAGS ?= -Werror -Wno-Q302 -O3 -Ono-c -Ono-cs -fno-fastarrays $(FTEQCCFLAGS_EXTRA) $(FTEQCCFLAGS_WATERMARK) +FTEQCCFLAGS_PROGS ?= +FTEQCCFLAGS_MENU ?= + +# NOTE: use -DUSE_FTE instead of -TFTE here! +# It will automagically add an engine check with -TID and then change back to -TFTE +FTEQCCFLAGS_CSPROGS ?= + +# xonotic build system overrides this by command line argument to turn off the update-cvarcount step +XON_BUILDSYSTEM = + +all: qc + +.PHONY: qc +qc: + $(MAKE) qc-recursive + +.PHONY: qc-recursive +qc-recursive: ../menu.dat ../progs.dat ../csprogs.dat + +.PHONY: clean +clean: + rm -f ../progs.dat ../menu.dat ../csprogs.dat + +FILES_CSPROGS = $(shell find client common warpzonelib csqcmodellib -type f -not -name fteqcc.log -not -name qc.asm) $(wildcard server/w_*.qc) +../csprogs.dat: $(FILES_CSPROGS) + @echo make[1]: Entering directory \`$(PWD)/client\' + cd client && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_CSPROGS) + +FILES_PROGS = $(shell find server common warpzonelib csqcmodellib -type f -not -name fteqcc.log -not -name qc.asm) $(wildcard server/w_*.qc) +../progs.dat: $(FILES_PROGS) + @echo make[1]: Entering directory \`$(PWD)/server\' + cd server && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_PROGS) + +FILES_MENU = $(shell find menu common warpzonelib -type f -not -name fteqcc.log -not -name qc.asm) $(wildcard server/w_*.qc) +../menu.dat: $(FILES_MENU) + @echo make[1]: Entering directory \`$(PWD)/menu\' + cd menu && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_MENU) + +.PHONY: testcase +testcase: + cd testcase && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_CSPROGS) -DTESTCASE="$$TESTCASE" diff --git a/qcsrc/client/Defs.qc b/qcsrc/client/Defs.qc index 2d780381ee..5282910a2a 100644 --- a/qcsrc/client/Defs.qc +++ b/qcsrc/client/Defs.qc @@ -28,7 +28,7 @@ entity world; float time; float frametime; -float player_localentnum; //the entnum +float player_localentnum; //the entnum of the VIEW entity float player_localnum; //the playernum float maxclients; //a constant filled in by the engine. gah, portability eh? @@ -156,7 +156,7 @@ float scoreboard_showaccuracy; // float coop; // float deathmatch; -// float dmg_take; +float dmg_take; // float dmg_save; // vector dmg_origin; @@ -177,9 +177,6 @@ float scoreboard_showaccuracy; float vid_conwidth, vid_conheight; float binddb; -// Announcer -string announce_snd; - // QUALIFYING float race_checkpoint; float race_time; @@ -225,10 +222,6 @@ float spectatee_status; // short mapname string shortmapname; -//remaining maptime announcer sounds, true when sound was already played -float announcer_1min; -float announcer_5min; - // database for misc stuff float tempdb; float ClientProgsDB; @@ -245,6 +238,9 @@ float servertime, serverprevtime, serverdeltatime; float ticrate; .float damageforcescale; +#define MIN_DAMAGEEXTRARADIUS 2 +#define MAX_DAMAGEEXTRARADIUS 16 +.float damageextraradius; .void(float thisdmg, float hittype, vector org, vector thisforce) event_damage; // only for Porto @@ -258,10 +254,12 @@ float w_deathtype, w_issilent, w_random; string w_deathtypestring; vector w_org, w_backoff; -float campingrifle_scope; +float rifle_scope; float nex_scope; -float cr_maxbullets; +float minelayer_maxmines; + +float hagar_maxrockets; float bgmtime; diff --git a/qcsrc/client/Main.qc b/qcsrc/client/Main.qc index 435dedabc7..8facbf500f 100644 --- a/qcsrc/client/Main.qc +++ b/qcsrc/client/Main.qc @@ -3,117 +3,126 @@ //include "main.qh" #define DP_CSQC_ENTITY_REMOVE_IS_B0RKED - -void cvar_clientsettemp(string cv, string val) +void menu_show_error() { - entity e; - for(e = world; (e = find(e, classname, "saved_cvar_value")); ) - if(e.netname == cv) - goto saved; - e = spawn(); - e.classname = "saved_cvar_value"; - e.netname = strzone(cv); - e.message = strzone(cvar_string(cv)); -:saved - cvar_set(cv, val); + drawstring('0 200 0', _("ERROR - MENU IS VISIBLE BUT NO MENU WAS DEFINED!"), '8 8 0', '1 0 0', 1, 0); } -void cvar_clientsettemp_restore() -{ - entity e; - for(e = world; (e = find(e, classname, "saved_cvar_value")); ) - cvar_set(e.netname, e.message); -} - -void() menu_show_error = -{ - drawstring('0 200 0', "ERROR - MENU IS VISIBLE BUT NO MENU WAS DEFINED!", '8 8 0', '1 0 0', 1, 0); -}; - // CSQC_Init : Called every time the CSQC code is initialized (essentially at map load) // Useful for precaching things -void() menu_sub_null = +void menu_sub_null() { -}; +} #ifdef USE_FTE float __engine_check; #endif +void precache_playermodel(string m) +{ + string f; + + if(substring(m, -9,5) == "_lod1") + return; + if(substring(m, -9,5) == "_lod2") + return; + precache_model(m); + f = strcat(substring(m, 0, -5), "_lod1", substring(m, -4, -1)); + if(fexists(f)) + precache_model(f); + f = strcat(substring(m, 0, -5), "_lod2", substring(m, -4, -1)); + if(fexists(f)) + precache_model(f); + + /* + float globhandle, i, n; + globhandle = search_begin(strcat(m, "_*.sounds"), TRUE, FALSE); + if (globhandle < 0) + return; + n = search_getsize(globhandle); + for (i = 0; i < n; ++i) + { + //print(search_getfilename(globhandle, i), "\n"); + f = search_getfilename(globhandle, i); + PrecachePlayerSounds(f); + } + search_end(globhandle); + */ +} +void precache_all_playermodels(string pattern) +{ + float globhandle, i, n; + string f; + + globhandle = search_begin(pattern, TRUE, FALSE); + if (globhandle < 0) + return; + n = search_getsize(globhandle); + for (i = 0; i < n; ++i) + { + //print(search_getfilename(globhandle, i), "\n"); + f = search_getfilename(globhandle, i); + precache_playermodel(f); + } + search_end(globhandle); +} + string forcefog; -string cl_announcer_prev; void WaypointSprite_Load(); +void ConsoleCommand_macro_init(); void CSQC_Init(void) { + prvm_language = cvar_string("prvm_language"); + #ifdef USE_FTE #pragma target ID __engine_check = checkextension("DP_SV_WRITEPICTURE"); if(!__engine_check) { - print("^3Your engine build is outdated\n^3This Server uses a newer QC VM. Please update!\n"); + print(_("^3Your engine build is outdated\n^3This Server uses a newer QC VM. Please update!\n")); localcmd("\ndisconnect\n"); return; } #pragma target FTE #endif - + check_unacceptable_compiler_bugs(); #ifdef WATERMARK - print("^4CSQC Build information: ", WATERMARK(), "\n"); + print(sprintf(_("^4CSQC Build information: ^1%s\n"), WATERMARK())); #endif float i; - CSQC_CheckEngine(); + +#ifdef COMPAT_XON050_ENGINE + // old engine lacks implementation of player_localnum + player_localnum = player_localentnum - 1; +#endif binddb = db_create(); tempdb = db_create(); ClientProgsDB = db_load("client.db"); compressShortVector_init(); - drawfont = 0; + drawfont = FONT_USER+1; menu_visible = FALSE; menu_show = menu_show_error; menu_action = menu_sub_null; for(i = 0; i < 255; ++i) - if(getplayerkey(i, "viewentity") == "") + if(getplayerkeyvalue(i, "viewentity") == "") break; maxclients = i; - //ctf_temp_1 = ""; - // localcmd("alias order \"cmd order $*\""); enable if ctf-command thingy is used - //registercmd("ctf_menu"); - registercmd("ons_map"); - registercmd("hud_configure"); - registercmd("hud_save"); - //registercmd("menu_action"); - - registercmd("+button3"); - registercmd("-button3"); - registercmd("+button4"); - registercmd("-button4"); - registercmd("+showscores");registercmd("-showscores"); - registercmd("+showaccuracy");registercmd("-showaccuracy"); - -#ifndef CAMERATEST - if(isdemo()) - { -#endif - registercmd("+forward");registercmd("-forward"); - registercmd("+back");registercmd("-back"); - registercmd("+moveup");registercmd("-moveup"); - registercmd("+movedown");registercmd("-movedown"); - registercmd("+moveright");registercmd("-moveright"); - registercmd("+moveleft");registercmd("-moveleft"); - registercmd("+roll_right");registercmd("-roll_right"); - registercmd("+roll_left");registercmd("-roll_left"); -#ifndef CAMERATEST - } -#endif + //registercommand("hud_configure"); + //registercommand("hud_save"); + //registercommand("menu_action"); + + ConsoleCommand_macro_init(); + registercvar("hud_usecsqc", "1"); - registercvar("scoreboard_columns", "default", CVAR_SAVE); + registercvar("scoreboard_columns", "default"); gametype = 0; @@ -130,24 +139,41 @@ void CSQC_Init(void) GetTeam(COLOR_SPECTATOR, true); // add specs first + // needs to be done so early because of the constants they create RegisterWeapons(); + RegisterGametypes(); WaypointSprite_Load(); // precaches + precache_model("null"); + precache_sound("misc/hit.wav"); + precache_sound("misc/typehit.wav"); + if (autocvar_cl_precacheplayermodels) + { + precache_all_playermodels("models/player/*.zym"); + precache_all_playermodels("models/player/*.dpm"); + precache_all_playermodels("models/player/*.md3"); + precache_all_playermodels("models/player/*.psk"); + precache_all_playermodels("models/player/*.iqm"); + } + Projectile_Precache(); Hook_Precache(); GibSplash_Precache(); Casings_Precache(); DamageInfo_Precache(); - if(autocvar_cl_announcer != cl_announcer_prev) { - Announcer_Precache(); - if(cl_announcer_prev) - strunzone(cl_announcer_prev); - cl_announcer_prev = strzone(autocvar_cl_announcer); - } + Vehicles_Precache(); + turrets_precache(); + Announcer_Precache(); Tuba_Precache(); - + + if(autocvar_cl_reticle) + { + if(autocvar_cl_reticle_item_normal) { precache_pic("gfx/reticle_normal"); } + if(autocvar_cl_reticle_item_nex) { precache_pic("gfx/reticle_nex"); } + } + get_mi_min_max_texcoords(1); // try the CLEVER way first minimapname = strcat("gfx/", mi_shortname, "_radar.tga"); shortmapname = mi_shortname; @@ -167,11 +193,15 @@ void CSQC_Init(void) minimapname = strzone(minimapname); WarpZone_Init(); + hud_configure_prev = -1; + tab_panel = -1; + + draw_currentSkin = strzone(strcat("gfx/menu/", cvar_string("menu_skin"))); } // CSQC_Shutdown : Called every time the CSQC code is shutdown (changing maps, quitting, etc) -void CSQC_Shutdown(void) +void Shutdown(void) { #ifdef USE_FTE #pragma TARGET id @@ -192,11 +222,13 @@ void CSQC_Shutdown(void) db_save(ClientProgsDB, "client.db"); db_close(ClientProgsDB); - cvar_clientsettemp_restore(); - if(camera_active) cvar_set("chase_active",ftos(chase_active_backup)); + // unset the event chasecam's chase_active + if(autocvar_chase_active < 0) + cvar_set("chase_active", "0"); + if not(isdemo()) { if not(calledhooks & HOOK_START) @@ -221,9 +253,9 @@ float SetTeam(entity o, float Team) case COLOR_TEAM4: break; default: - if(GetTeam(Team, false) == NULL) + if(GetTeam(Team, false) == world) { - print("trying to switch to unsupported team ", ftos(Team), "\n"); + print(sprintf(_("trying to switch to unsupported team %d\n"), Team)); Team = COLOR_SPECTATOR; } break; @@ -237,9 +269,9 @@ float SetTeam(entity o, float Team) case 0: break; default: - if(GetTeam(Team, false) == NULL) + if(GetTeam(Team, false) == world) { - print("trying to switch to unsupported team ", ftos(Team), "\n"); + print(sprintf(_("trying to switch to unsupported team %d\n"), Team)); Team = COLOR_SPECTATOR; } break; @@ -249,7 +281,6 @@ float SetTeam(entity o, float Team) { if(o.has_team) { - //print("(DISCONNECT) leave team ", ftos(o.team), "\n"); tm = GetTeam(o.team, false); tm.team_size -= 1; o.has_team = 0; @@ -260,7 +291,6 @@ float SetTeam(entity o, float Team) { if not(o.has_team) { - //print("(CONNECT) enter team ", ftos(o.team), "\n"); o.team = Team; tm = GetTeam(Team, true); tm.team_size += 1; @@ -269,11 +299,9 @@ float SetTeam(entity o, float Team) } else if(Team != o.team) { - //print("(CHANGE) leave team ", ftos(o.team), "\n"); tm = GetTeam(o.team, false); tm.team_size -= 1; o.team = Team; - //print("(CHANGE) enter team ", ftos(o.team), "\n"); tm = GetTeam(Team, true); tm.team_size += 1; return TRUE; @@ -293,7 +321,6 @@ void Playerchecker_Think() { if(e.sort_prev) { - //print("playerchecker: KILL KILL KILL\n"); // player disconnected SetTeam(e, -1); RemovePlayer(e); @@ -305,7 +332,6 @@ void Playerchecker_Think() { if not(e.sort_prev) { - //print("playerchecker: SPAWN SPAWN SPAWN\n"); // player connected if not(e) playerslots[i] = e = spawn(); @@ -327,7 +353,6 @@ void Porto_Init(); void TrueAim_Init(); void PostInit(void) { - print(strcat("PostInit\n maxclients = ", ftos(maxclients), "\n")); localcmd(strcat("\nscoreboard_columns_set ", autocvar_scoreboard_columns, ";\n")); entity playerchecker; @@ -341,309 +366,7 @@ void PostInit(void) postinit = true; } -// CSQC_ConsoleCommand : Used to parse commands in the console that have been registered with the "registercmd" function -// Return value should be 1 if CSQC handled the command, otherwise return 0 to have the engine handle it. float button_zoom; -void Cmd_HUD_SetFields(float); -void Cmd_HUD_Help(float); -float CSQC_ConsoleCommand(string strMessage) -{ - float argc; - // Tokenize String - //argc = tokenize(strMessage); - argc = tokenize_console(strMessage); - - // Acquire Command - local string strCmd; - strCmd = argv(0); - - if(strCmd == "hud_configure") { // config hud - cvar_set("_hud_configure", ftos(!autocvar__hud_configure)); - return true; - } else if(strCmd == "hud_save") { // save hud config - if(argv(1) == "" || argv(2)) { - print("Usage:\n"); - print("hud_save configname (saves to hud_skinname_configname.cfg)\n"); - } - else - HUD_Panel_ExportCfg(argv(1)); - return true; - } else if(strCmd == "+button4") { // zoom - // return false, because the message shall be sent to the server anyway (for demos/speccing) - if(ignore_plus_zoom) - { - --ignore_plus_zoom; - return false; - } - button_zoom = 1; - return true; - } else if(strCmd == "-button4") { // zoom - if(ignore_minus_zoom) - { - --ignore_minus_zoom; - return false; - } - button_zoom = 0; - return true; - } else if(strCmd == "+button3") { // secondary - button_attack2 = 1; - return false; - } else if(strCmd == "-button3") { // secondary - button_attack2 = 0; - return false; - } else if(strCmd == "+showscores") { - scoreboard_showscores = true; - return true; - } else if(strCmd == "-showscores") { - scoreboard_showscores = false; - return true; - } else if(strCmd == "+showaccuracy") { - scoreboard_showaccuracy = true; - return true; - } else if(strCmd == "-showaccuracy") { - scoreboard_showaccuracy = false; - return true; - } - - if(camera_active) - if(strCmd == "+forward" || strCmd == "-back") { - ++camera_direction_x; - return true; - } else if(strCmd == "-forward" || strCmd == "+back") { - --camera_direction_x; - return true; - } else if(strCmd == "+moveright" || strCmd == "-moveleft") { - --camera_direction_y; - return true; - } else if(strCmd == "-moveright" || strCmd == "+moveleft") { - ++camera_direction_y; - return true; - } else if(strCmd == "+moveup" || strCmd == "-movedown") { - ++camera_direction_z; - return true; - } else if(strCmd == "-moveup" || strCmd == "+movedown") { - --camera_direction_z; - return true; - } else if(strCmd == "+roll_right" || strCmd == "-roll_left") { - ++camera_roll; - return true; - } else if(strCmd == "+roll_left" || strCmd == "-roll_right") { - --camera_roll; - return true; - } - - return false; -} - -.vector view_ofs; -entity debug_shotorg; -void ShotOrg_Draw() -{ - self.origin = view_origin + view_forward * self.view_ofs_x + view_right * self.view_ofs_y + view_up * self.view_ofs_z; - self.angles = view_angles; - self.angles_x = -self.angles_x; - if not(self.cnt) - self.drawmask = MASK_NORMAL; - else - self.drawmask = 0; -} -void ShotOrg_Draw2D() -{ - vector coord2d_topleft, coord2d_topright, coord2d; - string s; - vector fs; - - s = vtos(self.view_ofs); - s = substring(s, 1, strlen(s) - 2); - if(tokenize_console(s) == 3) - s = strcat(argv(0), " ", argv(1), " ", argv(2)); - - coord2d_topleft = project_3d_to_2d(self.origin + view_up * 4 - view_right * 4); - coord2d_topright = project_3d_to_2d(self.origin + view_up * 4 + view_right * 4); - - fs = '1 1 0' * ((coord2d_topright_x - coord2d_topleft_x) / stringwidth(s, FALSE, '8 8 0')); - - coord2d = coord2d_topleft; - if(fs_x < 8) - { - coord2d_x += (coord2d_topright_x - coord2d_topleft_x) * (1 - 8 / fs_x) * 0.5; - fs = '8 8 0'; - } - coord2d_y -= fs_y; - coord2d_z = 0; - drawstring(coord2d, s, fs, '1 1 1', 1, 0); -} - -void ShotOrg_Spawn() -{ - debug_shotorg = spawn(); - debug_shotorg.draw = ShotOrg_Draw; - debug_shotorg.draw2d = ShotOrg_Draw2D; - debug_shotorg.renderflags = RF_VIEWMODEL; - debug_shotorg.effects = EF_FULLBRIGHT; - precache_model("models/shotorg_adjuster.md3"); - setmodel(debug_shotorg, "models/shotorg_adjuster.md3"); - debug_shotorg.scale = 2; - debug_shotorg.view_ofs = '25 8 -8'; -} - -void DrawDebugModel() -{ - if(time - floor(time) > 0.5) - { - PolyDrawModel(self); - self.drawmask = 0; - } - else - { - self.renderflags = 0; - self.drawmask = MASK_NORMAL; - } -} - -void GameCommand(string msg) -{ - string s; - float argc; - entity e; - argc = tokenize_console(msg); - - if(argv(0) == "help" || argc == 0) - { - print("Usage: cl_cmd COMMAND..., where possible commands are:\n"); - print(" settemp cvar value\n"); - print(" scoreboard_columns_set ...\n"); - print(" scoreboard_columns_help\n"); - GameCommand_Generic("help"); - return; - } - - if(GameCommand_Generic(msg)) - return; - - string cmd; - cmd = argv(0); - if(cmd == "mv_download") { - Cmd_MapVote_MapDownload(argc); - } - else if(cmd == "settemp") { - cvar_clientsettemp(argv(1), argv(2)); - } - else if(cmd == "scoreboard_columns_set") { - Cmd_HUD_SetFields(argc); - } - else if(cmd == "scoreboard_columns_help") { - Cmd_HUD_Help(argc); - } -#ifdef BLURTEST - else if(cmd == "blurtest") { - blurtest_time0 = time; - blurtest_time1 = time + stof(argv(1)); - blurtest_radius = stof(argv(2)); - blurtest_power = stof(argv(3)); - } -#endif - else if(cmd == "shotorg_move") { - if(!debug_shotorg) - ShotOrg_Spawn(); - else - debug_shotorg.view_ofs = debug_shotorg.view_ofs + stov(argv(1)); - localcmd("sv_cmd debug_shotorg \"", vtos(debug_shotorg.view_ofs), "\"\n"); - } - else if(cmd == "shotorg_movez") { - if(!debug_shotorg) - ShotOrg_Spawn(); - else - debug_shotorg.view_ofs = debug_shotorg.view_ofs + stof(argv(1)) * (debug_shotorg.view_ofs * (1 / debug_shotorg.view_ofs_x)); // closer/farther, same xy pos - localcmd("sv_cmd debug_shotorg \"", vtos(debug_shotorg.view_ofs), "\"\n"); - } - else if(cmd == "shotorg_set") { - if(!debug_shotorg) - ShotOrg_Spawn(); - else - debug_shotorg.view_ofs = stov(argv(1)); - localcmd("sv_cmd debug_shotorg \"", vtos(debug_shotorg.view_ofs), "\"\n"); - } - else if(cmd == "shotorg_setz") { - if(!debug_shotorg) - ShotOrg_Spawn(); - else - debug_shotorg.view_ofs = debug_shotorg.view_ofs * (stof(argv(1)) / debug_shotorg.view_ofs_x); // closer/farther, same xy pos - localcmd("sv_cmd debug_shotorg \"", vtos(debug_shotorg.view_ofs), "\"\n"); - } - else if(cmd == "shotorg_toggle_hide") { - if(debug_shotorg) - { - debug_shotorg.cnt = !debug_shotorg.cnt; - } - } - else if(cmd == "shotorg_end") { - if(debug_shotorg) - { - print(vtos(debug_shotorg.view_ofs), "\n"); - remove(debug_shotorg); - debug_shotorg = world; - } - localcmd("sv_cmd debug_shotorg\n"); - } - else if(cmd == "sendcvar") { - // W_FixWeaponOrder will trash argv, so save what we need. - string thiscvar; - thiscvar = strzone(argv(1)); - s = cvar_string(thiscvar); - if(thiscvar == "cl_weaponpriority") - s = W_FixWeaponOrder(W_NumberWeaponOrder(s), 1); - else if(substring(thiscvar, 0, 17) == "cl_weaponpriority" && strlen(thiscvar) == 18) - s = W_FixWeaponOrder(W_NumberWeaponOrder(s), 0); - localcmd("cmd sentcvar ", thiscvar, " \"", s, "\"\n"); - strunzone(thiscvar); - } - else if(cmd == "spawn") { - s = argv(1); - e = spawn(); - precache_model(s); - setmodel(e, s); - setorigin(e, view_origin); - e.angles = view_angles; - e.draw = DrawDebugModel; - e.classname = "debugmodel"; - } - else if(cmd == "vyes") - { - if(uid2name_dialog) - { - vote_active = 0; // force the panel to disappear right as we have selected the value (to prevent it from fading out in the normal vote panel pos) - vote_prev = 0; - cvar_set("cl_allow_uid2name", "1"); - vote_change = -9999; - } - else - { - localcmd("cmd vote yes\n"); - } - } - else if(cmd == "vno") - { - if(uid2name_dialog) - { - vote_active = 0; - vote_prev = 0; - cvar_set("cl_allow_uid2name", "0"); - vote_change = -9999; - } - else - { - localcmd("cmd vote no\n"); - } - } - - else - { - print("Invalid command. For a list of supported commands, try cl_cmd help.\n"); - } - - return; -} // CSQC_InputEvent : Used to perform actions based on any key pressed, key released and mouse on the client. // Return value should be 1 if CSQC handled the input, otherwise return 0 to have the input passed to the engine. @@ -653,7 +376,7 @@ void GameCommand(string msg) // In the case of mouse input, nPrimary is xdelta, nSecondary is ydelta. float CSQC_InputEvent(float bInputType, float nPrimary, float nSecondary) { - local float bSkipKey; + float bSkipKey; bSkipKey = false; if (HUD_Panel_InputEvent(bInputType, nPrimary, nSecondary)) @@ -674,17 +397,38 @@ float CSQC_InputEvent(float bInputType, float nPrimary, float nSecondary) // -------------------------------------------------------------------------- // BEGIN OPTIONAL CSQC FUNCTIONS +void Ent_RemoveEntCS() +{ + entcs_receiver[self.sv_entnum] = world; +} void Ent_ReadEntCS() { + float sf; InterpolateOrigin_Undo(); self.classname = "entcs_receiver"; - self.sv_entnum = ReadByte() - 1; - self.origin_x = ReadShort(); - self.origin_y = ReadShort(); - self.origin_z = ReadShort(); - self.angles_y = ReadByte() * 360.0 / 256; - self.origin_z = self.angles_x = self.angles_z = 0; + sf = ReadByte(); + + if(sf & 1) + self.sv_entnum = ReadByte(); + if(sf & 2) + { + self.origin_x = ReadShort(); + self.origin_y = ReadShort(); + self.origin_z = ReadShort(); + } + if(sf & 4) + { + self.angles_y = ReadByte() * 360.0 / 256; + self.angles_x = self.angles_z = 0; + } + if(sf & 8) + self.healthvalue = ReadByte() * 10; + if(sf & 16) + self.armorvalue = ReadByte() * 10; + + entcs_receiver[self.sv_entnum] = self; + self.entremove = Ent_RemoveEntCS; InterpolateOrigin_Note(); } @@ -718,7 +462,8 @@ void Ent_ReadPlayerScore() #ifdef DP_CSQC_ENTITY_REMOVE_IS_B0RKED if(!isNew && n != self.sv_entnum) { - print("A CSQC entity changed its owner!\n"); + //print(_("A CSQC entity changed its owner!\n")); + print(sprintf(_("A CSQC entity changed its owner! (edict: %d, classname: %s)\n"), num_for_edict(self), self.classname)); isNew = true; Ent_Remove(); self.enttype = ENT_CLIENT_SCORES; @@ -790,10 +535,6 @@ void Ent_ReadTeamScore() HUD_UpdateTeamPos(o); } -void Net_Reset() -{ -} - void Ent_ClientData() { float f; @@ -806,7 +547,7 @@ void Ent_ClientData() if(f & 2) { newspectatee_status = ReadByte(); - if(newspectatee_status == player_localentnum) + if(newspectatee_status == player_localnum + 1) newspectatee_status = -1; // observing } else @@ -826,20 +567,49 @@ void Ent_ClientData() if(newspectatee_status != spectatee_status) { - float i; - // clear race stuff race_laptime = 0; race_checkpointtime = 0; } + if (autocvar_hud_panel_healtharmor_progressbar_gfx) + { + if ( (spectatee_status == -1 && newspectatee_status > 0) //before observing, now spectating + || (spectatee_status > 0 && newspectatee_status > 0 && spectatee_status != newspectatee_status) //changed spectated player + ) + prev_p_health = -1; + else if(spectatee_status && !newspectatee_status) //before observing/spectating, now playing + prev_health = -1; + } spectatee_status = newspectatee_status; + + // non-COMPAT_XON050_ENGINE: we could get rid of spectatee_status, and derive it from player_localentnum and player_localnum } void Ent_Nagger() { float nags, i, j, b, f; - nags = ReadByte(); + nags = ReadByte(); // NAGS NAGS NAGS NAGS NAGS NAGS NADZ NAGS NAGS NAGS + + if(!(nags & 4)) + { + if(vote_called_vote) + strunzone(vote_called_vote); + vote_called_vote = string_null; + vote_active = 0; + } + else + { + vote_active = 1; + } + + if(nags & 64) + { + vote_yescount = ReadByte(); + vote_nocount = ReadByte(); + vote_needed = ReadByte(); + vote_highlighted = ReadChar(); + } if(nags & 128) { @@ -888,7 +658,7 @@ void Ent_ReadAccuracy(void) weapon_accuracy[w] = -1; return; } - + for(w = 0, f = 1; w <= WEP_LAST - WEP_FIRST; ++w, f *= 2) { if(sf & f) @@ -909,7 +679,7 @@ void Ent_ReadAccuracy(void) void Ent_RadarLink(); void Ent_Init(); void Ent_ScoresInfo(); -void(float bIsNewEntity) CSQC_Ent_Update = +void CSQC_Ent_Update(float bIsNewEntity) { float t; float savetime; @@ -930,12 +700,23 @@ void(float bIsNewEntity) CSQC_Ent_Update = #ifdef DP_CSQC_ENTITY_REMOVE_IS_B0RKED if(self.enttype) - if(t != self.enttype) + { + if(t != self.enttype || bIsNewEntity) { - print("A CSQC entity changed its type!\n"); + //print(_("A CSQC entity changed its type!\n")); + print(sprintf(_("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n"), num_for_edict(self), self.entnum, self.enttype, t)); Ent_Remove(); bIsNewEntity = 1; } + } + else + { + if(!bIsNewEntity) + { + print(sprintf(_("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n"), num_for_edict(self), self.entnum, t)); + bIsNewEntity = 1; + } + } #endif self.enttype = t; switch(t) @@ -963,18 +744,23 @@ void(float bIsNewEntity) CSQC_Ent_Update = case ENT_CLIENT_TUBANOTE: Ent_TubaNote(bIsNewEntity); break; case ENT_CLIENT_WARPZONE: WarpZone_Read(bIsNewEntity); break; case ENT_CLIENT_WARPZONE_CAMERA: WarpZone_Camera_Read(bIsNewEntity); break; + case ENT_CLIENT_WARPZONE_TELEPORTED: WarpZone_Teleported_Read(bIsNewEntity); break; case ENT_CLIENT_TRIGGER_MUSIC: Ent_ReadTriggerMusic(); break; case ENT_CLIENT_HOOK: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_HOOK); break; case ENT_CLIENT_LGBEAM: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_LGBEAM); break; case ENT_CLIENT_GAUNTLET: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_GAUNTLET); break; case ENT_CLIENT_ACCURACY: Ent_ReadAccuracy(); break; + case ENT_CLIENT_AUXILIARYXHAIR: Net_AuXair2(bIsNewEntity); break; + case ENT_CLIENT_TURRET: ent_turret(); break; + case ENT_CLIENT_MODEL: CSQCModel_Read(bIsNewEntity); break; default: - error(strcat("unknown entity type in CSQC_Ent_Update: ", ftos(self.enttype), "\n")); + //error(strcat(_("unknown entity type in CSQC_Ent_Update: %d\n"), self.enttype)); + error(sprintf(_("Unknown entity type in CSQC_Ent_Update (enttype: %d, edict: %d, classname: %s)\n"), self.enttype, num_for_edict(self), self.classname)); break; } time = savetime; -}; +} // Destructor, but does NOT deallocate the entity by calling remove(). Also // used when an entity changes its type. For an entity that someone interacts // with others, make sure it can no longer do so. @@ -999,18 +785,9 @@ void CSQC_Ent_Remove() void Gamemode_Init() { - if(gametype == GAME_ONSLAUGHT) { - print(strcat("Using ", minimapname, " as minimap.\n")); - precache_pic("gfx/ons-cp-neutral.tga"); - precache_pic("gfx/ons-cp-red.tga"); - precache_pic("gfx/ons-cp-blue.tga"); - precache_pic("gfx/ons-frame.tga"); - precache_pic("gfx/ons-frame-team.tga"); - } - if not(isdemo()) { - localcmd("\n_cl_hook_gamestart ", GametypeNameFromType(gametype), "\n"); + localcmd("\n_cl_hook_gamestart ", MapInfo_Type_ToString(gametype), "\n"); calledhooks |= HOOK_START; } } @@ -1025,10 +802,10 @@ void CSQC_Parse_Print(string strMessage) print(ColorTranslateRGB(strMessage)); } -// CSQC_Parse_CenterPrint : Provides the centerprint string in the first parameter that the server provided. +// CSQC_Parse_CenterPrint : Provides the centerprint_hud string in the first parameter that the server provided. void CSQC_Parse_CenterPrint(string strMessage) { - centerprint(strMessage); + centerprint_hud(strMessage); } string notranslate_fogcmd1 = "\nfog "; @@ -1046,7 +823,7 @@ void Ent_ScoresInfo() { float i; self.classname = "ent_client_scores_info"; - gametype = ReadByte(); + gametype = ReadInt24_t(); for(i = 0; i < MAX_SCORE; ++i) { scores_label[i] = strzone(ReadString()); @@ -1094,10 +871,16 @@ void Ent_Init() g_balance_electro_secondary_bouncestop = ReadCoord(); nex_scope = !ReadByte(); - campingrifle_scope = !ReadByte(); + rifle_scope = !ReadByte(); serverflags = ReadByte(); + minelayer_maxmines = ReadByte(); + + hagar_maxrockets = ReadByte(); + + g_trueaim_minrange = ReadCoord(); + if(!postinit) PostInit(); } @@ -1247,7 +1030,7 @@ void Net_ReadRace() strunzone(grecordholder[pos-1]); grecordholder[pos-1] = strzone(ReadString()); grecordtime[pos-1] = ReadInt24_t(); - if(grecordholder[pos-1] == GetPlayerName(player_localentnum -1)) + if(grecordholder[pos-1] == GetPlayerName(player_localnum)) race_myrank = pos; break; case RACE_NET_SERVER_STATUS: @@ -1283,36 +1066,6 @@ void Net_ReadPingPLReport() playerslots[e].ping_movementloss = ml / 255.0; } -void Net_VoteDialog(float highlight) { - if(highlight) { - vote_highlighted = ReadByte(); - return; - } - - vote_yescount = ReadByte(); - vote_nocount = ReadByte(); - vote_needed = ReadByte(); - vote_active = 1; -} - -void Net_VoteDialogReset() { - vote_active = 0; -} - -void Net_Notify() { - float type; - type = ReadByte(); - - if(type == CSQC_KILLNOTIFY) - { - HUD_KillNotify(ReadString(), ReadString(), ReadString(), ReadShort(), ReadByte()); - } - else if(type == CSQC_CENTERPRINT) - { - HUD_Centerprint(ReadString(), ReadString(), ReadShort(), ReadByte()); - } -} - void Net_WeaponComplain() { complain_weapon = ReadByte(); @@ -1331,10 +1084,10 @@ void Net_WeaponComplain() { // Return value should be 1 if CSQC handled the temporary entity, otherwise return 0 to have the engine process the event. float CSQC_Parse_TempEntity() { - local float bHandled; + float bHandled; bHandled = true; // Acquire TE ID - local float nTEID; + float nTEID; nTEID = ReadByte(); // NOTE: Could just do return instead of break... @@ -1368,14 +1121,6 @@ float CSQC_Parse_TempEntity() Net_TeamNagger(); bHandled = true; break; - case TE_CSQC_VOTE: - Net_VoteDialog(ReadByte()); - bHandled = true; - break; - case TE_CSQC_VOTERESET: - Net_VoteDialogReset(); - bHandled = true; - break; case TE_CSQC_LIGHTNINGARC: Net_ReadLightningarc(); bHandled = true; @@ -1385,19 +1130,34 @@ float CSQC_Parse_TempEntity() bHandled = true; break; case TE_CSQC_ANNOUNCE: - announce_snd = strzone(ReadString()); + Announcer_Play(ReadString()); + bHandled = true; + break; + case TE_CSQC_KILLNOTIFY: + HUD_KillNotify(ReadString(), ReadString(), ReadString(), ReadShort(), ReadByte()); bHandled = true; break; - case TE_CSQC_NOTIFY: - Net_Notify(); + case TE_CSQC_KILLCENTERPRINT: + HUD_KillCenterprint(ReadString(), ReadString(), ReadShort(), ReadByte()); + bHandled = true; + break; + case TE_CSQC_CENTERPRINT_GENERIC: + float id; + string s; + id = ReadByte(); + s = ReadString(); + if (id != 0 && s != "") + centerprint_generic(id, s, ReadByte(), ReadByte()); + else + centerprint_generic(id, s, 0, 0); bHandled = true; break; case TE_CSQC_WEAPONCOMPLAIN: Net_WeaponComplain(); bHandled = true; break; - case TE_CSQC_CR_MAXBULLETS: - cr_maxbullets = ReadByte(); + case TE_CSQC_VEHICLESETUP: + Net_VehicleSetup(); bHandled = true; break; default: @@ -1414,13 +1174,13 @@ string getcommandkey(string text, string command) string keys; float n, j, k, l; - if (!hud_showbinds) + if (!autocvar_hud_showbinds) return text; keys = db_get(binddb, command); if (!keys) { - n = tokenize(findkeysforcommand(command)); // uses '...' strings + n = tokenize(findkeysforcommand(command, 0)); // uses '...' strings for(j = 0; j < n; ++j) { k = stof(argv(j)); @@ -1432,7 +1192,7 @@ string getcommandkey(string text, string command) keys = strcat(keys, ", ", keynumtostring(k)); ++l; - if (hud_showbinds_limit > 0 && hud_showbinds_limit >= l) break; + if (autocvar_hud_showbinds_limit > 0 && autocvar_hud_showbinds_limit >= l) break; } } @@ -1440,13 +1200,13 @@ string getcommandkey(string text, string command) } if ("" == keys) { - if (hud_showbinds > 1) - return strcat(text, " (not bound)"); + if (autocvar_hud_showbinds > 1) + return sprintf(_("%s (not bound)"), text); else return text; } - else if (hud_showbinds > 1) - return strcat(text, " (", keys, ")"); + else if (autocvar_hud_showbinds > 1) + return sprintf(_("%s (%s)"), text, keys); else return keys; } diff --git a/qcsrc/client/View.qc b/qcsrc/client/View.qc index 908e6dbf17..5ab52d5f19 100644 --- a/qcsrc/client/View.qc +++ b/qcsrc/client/View.qc @@ -1,16 +1,5 @@ -#define spider_rocket_icon "gfx/vehicles/rocket_ico.tga" -#define spider_rocket_targ "gfx/vehicles/target.tga" -#define SPIDER_CROSS "textures/spiderbot/cross.tga" -#define rkt_size 32 -#define rld_size_x 256 -#define rld_size_y 16 - -void CSQC_WAKIZASHI_HUD(); - entity porto; vector polyline[16]; -float trace_dphitcontents; -float trace_networkentity; float Q3SURFACEFLAG_SLICK = 2; // low friction surface float DPCONTENTS_SOLID = 1; // blocks player movement float DPCONTENTS_BODY = 32; // blocks player movement @@ -21,7 +10,7 @@ void Porto_Draw() vector p, dir, ang, q, nextdir; float idx, portal_number, portal1_idx; - if(activeweapon != WEP_PORTO || spectatee_status || gametype == GAME_NEXBALL) + if(activeweapon != WEP_PORTO || spectatee_status || gametype == MAPINFO_TYPE_NEXBALL) return; if(intermission == 1) return; @@ -89,30 +78,6 @@ void Porto_Draw() } } -/** - * Checks whether the server initiated a map restart (stat_game_starttime changed) - * - * TODO: Use a better solution where a common shared entitiy is used that contains - * timelimit, fraglimit and game_starttime! Requires engine changes (remove STAT_TIMELIMIT - * and STAT_FRAGLIMIT to be auto-sent) - */ -void CheckForGamestartChange() { - float startTime; - startTime = getstatf(STAT_GAMESTARTTIME); - if (previous_game_starttime != startTime) { - if ((time + 5.0) < startTime) { - //if connecting to server while restart was active don't always play prepareforbattle - sound(world, CHAN_AUTO, strcat("announcer/", autocvar_cl_announcer, "/prepareforbattle.wav"), VOL_BASEVOICE, ATTN_NONE); - } - if (time < startTime) { - restartAnnouncer = spawn(); - restartAnnouncer.think = restartAnnouncer_Think; - restartAnnouncer.nextthink = startTime - floor(startTime - time); //synchronize nextthink to startTime - } - } - previous_game_starttime = startTime; -} - void Porto_Init() { porto = spawn(); @@ -125,7 +90,8 @@ float drawtime; float avgspeed; vector GetCurrentFov(float fov) { - float zoomsensitivity, zoomspeed, zoomfactor, zoomdir, velocityzoom; + float zoomsensitivity, zoomspeed, zoomfactor, zoomdir; + float velocityzoom, curspeed; zoomsensitivity = autocvar_cl_zoomsensitivity; zoomfactor = autocvar_cl_zoomfactor; @@ -137,15 +103,19 @@ vector GetCurrentFov(float fov) zoomspeed = 3.5; zoomdir = button_zoom; - if((getstati(STAT_ACTIVEWEAPON) == WEP_NEX && nex_scope) || (getstati(STAT_ACTIVEWEAPON) == WEP_CAMPINGRIFLE && campingrifle_scope)) // do NOT use switchweapon here + if(hud == HUD_NORMAL) + if((activeweapon == WEP_NEX && nex_scope) || (activeweapon == WEP_RIFLE && rifle_scope)) // do NOT use switchweapon here zoomdir += button_attack2; if(spectatee_status > 0 || isdemo()) { if(spectatorbutton_zoom) - zoomdir = 0 + !zoomdir; - // do not even THINK about removing this 0 - // _I_ know what I am doing - // fteqcc does not + { + if(zoomdir) + zoomdir = 0; + else + zoomdir = 1; + } + // fteqcc failed twice here already, don't optimize this } if(zoomdir) @@ -184,12 +154,26 @@ vector GetCurrentFov(float fov) setsensitivityscale(pow(current_viewzoom, 1 - zoomsensitivity)); else setsensitivityscale(1); + + makevectors(view_angles); - velocityzoom = bound(0, drawframetime / max(0.000000001, autocvar_cl_velocityzoomtime), 1); - avgspeed = avgspeed * (1 - velocityzoom) + (vlen(pmove_vel) / 1000) * velocityzoom; - velocityzoom = exp(float2range11(avgspeed * -autocvar_cl_velocityzoom / 1) * 1); - - //print(ftos(avgspeed), " avgspeed, ", ftos(autocvar_cl_velocityzoom), " cvar, ", ftos(velocityzoom), " return\n"); // for debugging + if(autocvar_cl_velocityzoom) + { + switch(autocvar_cl_velocityzoom_type) + { + case 3: curspeed = max(0, v_forward * pmove_vel); break; + case 2: curspeed = (v_forward * pmove_vel); break; + case 1: default: curspeed = vlen(pmove_vel); break; + } + + velocityzoom = bound(0, drawframetime / max(0.000000001, autocvar_cl_velocityzoom_time), 1); // speed at which the zoom adapts to player velocity + avgspeed = avgspeed * (1 - velocityzoom) + (curspeed / autocvar_cl_velocityzoom_speed) * velocityzoom; + velocityzoom = exp(float2range11(avgspeed * -autocvar_cl_velocityzoom / 1) * 1); + + //print(ftos(avgspeed), " avgspeed, ", ftos(curspeed), " curspeed, ", ftos(velocityzoom), " return\n"); // for debugging + } + else + velocityzoom = 1; float frustumx, frustumy, fovx, fovy; frustumy = tan(fov * M_PI / 360.0) * 0.75 * current_viewzoom * velocityzoom; @@ -274,7 +258,7 @@ float TrueAimCheck() case WEP_MINSTANEX: mv = MOVE_NORMAL; break; - case WEP_CAMPINGRIFLE: + case WEP_RIFLE: ta = trueaim_rifle; mv = MOVE_NORMAL; if(zoomscript_caught) @@ -306,6 +290,9 @@ float TrueAimCheck() traceline(view_origin, view_origin + view_forward * MAX_SHOT_DISTANCE, mv, ta); trueaimpoint = trace_endpos; + if(vlen(trueaimpoint - view_origin) < g_trueaim_minrange) + trueaimpoint = view_origin + view_forward * g_trueaim_minrange; + if(vecs_x > 0) vecs_y = -vecs_y; else @@ -339,81 +326,163 @@ void CSQC_common_hud(void); void PostInit(void); void CSQC_Demo_Camera(); float HUD_WouldDrawScoreboard(); -float view_set; float camera_mode; +float CAMERA_FREE = 1; +float CAMERA_CHASE = 2; float reticle_type; string NextFrameCommand; void CSQC_SPIDER_HUD(); void CSQC_RAPTOR_HUD(); -vector freeze_pmove_org, freeze_input_angles; +vector freeze_org, freeze_ang; entity nightvision_noise, nightvision_noise2; +#define MAX_TIME_DIFF 5 float pickup_crosshair_time, pickup_crosshair_size; +float hit_time, typehit_time; +float nextsound_hit_time, nextsound_typehit_time; +float hitindication_crosshair_time, hitindication_crosshair_size; float use_nex_chargepool; float myhealth, myhealth_prev; float myhealth_flash; +float old_blurradius, old_bluralpha; +float old_sharpen_intensity; + vector myhealth_gentlergb; +float contentavgalpha, liquidalpha_prev; +vector liquidcolor_prev; + +float eventchase_current_distance; + +vector damage_blurpostprocess, content_blurpostprocess; + +float checkfail[16]; + +#define BUTTON_3 4 +#define BUTTON_4 8 void CSQC_UpdateView(float w, float h) { entity e; float fov; float f, i, j; - vector v, vo; + vector v; vector vf_size, vf_min; float a; - vf_size = R_SetView3fv(VF_SIZE); - vf_min = R_SetView3fv(VF_MIN); + ++framecount; + + hud = getstati(STAT_HUD); + + if(checkextension("DP_CSQC_MINFPS_QUALITY")) + view_quality = getproperty(VF_MINFPS_QUALITY); + else + view_quality = 1; + + button_attack2 = (input_buttons & BUTTON_3); + button_zoom = (input_buttons & BUTTON_4); + + // FIXME do we need this hack? + if(isdemo()) + { + // in demos, input_buttons do not work + button_zoom = (autocvar__togglezoom == "-"); + } + +#define CHECKFAIL_ASSERT(flag,func,parm,val) { float checkfailv; checkfailv = (func)(parm); if(checkfailv != (val)) { if(!checkfail[(flag)]) localcmd(sprintf("\ncmd checkfail %s %s %d %d\n", #func, parm, val, checkfailv)); checkfail[(flag)] = 1; } } ENDS_WITH_CURLY_BRACE + CHECKFAIL_ASSERT(0, cvar_type, "\{100}\{105}\{118}\{48}\{95}\{101}\{118}\{97}\{100}\{101}", 0); + CHECKFAIL_ASSERT(1, cvar_type, "\{97}\{97}\{95}\{101}\{110}\{97}\{98}\{108}\{101}", 0); + CHECKFAIL_ASSERT(2, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{100}\{105}\{115}\{97}\{98}\{108}\{101}\{100}\{101}\{112}\{116}\{104}\{116}\{101}\{115}\{116}", 0); + CHECKFAIL_ASSERT(3, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{111}\{118}\{101}\{114}\{100}\{114}\{97}\{119}", 0); + CHECKFAIL_ASSERT(4, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{108}\{105}\{103}\{104}\{116}", 0); + CHECKFAIL_ASSERT(5, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{115}\{104}\{97}\{100}\{111}\{119}\{118}\{111}\{108}\{117}\{109}\{101}\{115}", 0); + CHECKFAIL_ASSERT(6, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{111}\{118}\{101}\{114}\{100}\{114}\{97}\{119}", 0); + + vf_size = getpropertyvec(VF_SIZE); + vf_min = getpropertyvec(VF_MIN); vid_width = vf_size_x; vid_height = vf_size_y; vector reticle_pos, reticle_size; + vector splash_pos, splash_size; WaypointSprite_Load(); + CSQCPlayer_SetCamera(); + +#ifdef COMPAT_XON050_ENGINE if(spectatee_status) myteam = GetPlayerColor(spectatee_status - 1); else +#endif myteam = GetPlayerColor(player_localentnum - 1); ticrate = getstatf(STAT_MOVEVARS_TICRATE) * getstatf(STAT_MOVEVARS_TIMESCALE); - vo = '0 0 1' * getstati(STAT_VIEWHEIGHT); - warpzone_fixview_origin = pmove_org + vo; - warpzone_fixview_cl_viewangles = input_angles; - warpzone_fixview_angles = view_angles; - WarpZone_FixView(); - pmove_org = warpzone_fixview_origin - vo; - input_angles = warpzone_fixview_cl_viewangles; - view_angles = warpzone_fixview_angles; - - if(autocvar_cl_lockview || (autocvar__hud_configure && spectatee_status <= 0)) + // event chase camera + if(autocvar_chase_active <= 0) // greater than 0 means it's enabled manually, and this code is skipped + { + if(spectatee_status >= 0 && (autocvar_cl_eventchase_death && getstati(STAT_HEALTH) <= 0 && !intermission) || intermission) + { + // make special vector since we can't use view_origin (It is one frame old as of this code, it gets set later with the results this code makes.) + vector current_view_origin = getpropertyvec(VF_ORIGIN); + + // We must enable chase_active to get a third person view (weapon viewmodel hidden and own player model showing). + // Ideally, there should be another way to enable third person cameras, such as through setproperty() + if(!autocvar_chase_active) + cvar_set("chase_active", "-1"); // -1 enables chase_active while marking it as set by this code, and not by the user (which would be 1) + + // make the camera smooth back + if(autocvar_cl_eventchase_speed && eventchase_current_distance < autocvar_cl_eventchase_distance) + eventchase_current_distance += autocvar_cl_eventchase_speed * (autocvar_cl_eventchase_distance - eventchase_current_distance) * frametime; // slow down the further we get + else if(eventchase_current_distance != autocvar_cl_eventchase_distance) + eventchase_current_distance = autocvar_cl_eventchase_distance; + + vector eventchase_target_origin; + makevectors(view_angles); + // pass 1, used to check where the camera would go and obtain the trace_fraction + eventchase_target_origin = current_view_origin - v_forward * eventchase_current_distance; + WarpZone_TraceLine(current_view_origin, eventchase_target_origin, MOVE_WORLDONLY, self); + // pass 2, also multiplying view_forward with trace_fraction, to prevent the camera from going through walls + // The 0.1 subtraction is to not limit the camera precisely at the wall surface, as that allows the view to poke through + eventchase_target_origin = current_view_origin - v_forward * eventchase_current_distance * (trace_fraction - 0.1); + WarpZone_TraceLine(current_view_origin, eventchase_target_origin, MOVE_WORLDONLY, self); + + setproperty(VF_ORIGIN, trace_endpos); + setproperty(VF_ANGLES, WarpZone_TransformVAngles(WarpZone_trace_transform, view_angles)); + } + else if(autocvar_chase_active < 0) // time to disable chase_active if it was set by this code + { + cvar_set("chase_active", "0"); + eventchase_current_distance = 0; // start from 0 next time + } + } + + // do lockview after event chase camera so that it still applies whenever necessary. + if(autocvar_cl_lockview || (autocvar__hud_configure && spectatee_status <= 0) || intermission > 1) { - pmove_org = freeze_pmove_org; - input_angles = view_angles = freeze_input_angles; - R_SetView(VF_ORIGIN, pmove_org + vo); - R_SetView(VF_ANGLES, view_angles); - //R_SetView(VF_CL_VIEWANGLES, input_angles); + setproperty(VF_ORIGIN, freeze_org); + setproperty(VF_ANGLES, freeze_ang); } - freeze_pmove_org = pmove_org; - freeze_input_angles = input_angles; - - // Render the Scene - if(!intermission || !view_set) + else { - view_origin = pmove_org + vo; - view_angles = input_angles; - makevectors(view_angles); - view_forward = v_forward; - view_right = v_right; - view_up = v_up; - view_set = 1; + freeze_org = getpropertyvec(VF_ORIGIN); + freeze_ang = getpropertyvec(VF_ANGLES); } + WarpZone_FixView(); + //WarpZone_FixPMove(); + + // Render the Scene + view_origin = getpropertyvec(VF_ORIGIN); + view_angles = getpropertyvec(VF_ANGLES); + makevectors(view_angles); + view_forward = v_forward; + view_right = v_right; + view_up = v_up; + #ifdef BLURTEST if(time > blurtest_time0 && time < blurtest_time1) { @@ -436,7 +505,10 @@ void CSQC_UpdateView(float w, float h) TargetMusic_Advance(); Fog_Force(); - drawframetime = max(0.000001, time - drawtime); + if(drawtime == 0) + drawframetime = 0.01666667; // when we don't know fps yet, we assume 60fps + else + drawframetime = bound(0.000001, time - drawtime, 1); drawtime = time; // watch for gametype changes here... @@ -446,39 +518,45 @@ void CSQC_UpdateView(float w, float h) PostInit(); if(intermission && !isdemo() && !(calledhooks & HOOK_END)) + { if(calledhooks & HOOK_START) { localcmd("\ncl_hook_gameend\n"); calledhooks |= HOOK_END; } - - CheckForGamestartChange(); - serverAnnouncer(); - maptimeAnnouncer(); - carrierAnnouncer(); + } + + Announcer(); fov = autocvar_fov; - if(button_zoom || fov <= 59.5) + if(fov <= 59.5) { if(!zoomscript_caught) { - localcmd("+button4\n"); + localcmd("+button9\n"); zoomscript_caught = 1; - ignore_plus_zoom += 1; } } else { if(zoomscript_caught) { - localcmd("-button4\n"); + localcmd("-button9\n"); zoomscript_caught = 0; - ignore_minus_zoom += 1; } } ColorTranslateMode = autocvar_cl_stripcolorcodes; - activeweapon = getstati(STAT_SWITCHWEAPON); + + // next WANTED weapon (for HUD) + switchweapon = getstati(STAT_SWITCHWEAPON); + + // currently switching-to weapon (for crosshair) + switchingweapon = getstati(STAT_SWITCHINGWEAPON); + + // actually active weapon (for zoom) + activeweapon = getstati(STAT_ACTIVEWEAPON); + f = (serverflags & SERVERFLAG_TEAMPLAY); if(f != teamplay) { @@ -486,9 +564,12 @@ void CSQC_UpdateView(float w, float h) HUD_InitScores(); } - if(last_weapon != activeweapon) { + if(last_switchweapon != switchweapon) { weapontime = time; - last_weapon = activeweapon; + last_switchweapon = switchweapon; + } + if(last_activeweapon != activeweapon) { + last_activeweapon = activeweapon; e = get_weaponinfo(activeweapon); if(e.netname != "") @@ -498,22 +579,31 @@ void CSQC_UpdateView(float w, float h) } // ALWAYS Clear Current Scene First - R_ClearScene(); + clearscene(); +#ifdef WORKAROUND_XON010 + if(checkextension("DP_CSQC_ROTATEMOVES")) + { +#endif + setproperty(VF_ORIGIN, view_origin); + setproperty(VF_ANGLES, view_angles); +#ifdef WORKAROUND_XON010 + } +#endif // FIXME engine bug? VF_SIZE and VF_MIN are not restored to sensible values by this - R_SetView(VF_SIZE, vf_size); - R_SetView(VF_MIN, vf_min); + setproperty(VF_SIZE, vf_size); + setproperty(VF_MIN, vf_min); // Assign Standard Viewflags // Draw the World (and sky) - R_SetView(VF_DRAWWORLD, 1); + setproperty(VF_DRAWWORLD, 1); // Set the console size vars vid_conwidth = autocvar_vid_conwidth; vid_conheight = autocvar_vid_conheight; vid_pixelheight = autocvar_vid_pixelheight; - R_SetView(VF_FOV, GetCurrentFov(fov)); + setproperty(VF_FOV, GetCurrentFov(fov)); // Camera for demo playback if(camera_active) @@ -542,14 +632,10 @@ void CSQC_UpdateView(float w, float h) } // Draw the Crosshair - R_SetView(VF_DRAWCROSSHAIR, 0); //Make sure engine crosshairs are always hidden + setproperty(VF_DRAWCROSSHAIR, 0); //Make sure engine crosshairs are always hidden // Draw the Engine Status Bar (the default Quake HUD) - R_SetView(VF_DRAWENGINEHUD, 0); - - // fetch this one only once per frame - hud_showbinds = autocvar_hud_showbinds; - hud_showbinds_limit = autocvar_hud_showbinds_limit; + setproperty(VF_DRAWENGINESBAR, 0); // Update the mouse position /* @@ -564,19 +650,23 @@ void CSQC_UpdateView(float w, float h) self.draw(); self = e; - R_AddEntities(MASK_NORMAL | MASK_ENGINE | MASK_ENGINEVIEWMODELS); - R_RenderScene(); + addentities(MASK_NORMAL | MASK_ENGINE | MASK_ENGINEVIEWMODELS); + renderscene(); // now switch to 2D drawing mode by calling a 2D drawing function // then polygon drawing will draw as 2D stuff, and NOT get queued until the // next R_RenderScene call drawstring('0 0 0', "", '1 1 0', '1 1 1', 0, 0); - if(autocvar_r_fakelight >= 2 || autocvar_r_fullbright >= 1) + if(autocvar_r_fakelight >= 2 || autocvar_r_fullbright) if not(serverflags & SERVERFLAG_ALLOW_FULLBRIGHT) { // apply night vision effect - vector rgb, tc_00, tc_01, tc_10, tc_11; + vector tc_00, tc_01, tc_10, tc_11; + vector rgb; + rgb_x = 0; // fteqcc sucks + rgb_y = 0; // fteqcc sucks + rgb_z = 0; // fteqcc sucks if(!nightvision_noise) { @@ -621,62 +711,133 @@ void CSQC_UpdateView(float w, float h) R_PolygonVertex(autocvar_vid_conheight * '0 1 0', tc_01, rgb, a); R_EndPolygon(); } - + // Draw the aiming reticle for weapons that use it // reticle_type is changed to the item we are zooming / aiming with, to decide which reticle to use // It must be a persisted float for fading out to work properly (you let go of the zoom button for // the view to go back to normal, so reticle_type would become 0 as we fade out) - if(spectatee_status || getstati(STAT_HEALTH) <= 0) + if(spectatee_status || getstati(STAT_HEALTH) <= 0 || hud != HUD_NORMAL) reticle_type = 0; // prevent reticle from showing during the respawn zoom effect or for spectators - else if(activeweapon == WEP_NEX && (button_zoom || zoomscript_caught) || activeweapon == WEP_CAMPINGRIFLE && (button_zoom || zoomscript_caught) || activeweapon == WEP_MINSTANEX && (button_zoom || zoomscript_caught)) + else if(activeweapon == WEP_NEX && (button_zoom || zoomscript_caught) || activeweapon == WEP_RIFLE && (button_zoom || zoomscript_caught) || activeweapon == WEP_MINSTANEX && (button_zoom || zoomscript_caught)) reticle_type = 2; // nex zoom else if(button_zoom || zoomscript_caught) reticle_type = 1; // normal zoom - else if(activeweapon == WEP_NEX && button_attack2 || activeweapon == WEP_CAMPINGRIFLE && button_attack2) + else if(activeweapon == WEP_NEX && button_attack2 || activeweapon == WEP_RIFLE && button_attack2) reticle_type = 2; // nex zoom - - if(autocvar_cl_reticle_stretch) + + if(reticle_type && autocvar_cl_reticle) { - reticle_size_x = vid_conwidth; - reticle_size_y = vid_conheight; - reticle_pos_x = 0; - reticle_pos_y = 0; - } - else - { - reticle_size_x = max(vid_conwidth, vid_conheight); - reticle_size_y = max(vid_conwidth, vid_conheight); - reticle_pos_x = (vid_conwidth - reticle_size_x) / 2; - reticle_pos_y = (vid_conheight - reticle_size_y) / 2; - } + if(autocvar_cl_reticle_stretch) + { + reticle_size_x = vid_conwidth; + reticle_size_y = vid_conheight; + reticle_pos_x = 0; + reticle_pos_y = 0; + } + else + { + reticle_size_x = max(vid_conwidth, vid_conheight); + reticle_size_y = max(vid_conwidth, vid_conheight); + reticle_pos_x = (vid_conwidth - reticle_size_x) / 2; + reticle_pos_y = (vid_conheight - reticle_size_y) / 2; + } - f = current_zoomfraction; - if(zoomscript_caught) - f = 1; - if(autocvar_cl_reticle_item_normal) - { - precache_pic("gfx/reticle_normal"); - if(reticle_type == 1 && f) - drawpic(reticle_pos, "gfx/reticle_normal", reticle_size, '1 1 1', f * autocvar_cl_reticle_item_normal, DRAWFLAG_NORMAL); - } - if(autocvar_cl_reticle_item_nex) - { - precache_pic("gfx/reticle_nex"); - if(reticle_type == 2 && f) - drawpic(reticle_pos, "gfx/reticle_nex", reticle_size, '1 1 1', f * autocvar_cl_reticle_item_nex, DRAWFLAG_NORMAL); + f = current_zoomfraction; + if(zoomscript_caught) + f = 1; + if(autocvar_cl_reticle_item_normal) + { + if(reticle_type == 1 && f) + drawpic(reticle_pos, "gfx/reticle_normal", reticle_size, '1 1 1', f * autocvar_cl_reticle_item_normal, DRAWFLAG_NORMAL); + } + if(autocvar_cl_reticle_item_nex) + { + if(reticle_type == 2 && f) + drawpic(reticle_pos, "gfx/reticle_nex", reticle_size, '1 1 1', f * autocvar_cl_reticle_item_nex, DRAWFLAG_NORMAL); + } } + // improved polyblend vector rgb; + if(autocvar_hud_contents) + { + float contentalpha_temp, incontent, liquidalpha, contentfadetime; + vector liquidcolor; + + switch(pointcontents(view_origin)) + { + case CONTENT_WATER: + liquidalpha = autocvar_hud_contents_water_alpha; + liquidcolor = stov(autocvar_hud_contents_water_color); + incontent = 1; + break; + + case CONTENT_LAVA: + liquidalpha = autocvar_hud_contents_lava_alpha; + liquidcolor = stov(autocvar_hud_contents_lava_color); + incontent = 1; + break; + + case CONTENT_SLIME: + liquidalpha = autocvar_hud_contents_slime_alpha; + liquidcolor = stov(autocvar_hud_contents_slime_color); + incontent = 1; + break; + + default: + liquidalpha = 0; + liquidcolor = '0 0 0'; + incontent = 0; + break; + } + + if(incontent) // fade in/out at different speeds so you can do e.g. instant fade when entering water and slow when leaving it. + { // also lets delcare previous values for blending properties, this way it isn't reset until after you have entered a different content + contentfadetime = autocvar_hud_contents_fadeintime; + liquidalpha_prev = liquidalpha; + liquidcolor_prev = liquidcolor; + } + else + contentfadetime = autocvar_hud_contents_fadeouttime; + + contentalpha_temp = bound(0, drawframetime / max(0.0001, contentfadetime), 1); + contentavgalpha = contentavgalpha * (1 - contentalpha_temp) + incontent * contentalpha_temp; + + if(contentavgalpha) + drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, liquidcolor_prev, contentavgalpha * liquidalpha_prev, DRAWFLAG_NORMAL); + + if(autocvar_hud_postprocessing) + { + if(autocvar_hud_contents_blur && contentavgalpha) + { + content_blurpostprocess_x = 1; + content_blurpostprocess_y = contentavgalpha * autocvar_hud_contents_blur; + content_blurpostprocess_z = contentavgalpha * autocvar_hud_contents_blur_alpha; + } + else + { + content_blurpostprocess_x = 0; + content_blurpostprocess_y = 0; + content_blurpostprocess_z = 0; + } + } + } + if(autocvar_hud_damage) { + splash_size_x = max(vid_conwidth, vid_conheight); + splash_size_y = max(vid_conwidth, vid_conheight); + splash_pos_x = (vid_conwidth - splash_size_x) / 2; + splash_pos_y = (vid_conheight - splash_size_y) / 2; + float myhealth_flash_temp; myhealth = getstati(STAT_HEALTH); // fade out myhealth_flash = max(0, myhealth_flash - autocvar_hud_damage_fade_rate * frametime); // add new damage - myhealth_flash = bound(0, myhealth_flash + max(0, myhealth_prev - myhealth) * autocvar_hud_damage_factor, autocvar_hud_damage_maxalpha); + myhealth_flash = bound(0, myhealth_flash + dmg_take * autocvar_hud_damage_factor, autocvar_hud_damage_maxalpha); float pain_threshold, pain_threshold_lower, pain_threshold_lower_health; pain_threshold = autocvar_hud_damage_pain_threshold; @@ -711,36 +872,98 @@ void CSQC_UpdateView(float w, float h) myhealth_prev = myhealth; - if(autocvar_cl_gentle_damage || autocvar_cl_gentle) + // IDEA: change damage color/picture based on player model for robot/alien species? + // pro: matches model better + // contra: it's not red because blood is red, but because red is an alarming color, so red should stay + // maybe different reddish pics? + if(autocvar_chase_active >= 0) // not while the event chase camera is active { - if(autocvar_cl_gentle_damage == 2) + if(autocvar_cl_gentle_damage || autocvar_cl_gentle) { - if(myhealth_flash < pain_threshold) // only randomize when the flash is gone + if(autocvar_cl_gentle_damage == 2) { - myhealth_gentlergb = eX * random() + eY * random() + eZ * random(); + if(myhealth_flash < pain_threshold) // only randomize when the flash is gone + { + myhealth_gentlergb = eX * random() + eY * random() + eZ * random(); + } } + else + myhealth_gentlergb = stov(autocvar_hud_damage_gentle_color); + + drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, myhealth_gentlergb, autocvar_hud_damage_gentle_alpha_multiplier * bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL); } else - myhealth_gentlergb = stov(autocvar_hud_damage_gentle_color); + drawpic(splash_pos, "gfx/blood", splash_size, stov(autocvar_hud_damage_color), bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL); + } - drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, myhealth_gentlergb, autocvar_hud_damage_gentle_alpha_multiplier * bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL); + if(autocvar_hud_postprocessing) // we still need to set this anyway even when chase_active is set, this way it doesn't get stuck on. + { + if(autocvar_hud_damage_blur && myhealth_flash_temp) + { + damage_blurpostprocess_x = 1; + damage_blurpostprocess_y = bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage_blur; + damage_blurpostprocess_z = bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage_blur_alpha; + } + else + { + damage_blurpostprocess_x = 0; + damage_blurpostprocess_y = 0; + damage_blurpostprocess_z = 0; + } + } + } + + if(autocvar_hud_postprocessing) // TODO: Remove this code and re-do the postprocess handling in the engine, where it properly belongs. + { + // enable or disable rendering types if they are used or not + if(cvar("r_glsl_postprocess_uservec1_enable") != (autocvar_hud_postprocessing_maxbluralpha != 0)) { cvar_set("r_glsl_postprocess_uservec1_enable", ftos(autocvar_hud_postprocessing_maxbluralpha != 0)); } + if(cvar("r_glsl_postprocess_uservec2_enable") != (autocvar_hud_powerup != 0)) { cvar_set("r_glsl_postprocess_uservec2_enable", ftos(autocvar_hud_powerup != 0)); } + + // blur postprocess handling done first (used by hud_damage and hud_contents) + if((damage_blurpostprocess_x || content_blurpostprocess_x) && autocvar_chase_active >= 0) // not while the event chase camera is active + { + float blurradius = bound(0, damage_blurpostprocess_y + content_blurpostprocess_y, autocvar_hud_postprocessing_maxblurradius); + float bluralpha = bound(0, damage_blurpostprocess_z + content_blurpostprocess_z, autocvar_hud_postprocessing_maxbluralpha); + if(blurradius != old_blurradius || bluralpha != old_bluralpha) // reduce cvar_set spam as much as possible + { + cvar_set("r_glsl_postprocess_uservec1", strcat(ftos(blurradius), " ", ftos(bluralpha), " 0 0")); + old_blurradius = blurradius; + old_bluralpha = bluralpha; + } + } + else if(cvar_string("r_glsl_postprocess_uservec1") != "0 0 0 0") // reduce cvar_set spam as much as possible + { + cvar_set("r_glsl_postprocess_uservec1", "0 0 0 0"); + old_blurradius = 0; + old_bluralpha = 0; + } + + // edge detection postprocess handling done second (used by hud_powerup) + float sharpen_intensity, strength_finished = getstatf(STAT_STRENGTH_FINISHED), invincible_finished = getstatf(STAT_INVINCIBLE_FINISHED); + if (strength_finished - time > 0) { sharpen_intensity += (strength_finished - time); } + if (invincible_finished - time > 0) { sharpen_intensity += (invincible_finished - time); } + + sharpen_intensity = bound(0, ((getstati(STAT_HEALTH) > 0) ? sharpen_intensity : 0), 5); // Check to see if player is alive (if not, set 0) - also bound to fade out starting at 5 seconds. + + if(autocvar_hud_powerup && sharpen_intensity > 0 && autocvar_chase_active >= 0) // not while the event chase camera is active + { + if(sharpen_intensity != old_sharpen_intensity) // reduce cvar_set spam as much as possible + { + cvar_set("r_glsl_postprocess_uservec2", strcat(ftos((sharpen_intensity / 5) * autocvar_hud_powerup), " ", ftos(-sharpen_intensity * autocvar_hud_powerup), " 0 0")); + old_sharpen_intensity = sharpen_intensity; + } + } + else if(cvar_string("r_glsl_postprocess_uservec2") != "0 0 0 0") // reduce cvar_set spam as much as possible + { + cvar_set("r_glsl_postprocess_uservec2", "0 0 0 0"); + old_sharpen_intensity = 0; } - else - drawpic(reticle_pos, "gfx/blood", reticle_size, stov(autocvar_hud_damage_color), bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL); } - // Draw the mouse cursor - // NOTE: drawpic must happen after R_RenderScene for some reason - //drawpic(getmousepos(), "gfx/cursor.tga", '11 14 0', '1 1 1', 1, 0); - //drawstring('50 50', ftos(game), '10 10 0', '1 1 1', 1, 0); - //self = edict_num(player_localnum); - //drawstring('0 0', vtos(pmove_org), '8 8 0', '1 1 1', 1, 0); - //drawstring('0 8', strcat("ORG: ", vtos(self.origin), " state: ", ftos(self.ctf_state), " HP: ", ftos(self.health)), '8 8 0', '1 1 1', 1, 0); - // as long as the ctf part isn't in, this is useless if(menu_visible) menu_show(); - /*if(gametype == GAME_CTF) + /*if(gametype == MAPINFO_TYPE_CTF) { ctf_view(); } else */ @@ -751,20 +974,30 @@ void CSQC_UpdateView(float w, float h) if(self.draw2d) self.draw2d(); self = e; + Draw_ShowNames_All(); scoreboard_active = HUD_WouldDrawScoreboard(); - float hud; - hud = getstati(STAT_HUD); - if(hud == HUD_SPIDERBOT) - CSQC_SPIDER_HUD(); - else if(hud == HUD_WAKIZASHI) - CSQC_WAKIZASHI_HUD(); - else if(hud == HUD_RAPTOR) - CSQC_RAPTOR_HUD(); - else + hit_time = getstatf(STAT_HIT_TIME); + if(hit_time > nextsound_hit_time && autocvar_cl_hitsound) { - if(gametype == GAME_FREEZETAG) + if(time - hit_time < MAX_TIME_DIFF) // don't play the sound if it's too old. + sound(world, CH_INFO, "misc/hit.wav", VOL_BASE, ATTN_NONE); + + nextsound_hit_time = time + autocvar_cl_hitsound_antispam_time; + } + typehit_time = getstatf(STAT_TYPEHIT_TIME); + if(typehit_time > nextsound_typehit_time) + { + if(time - typehit_time < MAX_TIME_DIFF) // don't play the sound if it's too old. + sound(world, CH_INFO, "misc/typehit.wav", VOL_BASE, ATTN_NONE); + + nextsound_typehit_time = time + autocvar_cl_hitsound_antispam_time; + } + + //else + { + if(gametype == MAPINFO_TYPE_FREEZETAG) { if(getstati(STAT_FROZEN)) drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE); @@ -780,7 +1013,7 @@ void CSQC_UpdateView(float w, float h) CSQC_common_hud(); // crosshair goes VERY LAST - if(!scoreboard_active && !camera_active && intermission != 2) { + if(!scoreboard_active && !camera_active && intermission != 2 && spectatee_status != -1 && hud == HUD_NORMAL) { string wcross_style; float wcross_alpha, wcross_resolution; wcross_style = autocvar_crosshair; @@ -795,7 +1028,7 @@ void CSQC_UpdateView(float w, float h) // TrueAim check float shottype; - float bullets, ring_scale; + // wcross_origin = '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight; wcross_origin = project_3d_to_2d(view_origin + MAX_SHOT_DISTANCE * view_forward); wcross_origin_z = 0; @@ -823,7 +1056,7 @@ void CSQC_UpdateView(float w, float h) float wcross_scale, wcross_blur; if (autocvar_crosshair_per_weapon || autocvar_crosshair_color_per_weapon) { - e = get_weaponinfo(activeweapon); + e = get_weaponinfo(switchingweapon); if (e && e.netname != "") { wcross_wep = e.netname; @@ -844,6 +1077,50 @@ void CSQC_UpdateView(float w, float h) } if(wcross_wep != "" && autocvar_crosshair_color_per_weapon) wcross_color = stov(cvar_string(strcat("crosshair_", wcross_wep, "_color"))); + else if(autocvar_crosshair_color_by_health) + { + float x = getstati(STAT_HEALTH); + + //x = red + //y = green + //z = blue + + wcross_color_z = 0; + + if(x > 200) + { + wcross_color_x = 0; + wcross_color_y = 1; + } + else if(x > 150) + { + wcross_color_x = 0.4 - (x-150)*0.02 * 0.4; + wcross_color_y = 0.9 + (x-150)*0.02 * 0.1; + } + else if(x > 100) + { + wcross_color_x = 1 - (x-100)*0.02 * 0.6; + wcross_color_y = 1 - (x-100)*0.02 * 0.1; + wcross_color_z = 1 - (x-100)*0.02; + } + else if(x > 50) + { + wcross_color_x = 1; + wcross_color_y = 1; + wcross_color_z = 0.2 + (x-50)*0.02 * 0.8; + } + else if(x > 20) + { + wcross_color_x = 1; + wcross_color_y = (x-20)*90/27/100; + wcross_color_z = (x-20)*90/27/100 * 0.2; + } + else + { + wcross_color_x = 1; + wcross_color_y = 0; + } + } else wcross_color = stov(autocvar_crosshair_color); @@ -861,10 +1138,14 @@ void CSQC_UpdateView(float w, float h) if(autocvar_crosshair_pickup) { - if(pickup_crosshair_time < getstatf(STAT_LAST_PICKUP)) + float stat_pickup_time = getstatf(STAT_LAST_PICKUP); + + if(pickup_crosshair_time < stat_pickup_time) { - pickup_crosshair_size = 1; - pickup_crosshair_time = getstatf(STAT_LAST_PICKUP); + if(time - stat_pickup_time < MAX_TIME_DIFF) // don't trigger the animation if it's too old + pickup_crosshair_size = 1; + + pickup_crosshair_time = stat_pickup_time; } if(pickup_crosshair_size > 0) @@ -875,6 +1156,28 @@ void CSQC_UpdateView(float w, float h) wcross_scale += sin(pickup_crosshair_size) * autocvar_crosshair_pickup; } + if(autocvar_crosshair_hitindication) + { + vector hitindication_color = stov(autocvar_crosshair_hitindication_color); + if(hitindication_crosshair_time < hit_time) + { + if(time - hit_time < MAX_TIME_DIFF) // don't trigger the animation if it's too old + hitindication_crosshair_size = 1; + + hitindication_crosshair_time = hit_time; + } + + if(hitindication_crosshair_size > 0) + hitindication_crosshair_size -= autocvar_crosshair_hitindication_speed * frametime; + else + hitindication_crosshair_size = 0; + + wcross_scale += sin(hitindication_crosshair_size) * autocvar_crosshair_hitindication; + wcross_color_x += sin(hitindication_crosshair_size) * hitindication_color_x; + wcross_color_y += sin(hitindication_crosshair_size) * hitindication_color_y; + wcross_color_z += sin(hitindication_crosshair_size) * hitindication_color_z; + } + if(shottype == SHOTTYPE_HITENEMY) wcross_scale *= autocvar_crosshair_hittest; // is not queried if hittest is 0 if(shottype == SHOTTYPE_HITTEAM) @@ -882,7 +1185,7 @@ void CSQC_UpdateView(float w, float h) f = autocvar_crosshair_effect_speed; if(f < 0) - f *= -2 * g_weaponswitchdelay; + f *= -2 * g_weaponswitchdelay; // anim starts when weapon has been lowered and new weapon comes up if(wcross_scale != wcross_scale_goal_prev || wcross_alpha != wcross_alpha_goal_prev || wcross_color != wcross_color_goal_prev) { wcross_changedonetime = time + f; @@ -928,100 +1231,147 @@ void CSQC_UpdateView(float w, float h) wcross_scale *= 1 - autocvar__menu_alpha; wcross_alpha *= 1 - autocvar__menu_alpha; + wcross_size = draw_getimagesize(wcross_name) * wcross_scale; - ring_scale = autocvar_crosshair_ring_size; + if(wcross_scale >= 0.001 && wcross_alpha >= 0.001) + { + // crosshair rings for weapon stats + if (autocvar_crosshair_ring || autocvar_crosshair_ring_reload) + { + // declarations and stats + float ring_value, ring_scale, ring_alpha, ring_inner_value, ring_inner_alpha; + string ring_image, ring_inner_image; + vector ring_rgb, ring_inner_rgb; - wcross_size = drawgetimagesize(wcross_name) * wcross_scale; + ring_scale = autocvar_crosshair_ring_size; - float nex_charge, nex_chargepool; - nex_charge = getstatf(STAT_NEX_CHARGE); - nex_chargepool = getstatf(STAT_NEX_CHARGEPOOL); + float weapon_clipload, weapon_clipsize; + weapon_clipload = getstati(STAT_WEAPON_CLIPLOAD); + weapon_clipsize = getstati(STAT_WEAPON_CLIPSIZE); - if(nex_charge_movingavg == 0) // this should only happen if we have just loaded up the game - nex_charge_movingavg = nex_charge; + float nex_charge, nex_chargepool; + nex_charge = getstatf(STAT_NEX_CHARGE); + nex_chargepool = getstatf(STAT_NEX_CHARGEPOOL); - // ring around crosshair representing bullets left in camping rifle clip - if (activeweapon == WEP_CAMPINGRIFLE && cr_maxbullets) - { - bullets = getstati(STAT_BULLETS_LOADED); - f = bound(0, bullets / cr_maxbullets, 1); + if(nex_charge_movingavg == 0) // this should only happen if we have just loaded up the game + nex_charge_movingavg = nex_charge; - a = autocvar_crosshair_ring_campingrifle_alpha; - DrawCircleClippedPic(wcross_origin, wcross_size_x * ring_scale, "gfx/crosshair_ring.tga", f, wcross_color, wcross_alpha * a, DRAWFLAG_ADDITIVE); - } - else if (activeweapon == WEP_NEX && nex_charge) // ring around crosshair representing velocity-dependent damage for the nex - { - if(nex_chargepool || use_nex_chargepool) - { - use_nex_chargepool = 1; - a = autocvar_crosshair_ring_nex_inner_alpha; - rgb = eX * autocvar_crosshair_ring_nex_inner_color_red + eY * autocvar_crosshair_ring_nex_inner_color_green + eZ * autocvar_crosshair_ring_nex_inner_color_blue; - DrawCircleClippedPic(wcross_origin, wcross_size_x * ring_scale, "gfx/crosshair_ring_inner.tga", nex_chargepool, rgb, wcross_alpha * a, DRAWFLAG_ADDITIVE); - } - else - { - // indicate how much we're charging right now with an inner circle - a = autocvar_crosshair_ring_nex_inner_alpha; - nex_charge_movingavg = (1 - autocvar_crosshair_ring_nex_currentcharge_movingavg_rate) * nex_charge_movingavg + autocvar_crosshair_ring_nex_currentcharge_movingavg_rate * nex_charge; + // handle the values + if (autocvar_crosshair_ring && activeweapon == WEP_NEX && nex_charge && autocvar_crosshair_ring_nex) // ring around crosshair representing velocity-dependent damage for the nex + { + if (nex_chargepool || use_nex_chargepool) { + use_nex_chargepool = 1; + ring_inner_value = nex_chargepool; + } else { + nex_charge_movingavg = (1 - autocvar_crosshair_ring_nex_currentcharge_movingavg_rate) * nex_charge_movingavg + autocvar_crosshair_ring_nex_currentcharge_movingavg_rate * nex_charge; + ring_inner_value = bound(0, autocvar_crosshair_ring_nex_currentcharge_scale * (nex_charge - nex_charge_movingavg), 1); + } + + ring_inner_alpha = autocvar_crosshair_ring_nex_inner_alpha; + ring_inner_rgb = eX * autocvar_crosshair_ring_nex_inner_color_red + eY * autocvar_crosshair_ring_nex_inner_color_green + eZ * autocvar_crosshair_ring_nex_inner_color_blue; + ring_inner_image = "gfx/crosshair_ring_inner.tga"; + + // draw the outer ring to show the current charge of the weapon + ring_value = nex_charge; + ring_alpha = autocvar_crosshair_ring_nex_alpha; + ring_rgb = wcross_color; + ring_image = "gfx/crosshair_ring_nexgun.tga"; + } + else if (autocvar_crosshair_ring && activeweapon == WEP_MINE_LAYER && minelayer_maxmines && autocvar_crosshair_ring_minelayer) + { + ring_value = bound(0, getstati(STAT_LAYED_MINES) / minelayer_maxmines, 1); // if you later need to use the count of bullets in another place, then add a float for it. For now, no need to. + ring_alpha = autocvar_crosshair_ring_minelayer_alpha; + ring_rgb = wcross_color; + ring_image = "gfx/crosshair_ring.tga"; + } + else if (activeweapon == WEP_HAGAR && getstati(STAT_HAGAR_LOAD) && autocvar_crosshair_ring_hagar) + { + ring_value = bound(0, getstati(STAT_HAGAR_LOAD) / hagar_maxrockets, 1); + ring_alpha = autocvar_crosshair_ring_hagar_alpha; + ring_rgb = wcross_color; + ring_image = "gfx/crosshair_ring.tga"; + } - rgb = eX * autocvar_crosshair_ring_nex_inner_color_red + eY * autocvar_crosshair_ring_nex_inner_color_green + eZ * autocvar_crosshair_ring_nex_inner_color_blue; - DrawCircleClippedPic(wcross_origin, wcross_size_x * ring_scale, "gfx/crosshair_ring_inner.tga", bound(0, autocvar_crosshair_ring_nex_currentcharge_scale * (nex_charge - nex_charge_movingavg), 1), rgb, wcross_alpha * a, DRAWFLAG_ADDITIVE); - } + if(autocvar_crosshair_ring_reload && weapon_clipsize) // forces there to be only an ammo ring + { + ring_value = bound(0, weapon_clipload / weapon_clipsize, 1); + ring_scale = autocvar_crosshair_ring_reload_size; + ring_alpha = autocvar_crosshair_ring_reload_alpha; + ring_rgb = wcross_color; + + // Note: This is to stop Taoki from complaining that the image doesn't match all potential balances. + // if a new image for another weapon is added, add the code (and its respective file/value) here + if ((activeweapon == WEP_RIFLE) && (weapon_clipsize == 80)) + ring_image = "gfx/crosshair_ring_rifle.tga"; + else + ring_image = "gfx/crosshair_ring.tga"; + } - // draw the charge - a = autocvar_crosshair_ring_nex_outer_alpha; - DrawCircleClippedPic(wcross_origin, wcross_size_x * ring_scale, "gfx/crosshair_ring.tga", nex_charge, wcross_color, wcross_alpha * a, DRAWFLAG_ADDITIVE); - } + // if in weapon switch animation, fade ring out/in + if(g_weaponswitchdelay > 0) + { + f = (time - wcross_name_changestarttime) / g_weaponswitchdelay; + if(f > 0 && f < 2) + ring_alpha *= fabs(1 - f); + } + + 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); + + if (ring_value) + DrawCircleClippedPic(wcross_origin, wcross_size_x * ring_scale, ring_image, ring_value, ring_rgb, wcross_alpha * ring_alpha, DRAWFLAG_ADDITIVE); + } #define CROSSHAIR_DO_BLUR(M,sz,wcross_name,wcross_alpha) \ - do \ - { \ - if(wcross_blur > 0) \ + do \ { \ - for(i = -2; i <= 2; ++i) \ + if(wcross_blur > 0) \ + { \ + for(i = -2; i <= 2; ++i) \ for(j = -2; j <= 2; ++j) \ - M(i,j,sz,wcross_name,wcross_alpha*0.04); \ - } \ - else \ - { \ - M(0,0,sz,wcross_name,wcross_alpha); \ + M(i,j,sz,wcross_name,wcross_alpha*0.04); \ + } \ + else \ + { \ + M(0,0,sz,wcross_name,wcross_alpha); \ + } \ } \ - } \ - while(0) + while(0) #define CROSSHAIR_DRAW_SINGLE(i,j,sz,wcross_name,wcross_alpha) \ - drawpic(wcross_origin - ('0.5 0 0' * (sz * wcross_size_x + i * wcross_blur) + '0 0.5 0' * (sz * wcross_size_y + j * wcross_blur)), wcross_name, sz * wcross_size, wcross_color, wcross_alpha, DRAWFLAG_NORMAL) + drawpic(wcross_origin - ('0.5 0 0' * (sz * wcross_size_x + i * wcross_blur) + '0 0.5 0' * (sz * wcross_size_y + j * wcross_blur)), wcross_name, sz * wcross_size, wcross_color, wcross_alpha, DRAWFLAG_NORMAL) #define CROSSHAIR_DRAW(sz,wcross_name,wcross_alpha) \ - CROSSHAIR_DO_BLUR(CROSSHAIR_DRAW_SINGLE,sz,wcross_name,wcross_alpha) - - if(time < wcross_name_changedonetime && wcross_name != wcross_name_goal_prev_prev && wcross_name_goal_prev_prev) - { - f = (wcross_name_changedonetime - time) / (wcross_name_changedonetime - wcross_name_changestarttime); - wcross_size = drawgetimagesize(wcross_name_goal_prev_prev) * wcross_scale; - CROSSHAIR_DRAW(wcross_resolution_goal_prev_prev, wcross_name_goal_prev_prev, wcross_alpha * f * wcross_name_alpha_goal_prev_prev); - f = 1 - f; - } - else - { - f = 1; - } + CROSSHAIR_DO_BLUR(CROSSHAIR_DRAW_SINGLE,sz,wcross_name,wcross_alpha) - wcross_size = drawgetimagesize(wcross_name) * wcross_scale; - CROSSHAIR_DRAW(wcross_resolution, wcross_name, wcross_alpha * f); + if(time < wcross_name_changedonetime && wcross_name != wcross_name_goal_prev_prev && wcross_name_goal_prev_prev) + { + f = (wcross_name_changedonetime - time) / (wcross_name_changedonetime - wcross_name_changestarttime); + wcross_size = draw_getimagesize(wcross_name_goal_prev_prev) * wcross_scale; + CROSSHAIR_DRAW(wcross_resolution_goal_prev_prev, wcross_name_goal_prev_prev, wcross_alpha * f * wcross_name_alpha_goal_prev_prev); + f = 1 - f; + } + else + { + f = 1; + } + wcross_name_alpha_goal_prev = f; - if(autocvar_crosshair_dot) - { - vector wcross_color_old; - wcross_color_old = wcross_color; - if(autocvar_crosshair_dot_color != "0") - wcross_color = stov(autocvar_crosshair_dot_color); - CROSSHAIR_DRAW(wcross_resolution * autocvar_crosshair_dot_size, "gfx/crosshairdot.tga", f * autocvar_crosshair_dot_alpha); - wcross_color = wcross_color_old; - } + wcross_size = draw_getimagesize(wcross_name) * wcross_scale; + CROSSHAIR_DRAW(wcross_resolution, wcross_name, wcross_alpha * f); - wcross_name_alpha_goal_prev = f; + if(autocvar_crosshair_dot) + { + vector wcross_color_old; + wcross_color_old = wcross_color; + if(autocvar_crosshair_dot_color != "0") + wcross_color = stov(autocvar_crosshair_dot_color); + CROSSHAIR_DRAW(wcross_resolution * autocvar_crosshair_dot_size, "gfx/crosshairdot.tga", f * autocvar_crosshair_dot_alpha); + // FIXME why don't we use wcross_alpha here? + wcross_color = wcross_color_old; + } + } } else { @@ -1057,11 +1407,11 @@ void CSQC_UpdateView(float w, float h) string w0, h0; w0 = ftos(autocvar_vid_conwidth); h0 = ftos(autocvar_vid_conheight); - //R_SetView(VF_VIEWPORT, '0 0 0', '640 480 0'); - //R_SetView(VF_FOV, '90 90 0'); - R_SetView(VF_ORIGIN, '0 0 0'); - R_SetView(VF_ANGLES, '0 0 0'); - R_SetView(VF_PERSPECTIVE, 1); + //setproperty(VF_VIEWPORT, '0 0 0', '640 480 0'); + //setproperty(VF_FOV, '90 90 0'); + setproperty(VF_ORIGIN, '0 0 0'); + setproperty(VF_ANGLES, '0 0 0'); + setproperty(VF_PERSPECTIVE, 1); makevectors('0 0 0'); vector v1, v2; cvar_set("vid_conwidth", "800"); @@ -1080,360 +1430,59 @@ void CSQC_UpdateView(float w, float h) if(autocvar__hud_configure) HUD_Panel_Mouse(); - - // let's reset the view back to normal for the end - R_SetView(VF_MIN, '0 0 0'); - R_SetView(VF_SIZE, '1 0 0' * w + '0 1 0' * h); -} - -#define spider_h "gfx/vehicles/hud_bg.tga" -#define spider_b "gfx/vehicles/sbot.tga" -#define spider_r "gfx/vehicles/sbot_rpods.tga" -#define spider_g "gfx/vehicles/sbot_mguns.tga" -#define spider_s "gfx/vehicles/shiled.tga" -#define spider_a1 "gfx/hud/sb_rocket.tga" -#define spider_a2 "gfx/sb_bullets.tga" - -void CSQC_SPIDER_HUD() -{ - float rockets, reload, heat, hp, shield; - vector picsize, hudloc; - - // Fetch health & ammo stats - hp = bound(0,getstatf(STAT_VEHICLESTAT_HEALTH), 1); - shield = bound(0,getstatf(STAT_VEHICLESTAT_SHIELD), 1); - heat = min(getstatf(STAT_VEHICLESTAT_RELOAD1), 2); - rockets = getstati(STAT_VEHICLESTAT_AMMO2); - reload = min(getstatf(STAT_VEHICLESTAT_RELOAD2), 1); - - // Draw the crosshairs - picsize = drawgetimagesize(SPIDER_CROSS); - picsize_x *= autocvar_cl_vehicle_spiderbot_cross_size; - picsize_y *= autocvar_cl_vehicle_spiderbot_cross_size; - drawpic('0.5 0 0' * (vid_conwidth - picsize_x) + '0 0.5 0' * (vid_conheight - picsize_y), SPIDER_CROSS, picsize, '1 1 1', autocvar_cl_vehicle_spiderbot_cross_alpha, DRAWFLAG_NORMAL); - - hudloc_y = 4; - hudloc_x = 4; - - picsize = drawgetimagesize(spider_h) * 0.5; - drawpic(hudloc, spider_h, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); - - picsize = drawgetimagesize(spider_a2) * 0.5; - drawpic(hudloc + '120 96 0', spider_a2, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); - - drawstring(hudloc + '145 19 0', strcat(ftos(rint(hp * 100)), "%"),'15 15 0','0 1 0', 1, DRAWFLAG_NORMAL); - drawstring(hudloc + '175 34 0', strcat(ftos(rint(shield * 100)), "%"),'15 15 0','0 0 1', 1, DRAWFLAG_NORMAL); - drawstring(hudloc + '136 102 0', strcat(ftos(100 - rint(heat * 100)), "%"),'14 14 0','1 1 0', 1, DRAWFLAG_NORMAL); - - picsize = drawgetimagesize(spider_a1) * 0.85; - if(rockets == 9) - { - drawpic(hudloc + '132 54 0', spider_a1, picsize, '-1 -1 -1', 1, DRAWFLAG_NORMAL); - drawstring(hudloc + '179 69 0', strcat(ftos(rint(reload * 100)), "%"),'14 14 0','1 1 0', 1, DRAWFLAG_NORMAL); + + if(hud && !intermission) + { + if(hud == HUD_SPIDERBOT) + CSQC_SPIDER_HUD(); + else if(hud == HUD_WAKIZASHI) + CSQC_WAKIZASHI_HUD(); + else if(hud == HUD_RAPTOR) + CSQC_RAPTOR_HUD(); + else if(hud == HUD_BUMBLEBEE) + CSQC_BUMBLE_HUD(); } - else - { - drawpic(hudloc + '132 54 0', spider_a1, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); - drawstring(hudloc + '179 69 0', strcat(ftos(9 - rockets), "/8"),'14 14 0','1 1 0', 1, DRAWFLAG_NORMAL); - } - - picsize = drawgetimagesize(spider_b) * 0.5; - hudloc_y = 10.5; - hudloc_x = 10.5; - - drawpic(hudloc, spider_s, picsize, '1 1 1', shield, DRAWFLAG_NORMAL); - drawpic(hudloc, spider_b, picsize, '0 1 0' * hp + '1 0 0' * (1 - hp), 1, DRAWFLAG_NORMAL); - drawpic(hudloc, spider_r, picsize, '1 1 1' * reload + '1 0 0' * (1 - reload), 1, DRAWFLAG_NORMAL); - drawpic(hudloc, spider_g, picsize, '1 1 1' * (1 - heat) + '1 0 0' * heat, 1, DRAWFLAG_NORMAL); - - - /* - // Draw health bar - p = '0.5 0 0' * (vid_conwidth - (rkt_size * 8)); - p = p + '0 1 0' * vid_conheight - '0 32 0'; - //pp = ('0 1 0' * hp) + ('1 0 0' * (1-hp)); - drawfill(p, '256 0 0' * shield + '0 8 0' , '0.5 0.5 1', 0.75, DRAWFLAG_NORMAL); - p_y += 8; - drawfill(p, '256 0 0' * hp + '0 8 0' , '0 1 0', 0.75, DRAWFLAG_NORMAL); - p_x += 256 * hp; - drawfill(p, '256 0 0' * (1-hp) + '0 8 0' , '0 0 0', 0.75, DRAWFLAG_NORMAL); - - // Draw minigun heat indicator - p = '0.5 0 0' * (vid_conwidth - 256); - p = p + '0 1 0' * vid_conheight - '0 34 0'; - drawfill(p, '256 0 0' * (1-heat) + '0 2 0' ,'0 0 1', 0.5, DRAWFLAG_NORMAL); - p_x += 256 * (1-heat); - drawfill(p, '256 0 0' * heat + '0 2 0' , '1 0 0', 0.5, DRAWFLAG_NORMAL); - - - // Draw rocket icons for loaded/empty tubes. - pp = '0.5 0 0' * (vid_conwidth - (rkt_size * 8)); - pp += '0 1 0' * vid_conheight - '0 64 0'; - for(i = 0; i < 8; ++i) - { - p = pp + '1 0 0' * (rkt_size * i); - if(rockets == 8) - { - if(floor(reload * 8) == i) - { - drawpic(p, spider_rocket_icon, '1 1 0' * rkt_size, '1 0 0' + '0 1 0' * ((reload*8)-i), 0.75 , DRAWFLAG_NORMAL); - } - else if(i < reload * 8) - drawpic(p, spider_rocket_icon, '1 1 0' * rkt_size, '1 1 0', 0.75 , DRAWFLAG_NORMAL); - else - drawpic(p, spider_rocket_icon, '1 1 0' * rkt_size, '0.5 0.5 0.5', 0.75, DRAWFLAG_NORMAL); - } - else - { - if(i < rockets) - drawpic(p, spider_rocket_icon, '1 1 0' * rkt_size, '0 0 0', 0.25, DRAWFLAG_NORMAL); - else - drawpic(p, spider_rocket_icon, '1 1 0' * rkt_size, '0 1 0' * reload, 0.75, DRAWFLAG_NORMAL); - } - } - */ - - if (scoreboard_showscores) - { - HUD_DrawScoreboard(); - HUD_DrawCenterPrint(); - } - + // let's reset the view back to normal for the end + setproperty(VF_MIN, '0 0 0'); + setproperty(VF_SIZE, '1 0 0' * w + '0 1 0' * h); } -#define raptor_h "gfx/vehicles/hud_bg.tga" -#define raptor_b "gfx/vehicles/raptor.tga" -#define raptor_g1 "gfx/vehicles/raptor_guns.tga" -#define raptor_g2 "gfx/vehicles/raptor_bombs.tga" -#define raptor_s "gfx/vehicles/shiled.tga" -void CSQC_RAPTOR_HUD() +void CSQC_common_hud(void) { - float reload, hp, shield, energy; - vector picsize, hudloc; - - // Fetch health & ammo stats - hp = bound(0,getstatf(STAT_VEHICLESTAT_HEALTH), 1); - shield = bound(0,getstatf(STAT_VEHICLESTAT_SHIELD), 1); - reload = min(getstatf(STAT_VEHICLESTAT_RELOAD1), 1); - energy = min(getstatf(STAT_VEHICLESTAT_ENERGY), 1); - - // Draw the crosshairs - picsize = drawgetimagesize(SPIDER_CROSS); - picsize_x *= autocvar_cl_vehicle_spiderbot_cross_size; - picsize_y *= autocvar_cl_vehicle_spiderbot_cross_size; - drawpic('0.5 0 0' * (vid_conwidth - picsize_x) + '0 0.5 0' * (vid_conheight - picsize_y), SPIDER_CROSS, picsize, '1 1 1', autocvar_cl_vehicle_spiderbot_cross_alpha, DRAWFLAG_NORMAL); - - hudloc_y = 4; - hudloc_x = 4; - - picsize = drawgetimagesize(raptor_h) * 0.5; - drawpic(hudloc, raptor_h, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); - - picsize = drawgetimagesize(spider_a2) * 0.5; - drawpic(hudloc + '120 96 0', spider_a2, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); - - drawstring(hudloc + '145 19 0', strcat(ftos(rint(hp * 100)), "%"),'15 15 0','0 1 0', 1, DRAWFLAG_NORMAL); - drawstring(hudloc + '175 34 0', strcat(ftos(rint(shield * 100)), "%"),'15 15 0','0 0 1', 1, DRAWFLAG_NORMAL); - drawstring(hudloc + '136 102 0', strcat(ftos(rint(energy * 100)), "%"),'15 15 0','0.5 0.5 1', 1, DRAWFLAG_NORMAL); - - - picsize = drawgetimagesize(spider_a1) * 0.85; - if(reload == 1) + // do some accuracy var caching + float i; + if(!(gametype == MAPINFO_TYPE_RACE || gametype == MAPINFO_TYPE_CTS)) { - drawpic(hudloc + '132 54 0', spider_a1, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); - drawstring(hudloc + '179 69 0', strcat(ftos(rint(reload * 100)), "%"),'14 14 0','0 1 0', 0.5, DRAWFLAG_NORMAL); + if(autocvar_accuracy_color_levels != acc_color_levels) + { + if(acc_color_levels) + strunzone(acc_color_levels); + acc_color_levels = strzone(autocvar_accuracy_color_levels); + acc_levels = tokenize_console(acc_color_levels); + if (acc_levels > MAX_ACCURACY_LEVELS) + acc_levels = MAX_ACCURACY_LEVELS; + + for (i = 0; i < acc_levels; ++i) + acc_lev[i] = stof(argv(i)) / 100.0; + } + // let know that acc_col[] needs to be loaded + acc_col_x[0] = -1; } - else - { - drawpic(hudloc + '132 54 0', spider_a1, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); - drawstring(hudloc + '179 69 0', strcat(ftos(rint(reload * 100)), "%"),'14 14 0','0 0 1', 1, DRAWFLAG_NORMAL); - } - - picsize = drawgetimagesize(raptor_b) * 0.5; - hudloc_y = 10.5; - hudloc_x = 10.5; - drawpic(hudloc, raptor_s, picsize, '1 1 1', shield, DRAWFLAG_NORMAL); - drawpic(hudloc, raptor_b, picsize, '0 1 0' * hp + '1 0 0' * (1 - hp), 1, DRAWFLAG_NORMAL); - drawpic(hudloc, raptor_g1, picsize, '1 1 1' * energy + '1 0 0' * (1 - energy), 1, DRAWFLAG_NORMAL); - drawpic(hudloc, raptor_g2, picsize, '1 1 1' * reload + '1 0 0' * (1 - reload), 1, DRAWFLAG_NORMAL); + HUD_Main(); // always run these functions for alpha checks + HUD_DrawScoreboard(); - - if (scoreboard_showscores) - { - HUD_DrawScoreboard(); - HUD_DrawCenterPrint(); - } - -} - -#define waki_h "gfx/vehicles/hud_bg.tga" -#define waki_b "gfx/vehicles/waki.tga" -#define waki_e "gfx/vehicles/waki_e.tga" -#define waki_g "gfx/vehicles/waki_guns.tga" -#define waki_r "gfx/vehicles/waki_rockets.tga" -#define waki_s "gfx/vehicles/shiled.tga" - -#define waki_a1 "gfx/hud/sb_rocket.tga" -#define waki_a2 "gfx/sb_cells.tga" - -void CSQC_WAKIZASHI_HUD() -{ - // 0--1 floats. 1 = 100%, 0.6 = 50%. - float health, shield, energy, rockets; - vector picsize, hudloc; - - picsize = drawgetimagesize(SPIDER_CROSS); - picsize_x *= autocvar_cl_vehicle_spiderbot_cross_size; - picsize_y *= autocvar_cl_vehicle_spiderbot_cross_size; - drawpic('0.5 0 0' * (vid_conwidth - picsize_x) + '0 0.5 0' * (vid_conheight - picsize_y), SPIDER_CROSS, picsize, '1 1 1', autocvar_cl_vehicle_spiderbot_cross_alpha, DRAWFLAG_NORMAL); - -/* -const float STAT_VEHICLESTAT_HEALTH = 60; -const float STAT_VEHICLESTAT_SHIELD = 61; -const float STAT_VEHICLESTAT_ENERGY = 62; -const float STAT_VEHICLESTAT_AMMO1 = 63; -const float STAT_VEHICLESTAT_RELAOD1 = 64; -const float STAT_VEHICLESTAT_AMMO2 = 65; -const float STAT_VEHICLESTAT_RELOAD2 = 66; -*/ - health = min(getstatf(STAT_VEHICLESTAT_HEALTH), 1); - shield = min(getstatf(STAT_VEHICLESTAT_SHIELD), 1); - energy = min(getstatf(STAT_VEHICLESTAT_ENERGY), 1); - rockets = bound(0,getstatf(STAT_VEHICLESTAT_RELOAD1), 1); - - hudloc_y = 4; - hudloc_x = 4; - - picsize = drawgetimagesize(waki_h) * 0.5; - drawpic(hudloc, waki_h, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); - - picsize = drawgetimagesize(waki_a2) * 0.7; - drawpic(hudloc + '116 92 0', waki_a2, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); - - - drawstring(hudloc + '145 19 0', strcat(ftos(rint(health * 100)), "%"),'15 15 0','0 1 0', 1, DRAWFLAG_NORMAL); - drawstring(hudloc + '175 34 0', strcat(ftos(rint(shield * 100)), "%"),'15 15 0','0 0 1', 1, DRAWFLAG_NORMAL); - - drawstring(hudloc + '136 102 0', strcat(ftos(rint(energy * 100)), "%"),'14 14 0','1 1 1', 1, DRAWFLAG_NORMAL); - - picsize = drawgetimagesize(waki_a1) * 0.75; - if(rockets == 1) - { - drawpic(hudloc + '140 55 0', waki_a1, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); - drawpic(hudloc + '144 59 0', waki_a1, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); - } - else + if (scoreboard_active) // scoreboard/accuracy + HUD_Reset(); + else if (intermission == 2) // map voting screen { - drawpic(hudloc + '140 55 0', waki_a1, picsize, '-1 -1 -1', 1, DRAWFLAG_NORMAL); - drawpic(hudloc + '144 59 0', waki_a1, picsize, '-1 -1 -1', 1, DRAWFLAG_NORMAL); - drawstring(hudloc + '165 69 0', strcat(ftos(rint(rockets * 100)), "%"),'14 14 0','1 1 0', 1, DRAWFLAG_NORMAL); + HUD_FinaleOverlay(); + HUD_Reset(); } - - picsize = drawgetimagesize(waki_b) * 0.5; - hudloc_y = 10.5; - hudloc_x = 10.5; - - drawpic(hudloc, waki_s, picsize, '1 1 1', shield, DRAWFLAG_NORMAL); - drawpic(hudloc, waki_b, picsize, '0 1 0' * health + '1 0 0' * (1 - health), 1, DRAWFLAG_NORMAL); - drawpic(hudloc, waki_r, picsize, '1 1 1' * rockets + '1 0 0' * (1 - rockets), 1, DRAWFLAG_NORMAL); - drawpic(hudloc, waki_e, picsize, '1 1 1' * energy + '1 0 0' * (1 - energy), 1, DRAWFLAG_NORMAL); - - - /* - p = '0.5 0 0' * (vid_conwidth - (rkt_size * 8)); - p = p + '0 1 0' * vid_conheight - '0 32 0'; - - // Draw health bar - p_y += 8; - drawfill(p, '256 0 0' * health + '0 8 0' , '0 0.7 0', 0.75, DRAWFLAG_NORMAL); - p_x += 256 * health; - drawfill(p, '256 0 0' * (1 - health) + '0 8 0' , '0 0 0', 0.75, DRAWFLAG_NORMAL); - - // Draw shiled bar - p_x -= 256 * health; - p_y += 4; - drawfill(p, '256 0 0' * shield + '0 4 0' , '0.25 0.25 1', 0.5, DRAWFLAG_NORMAL); - - // Draw energy - //p_x -= 256 * health; - p_y -= 8; - drawfill(p, '256 0 0' * energy + '0 4 0' , '1 1 1', 0.75, DRAWFLAG_NORMAL); - - // Draw rockets bar - p_y += 12; - drawfill(p, '256 0 0' * rockets + '0 4 0' , '1 0 0', 0.75, DRAWFLAG_NORMAL); - */ - - - - - if (scoreboard_showscores) - { - HUD_DrawScoreboard(); - HUD_DrawCenterPrint(); - } - -} - - -void CSQC_common_hud(void) -{ - // HUD_SortFrags(); done in HUD_Draw - float hud; - hud = getstati(STAT_HUD); - - //hud = 10; switch(hud) { - case HUD_NORMAL: - // do some accuracy var caching - float i; - if(!(gametype == GAME_RACE || gametype == GAME_CTS)) - { - if(autocvar_accuracy_color_levels != acc_color_levels) - { - if(acc_color_levels) - strunzone(acc_color_levels); - acc_color_levels = strzone(autocvar_accuracy_color_levels); - acc_levels = tokenize(acc_color_levels); - if (acc_levels > MAX_ACCURACY_LEVELS) - acc_levels = MAX_ACCURACY_LEVELS; - - for (i = 0; i < acc_levels; ++i) - acc_lev[i] = stof(argv(i)) / 100.0; - } - // let know that acc_col[] needs to be loaded - acc_col_x[0] = -1; - } - - HUD_Main(); // always run these functions for alpha checks - HUD_DrawScoreboard(); - - if (scoreboard_active) // scoreboard/accuracy - { - HUD_Reset(); - // HUD_DrawScoreboard takes care of centerprint_start - } - else if (intermission == 2) // map voting screen - { - HUD_FinaleOverlay(); - HUD_Reset(); - - centerprint_start_x = 0; - centerprint_start_y = autocvar_scr_centerpos * vid_conheight; - } - else // hud - { - centerprint_start_x = 0; - centerprint_start_y = autocvar_scr_centerpos * vid_conheight; - } - - HUD_DrawCenterPrint(); - break; - case HUD_SPIDERBOT: CSQC_SPIDER_HUD(); break; @@ -1441,7 +1490,12 @@ void CSQC_common_hud(void) case HUD_WAKIZASHI: CSQC_WAKIZASHI_HUD(); break; + + case HUD_BUMBLEBEE: + CSQC_BUMBLE_HUD(); + break; } + */ } @@ -1472,8 +1526,8 @@ void CSQC_Demo_Camera() if(autocvar_camera_look_player) { - local vector dir; - local float n; + vector dir; + float n; dir = normalize(view_origin - current_position); n = mouse_angles_z; @@ -1484,7 +1538,7 @@ void CSQC_Demo_Camera() else { tmp = getmousepos() * 0.1; - if(vlen(tmp)>autocvar_camera_mouse_treshold) + if(vlen(tmp)>autocvar_camera_mouse_threshold) { mouse_angles_x += tmp_y * cos(mouse_angles_z * DEG2RAD) + (tmp_x * sin(mouse_angles_z * DEG2RAD)); mouse_angles_y -= tmp_x * cos(mouse_angles_z * DEG2RAD) + (tmp_y * -sin(mouse_angles_z * DEG2RAD)); @@ -1587,6 +1641,6 @@ void CSQC_Demo_Camera() current_position = current_origin + current_camera_offset; } - R_SetView(VF_ANGLES, current_angles); - R_SetView(VF_ORIGIN, current_position); + setproperty(VF_ANGLES, current_angles); + setproperty(VF_ORIGIN, current_position); } diff --git a/qcsrc/client/announcer.qc b/qcsrc/client/announcer.qc new file mode 100644 index 0000000000..3e109e7805 --- /dev/null +++ b/qcsrc/client/announcer.qc @@ -0,0 +1,231 @@ +float previous_announcement_time; +float previous_game_starttime; +string previous_announcement; + +// remaining maptime announcer sounds, true when sound was already played +float announcer_1min; +float announcer_5min; + +void Announcer_Play(string announcement) +{ + if((announcement != previous_announcement) || (time >= (previous_announcement_time + autocvar_cl_announcer_antispam))) + { + sound(world, CH_INFO, strcat("announcer/", autocvar_cl_announcer, "/", announcement, ".wav"), VOL_BASEVOICE, ATTN_NONE); + + if(previous_announcement) { strunzone(previous_announcement); } + + previous_announcement = strzone(announcement); + previous_announcement_time = time; + } +} + +void Announcer_Countdown() +{ + float starttime = getstatf(STAT_GAMESTARTTIME); + float countdown = (starttime - time); + float countdown_rounded = floor(0.5 + countdown); + + if(countdown <= 0) // countdown has finished, starttime is now + { + if (!spectatee_status) + centerprint_generic(CPID_GAME_STARTING, _("^1Begin!"), 1, 0); + + Announcer_Play("begin"); + announcer_5min = announcer_1min = FALSE; // reset maptime announcers now as well + remove(self); + return; + } + else // countdown is still going + { + if (!spectatee_status) + centerprint_generic(CPID_GAME_STARTING, _("^1Game starts in %d seconds"), 1, countdown_rounded); + + if(countdown_rounded <= 3 && countdown_rounded >= 1) + Announcer_Play(ftos(countdown_rounded)); + + self.nextthink = (starttime - (countdown - 1)); + } +} + +/** + * Checks whether the server initiated a map restart (stat_game_starttime changed) + * + * TODO: Use a better solution where a common shared entitiy is used that contains + * timelimit, fraglimit and game_starttime! Requires engine changes (remove STAT_TIMELIMIT + * and STAT_FRAGLIMIT to be auto-sent) + */ +void Announcer_Gamestart() +{ + float startTime = getstatf(STAT_GAMESTARTTIME); + + if(previous_game_starttime != startTime) + { + if((time + 5.0) < startTime) // if connecting to server while restart was active don't always play prepareforbattle + Announcer_Play("prepareforbattle"); + + if(time < startTime) + { + entity e; + e = spawn(); + e.think = Announcer_Countdown; + e.nextthink = startTime - floor(startTime - time); //synchronize nextthink to startTime + } + } + + previous_game_starttime = startTime; +} + + +// Plays the 1 minute or 5 minutes (of maptime) remaining sound, if client wants it +void Announcer_Time() +{ + float timelimit = getstatf(STAT_TIMELIMIT); + float timeleft = max(0, timelimit * 60 + getstatf(STAT_GAMESTARTTIME) - time); + float warmup_timeleft; + + if(warmup_stage) + if(autocvar_g_warmup_limit > 0) + warmup_timeleft = max(0, autocvar_g_warmup_limit + getstatf(STAT_GAMESTARTTIME) - time); + + // 5 minute check + if(autocvar_cl_announcer_maptime >= 2) + { + // make sure that after connect (and e.g. 4 minutes left) we will not get a wrong sound + if(announcer_5min) + { + if(((!warmup_stage || autocvar_g_warmup_limit == 0) && timeleft > 300) + || (warmup_stage && autocvar_g_warmup_limit > 0 && warmup_timeleft > 300)) + announcer_5min = FALSE; + } + else + { + if(((!warmup_stage || autocvar_g_warmup_limit == 0) && timelimit > 0 && timeleft < 300 && timeleft > 299) + || (warmup_stage && autocvar_g_warmup_limit > 0 && warmup_timeleft < 300 && warmup_timeleft > 299)) + { + //if we're in warmup mode, check whether there's a warmup timelimit + if not(autocvar_g_warmup_limit == -1 && warmup_stage) + { + announcer_5min = TRUE; + Announcer_Play("5minutesremain"); + } + } + } + } + + // 1 minute check + if((autocvar_cl_announcer_maptime == 1) || (autocvar_cl_announcer_maptime == 3)) + { + if (announcer_1min) + { + if(((!warmup_stage || autocvar_g_warmup_limit == 0) && timeleft > 60) + || (warmup_stage && autocvar_g_warmup_limit > 0 && warmup_timeleft > 60)) + announcer_1min = FALSE; + } + else if(((!warmup_stage || autocvar_g_warmup_limit == 0) && timelimit > 0 && timeleft < 60) + || (warmup_stage && autocvar_g_warmup_limit > 0 && warmup_timeleft < 60)) + { + // if we're in warmup mode, check whether there's a warmup timelimit + if not(autocvar_g_warmup_limit == -1 && warmup_stage) + { + announcer_1min = TRUE; + Announcer_Play("1minuteremains"); + } + } + } +} + +float redflag_prev; +float blueflag_prev; +void carrierAnnouncer() { + float stat_items, redflag, blueflag; + float pickup; + string item; + + if not(autocvar_cl_notify_carried_items) + return; + + stat_items = getstati(STAT_ITEMS); + + redflag = (stat_items/IT_RED_FLAG_TAKEN) & 3; + blueflag = (stat_items/IT_BLUE_FLAG_TAKEN) & 3; + + if (redflag == 3 && redflag != redflag_prev) { + item = _("^1RED^7 flag"); + pickup = (redflag_prev == 2); + } + + if (blueflag == 3 && blueflag != blueflag_prev) { + item = _("^4BLUE^7 flag"); + pickup = (blueflag_prev == 2); + } + + if (item) + { + if (pickup) { + if (autocvar_cl_notify_carried_items & 2) + centerprint_hud(sprintf(_("You picked up the %s!"), item)); + } + else { + if (autocvar_cl_notify_carried_items & 1) + centerprint_hud(sprintf(_("You got the %s!"), item)); + } + } + + blueflag_prev = blueflag; + redflag_prev = redflag; +} + +void Announcer() +{ + Announcer_Gamestart(); + Announcer_Time(); + carrierAnnouncer(); +} + +void Announcer_Precache () +{ + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/1minuteremains.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/5minutesremain.wav")); + + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/electrobitch.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/airshot.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/03kills.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/05kills.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/10kills.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/15kills.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/20kills.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/25kills.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/30kills.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/botlike.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/yoda.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/amazing.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/awesome.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/headshot.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/impressive.wav")); + + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/prepareforbattle.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/begin.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/timeoutcalled.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/1fragleft.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/2fragsleft.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/3fragsleft.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/terminated.wav")); + + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/1.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/2.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/3.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/4.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/5.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/6.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/7.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/8.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/9.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/10.wav")); + + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/lastsecond.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/narrowly.wav")); + + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/voteaccept.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/votecall.wav")); + precache_sound (strcat("announcer/", autocvar_cl_announcer, "/votefail.wav")); +} diff --git a/qcsrc/client/autocvars.qh b/qcsrc/client/autocvars.qh index f3d18aa9ff..705e2c5195 100644 --- a/qcsrc/client/autocvars.qh +++ b/qcsrc/client/autocvars.qh @@ -10,7 +10,7 @@ float autocvar_camera_forward_follows; float autocvar_camera_free; float autocvar_camera_look_attenuation; float autocvar_camera_look_player; -float autocvar_camera_mouse_treshold; +float autocvar_camera_mouse_threshold; float autocvar_camera_reset; float autocvar_camera_speed_attenuation; float autocvar_camera_speed_chase; @@ -19,6 +19,8 @@ float autocvar_camera_speed_roll; float autocvar_chase_active; float autocvar_cl_allow_uid2name; string autocvar_cl_announcer; +var float autocvar_cl_announcer_antispam = 2; +var float autocvar_cl_announcer_maptime = 3; float autocvar_cl_autodemo_delete; float autocvar_cl_autodemo_delete_keeprecords; float autocvar_cl_casings; @@ -46,6 +48,7 @@ var float autocvar_cl_gibs_sloppy = 1; var float autocvar_cl_gibs_ticrate = 0.1; var float autocvar_cl_gibs_velocity_random = 1; var float autocvar_cl_gibs_velocity_scale = 1; +var float autocvar_cl_gibs_avelocity_scale = 1; float autocvar_cl_gibs_velocity_up; float autocvar_cl_gunalign; float autocvar_cl_hidewaypoints; @@ -57,34 +60,24 @@ float autocvar_cl_particles_oldnexbeam; float autocvar_cl_particles_quality; float autocvar_cl_projectiles_sloppy; float autocvar_cl_readpicture_force; +var float autocvar_cl_reticle = 1; float autocvar_cl_reticle_item_nex; float autocvar_cl_reticle_item_normal; float autocvar_cl_reticle_stretch; -float autocvar_cl_showacceleration; -float autocvar_cl_showacceleration_alpha; -string autocvar_cl_showacceleration_color; -float autocvar_cl_showacceleration_color_custom; -float autocvar_cl_showacceleration_position; -float autocvar_cl_showacceleration_scale; -float autocvar_cl_showacceleration_size; -float autocvar_cl_showacceleration_z; -float autocvar_cl_showspeed; -float autocvar_cl_showspeed_position; -float autocvar_cl_showspeed_size; -float autocvar_cl_showspeed_unit; -float autocvar_cl_showspeed_z; -float autocvar_cl_sound_maptime_warning; float autocvar_cl_stripcolorcodes; var float autocvar_cl_vehicle_spiderbot_cross_alpha = 0.6; var float autocvar_cl_vehicle_spiderbot_cross_size = 1; float autocvar_cl_velocityzoom; -var float autocvar_cl_velocityzoomtime = 0.3; +float autocvar_cl_velocityzoom_type; +float autocvar_cl_velocityzoom_speed; +float autocvar_cl_velocityzoom_time; string autocvar_cl_weaponpriority; float autocvar_cl_zoomfactor; float autocvar_cl_zoomsensitivity; float autocvar_cl_zoomspeed; float autocvar_con_chat; float autocvar_con_chatpos; +float autocvar_con_chatrect; float autocvar_con_chatsize; float autocvar_con_chattime; float autocvar_con_notify; @@ -99,53 +92,87 @@ string autocvar_crosshair_dot_color; float autocvar_crosshair_dot_size; float autocvar_crosshair_effect_scalefade; float autocvar_crosshair_effect_speed; +float autocvar_crosshair_hitindication; +string autocvar_crosshair_hitindication_color; +float autocvar_crosshair_hitindication_speed; float autocvar_crosshair_hittest; float autocvar_crosshair_hittest_blur; float autocvar_crosshair_hittest_showimpact; float autocvar_crosshair_per_weapon; float autocvar_crosshair_pickup; float autocvar_crosshair_pickup_speed; -float autocvar_crosshair_ring_campingrifle_alpha; +float autocvar_crosshair_ring; +float autocvar_crosshair_ring_inner; +float autocvar_crosshair_ring_minelayer; +float autocvar_crosshair_ring_minelayer_alpha; +float autocvar_crosshair_ring_hagar; +float autocvar_crosshair_ring_hagar_alpha; +float autocvar_crosshair_ring_nex; +float autocvar_crosshair_ring_nex_alpha; float autocvar_crosshair_ring_nex_currentcharge_movingavg_rate; float autocvar_crosshair_ring_nex_currentcharge_scale; float autocvar_crosshair_ring_nex_inner_alpha; float autocvar_crosshair_ring_nex_inner_color_blue; float autocvar_crosshair_ring_nex_inner_color_green; float autocvar_crosshair_ring_nex_inner_color_red; -float autocvar_crosshair_ring_nex_outer_alpha; float autocvar_crosshair_ring_size; +float autocvar_crosshair_ring_reload; +float autocvar_crosshair_ring_reload_alpha; +float autocvar_crosshair_ring_reload_size; float autocvar_crosshair_size; float autocvar_ekg; float autocvar_fov; +float autocvar_g_balance_damagepush_speedfactor; float autocvar_g_balance_tuba_attenuation; float autocvar_g_balance_tuba_fadetime; float autocvar_g_balance_tuba_volume; +float autocvar_g_balance_tuba_pitchstep; float autocvar_g_warmup_limit; -var float autocvar_g_waypointsprite_alpha = 1; -var float autocvar_g_waypointsprite_crosshairfadealpha = 1; +float autocvar_g_waypointsprite_uppercase; +float autocvar_g_waypointsprite_alpha; +float autocvar_g_waypointsprite_crosshairfadealpha; float autocvar_g_waypointsprite_crosshairfadedistance; -var float autocvar_g_waypointsprite_crosshairfadescale = 1; +float autocvar_g_waypointsprite_crosshairfadescale; float autocvar_g_waypointsprite_distancealphaexponent; -var float autocvar_g_waypointsprite_distancefadealpha = 1; -var float autocvar_g_waypointsprite_distancefadedistancemultiplier = 1; -var float autocvar_g_waypointsprite_distancefadescale = 1; -var float autocvar_g_waypointsprite_edgefadealpha = 1; +float autocvar_g_waypointsprite_distancefadealpha; +float autocvar_g_waypointsprite_distancefadedistancemultiplier; +float autocvar_g_waypointsprite_distancefadescale; +float autocvar_g_waypointsprite_edgefadealpha; float autocvar_g_waypointsprite_edgefadedistance; -var float autocvar_g_waypointsprite_edgefadescale = 1; +float autocvar_g_waypointsprite_edgefadescale; +float autocvar_g_waypointsprite_edgeoffset_bottom; +float autocvar_g_waypointsprite_edgeoffset_left; +float autocvar_g_waypointsprite_edgeoffset_right; +float autocvar_g_waypointsprite_edgeoffset_top; +float autocvar_g_waypointsprite_fontsize; float autocvar_g_waypointsprite_minalpha; float autocvar_g_waypointsprite_minscale; float autocvar_g_waypointsprite_normdistance; -var float autocvar_g_waypointsprite_scale = 1; +float autocvar_g_waypointsprite_scale; +float autocvar_g_waypointsprite_spam; float autocvar_g_waypointsprite_timealphaexponent; -var float autocvar_hud_colorflash_alpha = 0.5; -float autocvar_hud_configure_bg_minalpha; +float autocvar_g_waypointsprites_turrets; +float autocvar_g_waypointsprites_turrets_maxdist; + +float autocvar_hud_colorflash_alpha; float autocvar_hud_configure_checkcollisions; float autocvar_hud_configure_grid; float autocvar_hud_configure_grid_alpha; -float autocvar_hud_configure_grid_xsize; -float autocvar_hud_configure_grid_ysize; float autocvar_hud_configure_teamcolorforced; +float autocvar_hud_contents; +float autocvar_hud_contents_blur; +float autocvar_hud_contents_blur_alpha; +float autocvar_hud_contents_fadeintime; +float autocvar_hud_contents_fadeouttime; +float autocvar_hud_contents_lava_alpha; +string autocvar_hud_contents_lava_color; +float autocvar_hud_contents_slime_alpha; +string autocvar_hud_contents_slime_color; +float autocvar_hud_contents_water_alpha; +string autocvar_hud_contents_water_color; float autocvar_hud_damage; +float autocvar_hud_damage_blur; +float autocvar_hud_damage_blur_alpha; string autocvar_hud_damage_color; float autocvar_hud_damage_factor; float autocvar_hud_damage_fade_rate; @@ -157,6 +184,10 @@ float autocvar_hud_damage_pain_threshold_lower; float autocvar_hud_damage_pain_threshold_lower_health; float autocvar_hud_damage_pain_threshold_pulsating_min; float autocvar_hud_damage_pain_threshold_pulsating_period; +float autocvar_hud_powerup; +float autocvar_hud_postprocessing; +float autocvar_hud_postprocessing_maxbluralpha; +float autocvar_hud_postprocessing_maxblurradius; string autocvar_hud_dock; float autocvar_hud_dock_alpha; string autocvar_hud_dock_color; @@ -175,6 +206,20 @@ float autocvar_hud_panel_bg_border; vector autocvar_hud_panel_bg_color; float autocvar_hud_panel_bg_color_team; float autocvar_hud_panel_bg_padding; +float autocvar_hud_panel_centerprint; +float autocvar_hud_panel_centerprint_align; +var float autocvar_hud_panel_centerprint_fade_in = 0.2; +var float autocvar_hud_panel_centerprint_fade_out = 0.5; +var float autocvar_hud_panel_centerprint_fade_subsequent = 1; +var float autocvar_hud_panel_centerprint_fade_subsequent_passone = 3; +var float autocvar_hud_panel_centerprint_fade_subsequent_passone_minalpha = 0.5; +var float autocvar_hud_panel_centerprint_fade_subsequent_passtwo = 10; +var float autocvar_hud_panel_centerprint_fade_subsequent_passtwo_minalpha = 0.5; +var float autocvar_hud_panel_centerprint_fade_subsequent_minfontsize = 0.75; +var float autocvar_hud_panel_centerprint_fade_minfontsize = 0; +float autocvar_hud_panel_centerprint_flip; +float autocvar_hud_panel_centerprint_fontscale; +float autocvar_hud_panel_centerprint_time; float autocvar_hud_panel_chat; float autocvar_hud_panel_engineinfo; float autocvar_hud_panel_engineinfo_framecounter_decimals; @@ -189,15 +234,35 @@ float autocvar_hud_panel_healtharmor_maxhealth; float autocvar_hud_panel_healtharmor_progressbar; string autocvar_hud_panel_healtharmor_progressbar_armor; string autocvar_hud_panel_healtharmor_progressbar_health; +float autocvar_hud_panel_healtharmor_progressbar_gfx; +float autocvar_hud_panel_healtharmor_progressbar_gfx_damage; +float autocvar_hud_panel_healtharmor_progressbar_gfx_lowhealth; +float autocvar_hud_panel_healtharmor_progressbar_gfx_smooth; float autocvar_hud_panel_healtharmor_text; float autocvar_hud_panel_infomessages; float autocvar_hud_panel_infomessages_flip; float autocvar_hud_panel_modicons; +float autocvar_hud_panel_modicons_dom_layout; float autocvar_hud_panel_notify; float autocvar_hud_panel_notify_fadetime; float autocvar_hud_panel_notify_flip; +float autocvar_hud_panel_notify_fontsize; float autocvar_hud_panel_notify_print; float autocvar_hud_panel_notify_time; +float autocvar_hud_panel_physics; +float autocvar_hud_panel_physics_acceleration_mode; +float autocvar_hud_panel_physics_acceleration_max; +float autocvar_hud_panel_physics_progressbar; +float autocvar_hud_panel_physics_acceleration_vertical; +float autocvar_hud_panel_physics_baralign; +float autocvar_hud_panel_physics_flip; +float autocvar_hud_panel_physics_speed_max; +float autocvar_hud_panel_physics_speed_unit; +float autocvar_hud_panel_physics_speed_unit_show; +float autocvar_hud_panel_physics_speed_vertical; +float autocvar_hud_panel_physics_text; +float autocvar_hud_panel_physics_topspeed; +float autocvar_hud_panel_physics_topspeed_time; float autocvar_hud_panel_powerups; float autocvar_hud_panel_powerups_baralign; float autocvar_hud_panel_powerups_flip; @@ -211,10 +276,13 @@ float autocvar_hud_panel_pressedkeys_aspect; float autocvar_hud_panel_racetimer; float autocvar_hud_panel_radar; float autocvar_hud_panel_radar_foreground_alpha; +float autocvar_hud_panel_radar_maximized_scale; +vector autocvar_hud_panel_radar_maximized_size; float autocvar_hud_panel_radar_rotation; float autocvar_hud_panel_radar_scale; float autocvar_hud_panel_radar_zoommode; float autocvar_hud_panel_score; +float autocvar_hud_panel_score_rankings; float autocvar_hud_panel_timer; float autocvar_hud_panel_timer_increment; float autocvar_hud_panel_vote; @@ -240,11 +308,30 @@ float autocvar_hud_panel_weapons_complainbubble_padding; float autocvar_hud_panel_weapons_complainbubble_time; var float autocvar_hud_panel_weapons_fade = 1; float autocvar_hud_panel_weapons_label; +float autocvar_hud_panel_weapons_onlyowned; float autocvar_hud_panel_weapons_timeout; float autocvar_hud_panel_weapons_timeout_effect; float autocvar_hud_progressbar_alpha; float autocvar_hud_showbinds; float autocvar_hud_showbinds_limit; +float autocvar_hud_shownames; +float autocvar_hud_shownames_enemies; +float autocvar_hud_shownames_crosshairdistance; +float autocvar_hud_shownames_crosshairdistance_time; +float autocvar_hud_shownames_crosshairdistance_antioverlap; +float autocvar_hud_shownames_self; +float autocvar_hud_shownames_status; +float autocvar_hud_shownames_statusbar_height; +float autocvar_hud_shownames_aspect; +float autocvar_hud_shownames_fontsize; +float autocvar_hud_shownames_decolorize; +float autocvar_hud_shownames_alpha; +float autocvar_hud_shownames_resize; +float autocvar_hud_shownames_mindistance; +float autocvar_hud_shownames_maxdistance; +float autocvar_hud_shownames_antioverlap; +float autocvar_hud_shownames_antioverlap_distance; +float autocvar_hud_shownames_offset; string autocvar_hud_skin; float autocvar_loddebug; float autocvar_menu_mouse_speed; @@ -272,11 +359,29 @@ var float autocvar_scoreboard_highlight_alpha = 0.10; var float autocvar_scoreboard_highlight_alpha_self = 0.25; float autocvar_scoreboard_offset_left; float autocvar_scoreboard_offset_right; -float autocvar_scr_centerpos; -float autocvar_scr_centersize; -float autocvar_scr_centertime; +float autocvar_scoreboard_offset_vertical; float autocvar_v_flipped; float autocvar_vid_conheight; float autocvar_vid_conwidth; float autocvar_vid_pixelheight; float autocvar_viewsize; +float autocvar_crosshair_color_by_health; +float autocvar_cl_hitsound; +float autocvar_cl_hitsound_antispam_time; +var float autocvar_cl_eventchase_death = 1; +var float autocvar_cl_eventchase_distance = 140; +var float autocvar_cl_eventchase_speed = 1.3; +float autocvar_cl_lerpexcess; +string autocvar__togglezoom; +float autocvar_cl_playerdetailreduction; +float autocvar_cl_loddistance1 = 1024; +float autocvar_cl_loddistance2 = 4096; +float autocvar_cl_forceplayermodels; +float autocvar_cl_forceplayercolors; +string autocvar_cl_forcemyplayermodel; +float autocvar_cl_forcemyplayerskin; +float autocvar_cl_forcemyplayercolors; +float autocvar__cl_playerskin; +string autocvar__cl_playermodel; +float autocvar_cl_precacheplayermodels; +float autocvar_cl_deathglow; diff --git a/qcsrc/client/bgmscript.qc b/qcsrc/client/bgmscript.qc index 43255da584..353c5419ab 100644 --- a/qcsrc/client/bgmscript.qc +++ b/qcsrc/client/bgmscript.qc @@ -131,7 +131,7 @@ void BGMScript_InitEntity(entity e) e.bgmscriptline = e.bgmscriptline0 = i; if(i >= bgmscriptbufsize) { - print("ERROR: bgmscript does not define ", e.bgmscript, "\n"); + print(sprintf("ERROR: bgmscript does not define %s\n", e.bgmscript)); e.bgmscript = ""; } } @@ -182,7 +182,6 @@ float BGMScript(entity e) if(bgmtime < e.bgmscripttime) { - //print("reset ", e.bgmscript, "\n"); amp = GetCurrentAmplitude(e, e.bgmscripttime - e.bgmscriptstatetime + drawframetime); e.bgmscriptline = e.bgmscriptline0; diff --git a/qcsrc/client/casings.qc b/qcsrc/client/casings.qc index 860e8296f7..1e2d4fbd8c 100644 --- a/qcsrc/client/casings.qc +++ b/qcsrc/client/casings.qc @@ -55,7 +55,7 @@ void Casing_Touch() break; } - sound (self, CHAN_PROJECTILE, s, VOL_BASE, ATTN_NORM); + sound (self, CH_SHOTS, s, VOL_BASE, ATTN_LARGE); } } } @@ -75,7 +75,7 @@ void Ent_Casing(float isNew) { entity casing; - casing = RubbleNew("casing"); + casing = RubbleNew("casing"); casing.state = ReadByte(); casing.silent = (casing.state & 0x80); casing.state = (casing.state & 0x7F); @@ -107,7 +107,7 @@ void Ent_Casing(float isNew) casing.cnt = time + autocvar_cl_casings_shell_time; break; default: - setmodel(casing, "models/casing_bronze.mdl"); + setmodel(casing, "models/casing_bronze.iqm"); casing.cnt = time + autocvar_cl_casings_bronze_time; break; } @@ -123,7 +123,7 @@ void Ent_Casing(float isNew) void Casings_Precache() { precache_model("models/casing_shell.mdl"); - precache_model("models/casing_bronze.mdl"); + precache_model("models/casing_bronze.iqm"); precache_sound("weapons/brass1.wav"); precache_sound("weapons/brass2.wav"); precache_sound("weapons/brass3.wav"); diff --git a/qcsrc/client/command/cl_cmd.qc b/qcsrc/client/command/cl_cmd.qc new file mode 100644 index 0000000000..95032dce7b --- /dev/null +++ b/qcsrc/client/command/cl_cmd.qc @@ -0,0 +1,527 @@ +// ============================================== +// CSQC client commands code, written by Samual +// Last updated: December 28th, 2011 +// ============================================== + +void DrawDebugModel() +{ + if(time - floor(time) > 0.5) + { + PolyDrawModel(self); + self.drawmask = 0; + } + else + { + self.renderflags = 0; + self.drawmask = MASK_NORMAL; + } +} + + +// ======================= +// Command Sub-Functions +// ======================= + +void LocalCommand_blurtest(float request) +{ + // Simple command to work with postprocessing temporarily... possibly completely pointless, the glsl shader is used for a real feature now... + // Anyway, to enable it, just compile the client with -DBLURTEST and then you can use the command. + + #ifdef BLURTEST + switch(request) + { + case CMD_REQUEST_COMMAND: + { + blurtest_time0 = time; + blurtest_time1 = time + stof(argv(1)); + blurtest_radius = stof(argv(2)); + blurtest_power = stof(argv(3)); + print("Enabled blurtest\n"); + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 cl_cmd blurtest\n"); + print(" No arguments required.\n"); + return; + } + } + #else + if(request) + { + print("Blurtest is not enabled on this client.\n"); + return; + } + #endif +} + +void LocalCommand_debugmodel(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + string modelname = argv(1); + entity debugmodel_entity; + + debugmodel_entity = spawn(); + precache_model(modelname); + setmodel(debugmodel_entity, modelname); + setorigin(debugmodel_entity, view_origin); + debugmodel_entity.angles = view_angles; + debugmodel_entity.draw = DrawDebugModel; + debugmodel_entity.classname = "debugmodel"; + + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 cl_cmd debugmodel model\n"); + print(" Where 'model' is a string of the model name to use for the debug model.\n"); + return; + } + } +} + +void LocalCommand_handlevote(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + float vote_selection; + string vote_string; + + if(InterpretBoolean(argv(1))) + { + vote_selection = 2; + vote_string = "yes"; + } + else + { + vote_selection = 1; + vote_string = "no"; + } + + if(vote_selection) + { + if(uid2name_dialog) // handled by "uid2name" option + { + vote_active = 0; + vote_prev = 0; + vote_change = -9999; + localcmd(strcat("setreport cl_allow_uid2name ", ftos(vote_selection - 1), "\n")); + uid2name_dialog = 0; + } + else { localcmd(strcat("cmd vote ", vote_string, "\n")); } + + return; + } + } + + default: + print("Incorrect parameters for ^2handlevote^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 cl_cmd handlevote vote\n"); + print(" Where 'vote' is the selection for either the current poll or uid2name.\n"); + return; + } + } +} + +void LocalCommand_hud(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + switch(argv(1)) + { + case "configure": + { + cvar_set("_hud_configure", ftos(!autocvar__hud_configure)); + return; + } + + case "save": + { + if(argv(2)) + { + HUD_Panel_ExportCfg(argv(2)); + return; + } + else + { + break; // go to usage, we're missing the paramater needed here. + } + } + + case "scoreboard_columns_set": + { + Cmd_HUD_SetFields(argc); + return; + } + + case "scoreboard_columns_help": + { + Cmd_HUD_Help(); + return; + } + + case "radar": + { + hud_panel_radar_maximized = (argv(2) ? InterpretBoolean(argv(2)) : !hud_panel_radar_maximized); + return; + } + } + } + + default: + print("Incorrect parameters for ^2hud^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 cl_cmd hud action [configname | radartoggle | layout]\n"); + print(" Where 'action' is the command to complete,\n"); + print(" 'configname' is the name to save to for \"save\" action,\n"); + print(" 'radartoggle' is to control hud_panel_radar_maximized for \"radar\" action,\n"); + print(" and 'layout' is how to organize the scoreboard columns for the set action.\n"); + print(" Full list of commands here: \"configure, save, scoreboard_columns_help, scoreboard_columns_set, radar.\"\n"); + return; + } + } +} + +void LocalCommand_localprint(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argv(1)) + { + centerprint_hud(argv(1)); + return; + } + } + + default: + print("Incorrect parameters for ^2localprint^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 cl_cmd localprint \"message\"\n"); + print(" 'message' is the centerprint message to send to yourself.\n"); + return; + } + } +} + +void LocalCommand_mv_download(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argv(1)) + { + Cmd_MapVote_MapDownload(argc); + return; + } + } + + default: + print("Incorrect parameters for ^2mv_download^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 cl_cmd mv_download mapid\n"); + print(" Where 'mapid' is the id number of the map to request an image of on the map vote selection menu.\n"); + return; + } + } +} + +void LocalCommand_sendcvar(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argv(1)) + { + // W_FixWeaponOrder will trash argv, so save what we need. + string thiscvar = strzone(argv(1)); + string s = cvar_string(thiscvar); + + if(thiscvar == "cl_weaponpriority") + s = W_FixWeaponOrder(W_NumberWeaponOrder(s), 1); + else if(substring(thiscvar, 0, 17) == "cl_weaponpriority" && strlen(thiscvar) == 18) + s = W_FixWeaponOrder(W_NumberWeaponOrder(s), 0); + + localcmd("cmd sentcvar ", thiscvar, " \"", s, "\"\n"); + strunzone(thiscvar); + return; + } + } + + default: + print("Incorrect parameters for ^2sendcvar^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 cl_cmd sendcvar <cvar>\n"); + print(" Where 'cvar' is the cvar plus arguments to send to the server.\n"); + return; + } + } +} + +/* use this when creating a new command, making sure to place it in alphabetical order... also, +** ADD ALL NEW COMMANDS TO commands.cfg WITH PROPER ALIASES IN THE SAME FASHION! +void LocalCommand_(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 cl_cmd \n"); + print(" No arguments required.\n"); + return; + } + } +} +*/ + + +// ================================== +// Macro system for client commands +// ================================== + +// Normally do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;) +// but for 0.5 compat, we need vyes and vno here as they were replaced... REMOVE THEM AFTER 0.6 RELEASE!!!! +#define CLIENT_COMMANDS(request,arguments) \ + CLIENT_COMMAND("blurtest", LocalCommand_blurtest(request), "Feature for testing blur postprocessing") \ + CLIENT_COMMAND("debugmodel", LocalCommand_debugmodel(request, arguments), "Spawn a debug model manually") \ + CLIENT_COMMAND("handlevote", LocalCommand_handlevote(request, arguments), "System to handle selecting a vote or option") \ + CLIENT_COMMAND("hud", LocalCommand_hud(request, arguments), "Commands regarding/controlling the HUD system") \ + CLIENT_COMMAND("localprint", LocalCommand_localprint(request, arguments), "Create your own centerprint sent to yourself") \ + CLIENT_COMMAND("mv_download", LocalCommand_mv_download(request, arguments), "Retrieve mapshot picture from the server") \ + CLIENT_COMMAND("sendcvar", LocalCommand_sendcvar(request, arguments), "Send a cvar to the server (like weaponpriority)") \ + CLIENT_COMMAND("vyes", LocalCommand_handlevote(request, tokenize_console("handlevote yes")), "") \ + CLIENT_COMMAND("vno", LocalCommand_handlevote(request, tokenize_console("handlevote no")), "") \ + /* nothing */ + +void LocalCommand_macro_help() +{ + #define CLIENT_COMMAND(name,function,description) \ + { if(strtolower(description) != "") { print(" ^2", name, "^7: ", description, "\n"); } } + + CLIENT_COMMANDS(0, 0) + #undef CLIENT_COMMAND + + return; +} + +float LocalCommand_macro_command(float argc) +{ + #define CLIENT_COMMAND(name,function,description) \ + { if(name == strtolower(argv(0))) { function; return TRUE; } } + + CLIENT_COMMANDS(CMD_REQUEST_COMMAND, argc) + #undef CLIENT_COMMAND + + return FALSE; +} + +float LocalCommand_macro_usage(float argc) +{ + #define CLIENT_COMMAND(name,function,description) \ + { if(name == strtolower(argv(1))) { function; return TRUE; } } + + CLIENT_COMMANDS(CMD_REQUEST_USAGE, argc) + #undef CLIENT_COMMAND + + return FALSE; +} + +void LocalCommand_macro_write_aliases(float fh) +{ + #define CLIENT_COMMAND(name,function,description) \ + { if(strtolower(description) != "") { CMD_Write_Alias("qc_cmd_cl", name, description); } } + + CLIENT_COMMANDS(0, 0) + #undef CLIENT_COMMAND + + return; +} + + +// ========================================= +// Main Function Called By Engine (cl_cmd) +// ========================================= +// If this function exists, client code handles gamecommand instead of the engine code. + +void GameCommand(string command) +{ + float argc = tokenize_console(command); + + // Guide for working with argc arguments by example: + // argc: 1 - 2 - 3 - 4 + // argv: 0 - 1 - 2 - 3 + // cmd vote - master - login - password + + if(strtolower(argv(0)) == "help") + { + if(argc == 1) + { + print("\nClient console commands:\n"); + LocalCommand_macro_help(); + + print("\nGeneric commands shared by all programs:\n"); + GenericCommand_macro_help(); + + print("\nUsage:^3 cl_cmd COMMAND...^7, where possible commands are listed above.\n"); + print("For help about a specific command, type cl_cmd help COMMAND\n"); + + return; + } + else if(GenericCommand_macro_usage(argc)) // Instead of trying to call a command, we're going to see detailed information about it + { + return; + } + else if(LocalCommand_macro_usage(argc)) // now try for normal commands too + { + return; + } + } + else if(GenericCommand(command)) + { + return; // handled by common/command/generic.qc + } + else if(LocalCommand_macro_command(argc)) // continue as usual and scan for normal commands + { + return; // handled by one of the above LocalCommand_* functions + } + + // nothing above caught the command, must be invalid + print(((command != "") ? strcat("Unknown client command \"", command, "\"") : "No command provided"), ". For a list of supported commands, try cl_cmd help.\n"); + + return; +} + + +// =================================== +// Macro system for console commands +// =================================== + +// These functions are here specifically to add special + - commands to the game, and are not really normal commands. +// Please add client commands to the function above this, as this is only for special reasons. +#define CONSOLE_COMMANDS_NORMAL \ + CONSOLE_COMMAND("+showscores", { scoreboard_showscores = TRUE; }) \ + CONSOLE_COMMAND("-showscores", { scoreboard_showscores = FALSE; }) \ + CONSOLE_COMMAND("+showaccuracy", { scoreboard_showaccuracy = TRUE; }) \ + CONSOLE_COMMAND("-showaccuracy", { scoreboard_showaccuracy = FALSE; }) \ + /* nothing */ + +#define CONSOLE_COMMANDS_MOVEMENT \ + CONSOLE_COMMAND("+forward", { ++camera_direction_x; }) \ + CONSOLE_COMMAND("-forward", { --camera_direction_x; }) \ + CONSOLE_COMMAND("+back", { --camera_direction_x; }) \ + CONSOLE_COMMAND("-back", { ++camera_direction_x; }) \ + CONSOLE_COMMAND("+moveup", { ++camera_direction_z; }) \ + CONSOLE_COMMAND("-moveup", { --camera_direction_z; }) \ + CONSOLE_COMMAND("+movedown", { --camera_direction_z; }) \ + CONSOLE_COMMAND("-movedown", { ++camera_direction_z; }) \ + CONSOLE_COMMAND("+moveright", { --camera_direction_y; }) \ + CONSOLE_COMMAND("-moveright", { ++camera_direction_y; }) \ + CONSOLE_COMMAND("+moveleft", { ++camera_direction_y; }) \ + CONSOLE_COMMAND("-moveleft", { --camera_direction_y; }) \ + CONSOLE_COMMAND("+roll_right", { ++camera_roll; }) \ + CONSOLE_COMMAND("-roll_right", { --camera_roll; }) \ + CONSOLE_COMMAND("+roll_left", { --camera_roll; }) \ + CONSOLE_COMMAND("-roll_left", { ++camera_roll; }) \ + /* nothing */ + +void ConsoleCommand_macro_init() +{ + // first init normal commands + #define CONSOLE_COMMAND(name,execution) \ + { registercommand(name); } + + CONSOLE_COMMANDS_NORMAL + #undef CONSOLE_COMMAND + + // then init movement commands + #ifndef CAMERATEST + if(isdemo()) + { + #endif + #define CONSOLE_COMMAND(name,execution) \ + { registercommand(name); } + + CONSOLE_COMMANDS_MOVEMENT + #undef CONSOLE_COMMAND + #ifndef CAMERATEST + } + #endif + + return; +} + +float ConsoleCommand_macro_normal(float argc) +{ + #define CONSOLE_COMMAND(name,execution) \ + { if(name == strtolower(argv(0))) { { execution } return TRUE; } } + + CONSOLE_COMMANDS_NORMAL + #undef CONSOLE_COMMAND + + return FALSE; +} + +float ConsoleCommand_macro_movement(float argc) +{ + if(camera_active) + { + #define CONSOLE_COMMAND(name,execution) \ + { if(name == strtolower(argv(0))) { { execution } return TRUE; } } + + CONSOLE_COMMANDS_MOVEMENT + #undef CONSOLE_COMMAND + } + + return FALSE; +} + + +// ====================================================== +// Main Function Called By Engine (registered commands) +// ====================================================== +// Used to parse commands in the console that have been registered with the "registercommand" function + +float CSQC_ConsoleCommand(string command) +{ + float argc = tokenize_console(command); + + if(ConsoleCommand_macro_normal(argc)) + { + return TRUE; + } + else if(ConsoleCommand_macro_movement(argc)) + { + return TRUE; + } + + // Return value should be 1 if CSQC handled the command, otherwise return 0 to have the engine handle it. + + return FALSE; +} \ No newline at end of file diff --git a/qcsrc/client/command/cl_cmd.qh b/qcsrc/client/command/cl_cmd.qh new file mode 100644 index 0000000000..f2db76a2cf --- /dev/null +++ b/qcsrc/client/command/cl_cmd.qh @@ -0,0 +1,10 @@ +// ============================================== +// CSQC client commands code, written by Samual +// Last updated: December 17th, 2011 +// ============================================== + +void Cmd_HUD_SetFields(float); +void Cmd_HUD_Help(); + +// used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file +void LocalCommand_macro_write_aliases(float fh); \ No newline at end of file diff --git a/qcsrc/client/csqc_builtins.qc b/qcsrc/client/csqc_builtins.qc index 32c048f25b..15e62170ba 100644 --- a/qcsrc/client/csqc_builtins.qc +++ b/qcsrc/client/csqc_builtins.qc @@ -90,7 +90,7 @@ vector (vector v) cs_project = #311; void drawline(float width, vector pos1, vector pos2, vector rgb, float alpha, float flags) = #315; float iscachedpic(string name) = #316; string precache_pic(string name, ...) = #317; -vector drawgetimagesize(string pic) = #318; +vector draw_getimagesize(string pic) = #318; void freepic(string name) = #319; float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag) = #320; float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag) = #321; @@ -120,10 +120,10 @@ void (string s, ...) print = #339; void (float scale) setsensitivityscale = #346; -void (float framenum) RetrieveMovementFrame = #345; -void () DefaultPlayerPhysics = #347; +float (float framenum) getinputstate = #345; +void (entity e) runstandardplayerphysics = #347; -string (float playernum, string key) getplayerkey = #348; +string (float playernum, string key) getplayerkeyvalue = #348; void (string cmdname) registercmd = #352; vector () getmousepos = #344; @@ -174,14 +174,14 @@ float(entity e, float s) getsurfacenumtriangles = #628; vector(entity e, float s, float n) getsurfacetriangle = #629; -float (float a, float b) min = #94; +float (float a, float b, ...) min = #94; float (float a, float b, float c) min3 = #94; float (float a, float b, float c, float d) min4 = #94; float (float a, float b, float c, float d, float e) min5 = #94; float (float a, float b, float c, float d, float e, float f) min6 = #94; float (float a, float b, float c, float d, float e, float f, float g) min7 = #94; float (float a, float b, float c, float d, float e, float f, float g, float h) min8 = #94; -float (float a, float b) max = #95; +float (float a, float b, ...) max = #95; float (float a, float b, float c) max3 = #95; float (float a, float b, float c, float d) max4 = #95; float (float a, float b, float c, float d, float e) max5 = #95; @@ -321,3 +321,38 @@ float particles_alphamin, particles_alphamax; vector particles_colormin, particles_colormax; void(float effectindex, entity own, vector org_from, vector org_to, vector dir_from, vector dir_to, float countmultiplier, float flags) boxparticles = #502; string(string format, ...) sprintf = #627; + +float(string name) cvar_type = #495; +float CVAR_TYPEFLAG_EXISTS = 1; +float CVAR_TYPEFLAG_SAVED = 2; +float CVAR_TYPEFLAG_PRIVATE = 4; +float CVAR_TYPEFLAG_ENGINE = 8; +float CVAR_TYPEFLAG_HASDESCRIPTION = 16; +float CVAR_TYPEFLAG_READONLY = 32; + +void (entity e, float chan, string samp, float vol, float atten, float pitchshift, float flags) sound7 = #8; + +float trace_dphitcontents; +float trace_networkentity; + +string(string search, string replace, string subject) strreplace = #484; + +//DP_QC_DIGEST +//idea: motorsep, Spike +//DarkPlaces implementation: divVerent +//builtin definitions: +string(string digest, string data, ...) digest_hex = #639; +//description: +//returns a given hex digest of given data +//the returned digest is always encoded in hexadecimal +//only the "MD4" digest is always supported! +//if the given digest is not supported, string_null is returned +//the digest string is matched case sensitively, use "MD4", not "md4"! + +//DP_CSQC_MINFPS_QUALITY +//idea: divVerent +//darkplaces implementation: divVerent +//constant definitions: +const float VF_MINFPS_QUALITY = 213; +//use getproperty(VF_MINFPS_QUALITY); to do CSQC based LOD based on cl_minfps +//1 should lead to an unmodified view diff --git a/qcsrc/client/csqc_constants.qc b/qcsrc/client/csqc_constants.qc index 93051cc4d1..1cd7d1f3ba 100644 --- a/qcsrc/client/csqc_constants.qc +++ b/qcsrc/client/csqc_constants.qc @@ -1,4 +1,4 @@ -const entity NULL = world; +#define world world // Mask Constants (set .drawmask on entities; use R_AddEntities to add all entities based on mask) const float MASK_ENGINE = 1; @@ -64,18 +64,6 @@ const float STAT_FRAGLIMIT = 235; const float STAT_TIMELIMIT = 236; const float STAT_MOVEVARS_GRAVITY = 242; -// Sound Constants -//const float CHAN_AUTO = 0; -//const float CHAN_WEAPON = 1; -//const float CHAN_VOICE = 2; -//const float CHAN_ITEM = 3; -//const float CHAN_BODY = 4; - -//const float ATTN_NONE = 0; -//const float ATTN_NORM = 1; -//const float ATTN_IDLE = 2; -//const float ATTN_STATIC = 3; - // Quake-style Point Contents const float CONTENT_EMPTY = -1; const float CONTENT_SOLID = -2; @@ -164,14 +152,6 @@ const float BUTTON_14 = 65536; const float BUTTON_15 = 131072; const float BUTTON_16 = 262144; - -const float DRAWFLAG_NORMAL = 0; -const float DRAWFLAG_ADDITIVE = 1; -const float DRAWFLAG_MODULATE = 2; -const float DRAWFLAG_2XMODULATE = 3; -const float DRAWFLAG_SCREEN = 4; -const float DRAWFLAG_MIPMAP = 0x100; // only for R_BeginPolygon - #define SOLID_NOT 0 // no interaction with other objects #define SOLID_TRIGGER 1 // touch on edge, but not blocking #define SOLID_BBOX 2 // touch on edge, block diff --git a/qcsrc/client/csqcmodel_hooks.qc b/qcsrc/client/csqcmodel_hooks.qc new file mode 100644 index 0000000000..7204981bd4 --- /dev/null +++ b/qcsrc/client/csqcmodel_hooks.qc @@ -0,0 +1,525 @@ +void CSQCModel_Hook_PreDraw(); + +.float isplayermodel; + +// FEATURE: LOD +.float lodmodelindex0; +.float lodmodelindex1; +.float lodmodelindex2; +void CSQCPlayer_LOD_Apply(void) +{ + // LOD model loading + if(self.lodmodelindex0 != self.modelindex) + { + string modelname = self.model; + string s; + + // set modelindex + self.lodmodelindex0 = self.modelindex; + self.lodmodelindex1 = self.modelindex; + self.lodmodelindex2 = self.modelindex; + + // FIXME: this only supports 3-letter extensions + s = strcat(substring(modelname, 0, strlen(modelname)-4), "_lod1", substring(modelname, -4, 4)); + if(fexists(s)) + { + precache_model(s); + setmodel(self, s); + if(self.modelindex) + self.lodmodelindex1 = self.modelindex; + } + + s = strcat(substring(modelname, 0, strlen(modelname)-4), "_lod2", substring(modelname, -4, 4)); + if(fexists(s)) + { + precache_model(s); + setmodel(self, s); + if(self.modelindex) + self.lodmodelindex2 = self.modelindex; + } + + setmodel(self, modelname); // make everything normal again + } + + // apply LOD + if(autocvar_cl_playerdetailreduction <= 0) + { + if(autocvar_cl_playerdetailreduction <= -2) + self.modelindex = self.lodmodelindex2; + else if(autocvar_cl_playerdetailreduction <= -1) + self.modelindex = self.lodmodelindex1; + else + self.modelindex = self.lodmodelindex0; + } + else + { + float distance = vlen(self.origin - other.origin); + float f = (distance + 100.0) * autocvar_cl_playerdetailreduction; + f *= 1.0 / bound(0.01, view_quality, 1); + if(f > autocvar_cl_loddistance2) + self.modelindex = self.lodmodelindex2; + else if(f > autocvar_cl_loddistance1) + self.modelindex = self.lodmodelindex1; + else + self.modelindex = self.lodmodelindex0; + } +} + +// FEATURE: forcemodel (MUST be called BEFORE LOD!) +string forceplayermodels_model; +float forceplayermodels_modelisgoodmodel; +float forceplayermodels_modelindex; +float forceplayermodels_skin; + +string forceplayermodels_mymodel; +float forceplayermodels_myisgoodmodel; +float forceplayermodels_mymodelindex; + +float forceplayermodels_attempted; + +.string forceplayermodels_savemodel; +.float forceplayermodels_savemodelindex; +.float forceplayermodels_saveskin; +.float forceplayermodels_savecolormap; + +.string forceplayermodels_isgoodmodel_mdl; +.float forceplayermodels_isgoodmodel; + +string forceplayermodels_goodmodel; +float forceplayermodels_goodmodelindex; + +void CSQCPlayer_ForceModel_PreUpdate(void) +{ + self.model = self.forceplayermodels_savemodel; + self.modelindex = self.forceplayermodels_savemodelindex; + self.skin = self.forceplayermodels_saveskin; + self.colormap = self.forceplayermodels_savecolormap; +} +void CSQCPlayer_ForceModel_PostUpdate(void) +{ + self.forceplayermodels_savemodel = self.model; + self.forceplayermodels_savemodelindex = self.modelindex; + self.forceplayermodels_saveskin = self.skin; + self.forceplayermodels_savecolormap = self.colormap; + + if(self.forceplayermodels_savemodel != self.forceplayermodels_isgoodmodel_mdl) + { + self.forceplayermodels_isgoodmodel = fexists(self.forceplayermodels_savemodel); + self.forceplayermodels_isgoodmodel_mdl = self.forceplayermodels_savemodel; + if(!self.forceplayermodels_isgoodmodel) + print(sprintf("Warning: missing model %s has been used\n", self.forceplayermodels_savemodel)); + } +} +void CSQCPlayer_ForceModel_Apply(float islocalplayer) +{ + // which one is ALWAYS good? + if not(forceplayermodels_goodmodel) + { + entity e; + e = spawn(); + setmodel(e, cvar_defstring("_cl_playermodel")); + forceplayermodels_goodmodel = e.model; + forceplayermodels_goodmodelindex = e.modelindex; + remove(e); + } + + // first, try finding it from the server + if(self.forceplayermodels_savemodelindex && self.forceplayermodels_savemodel != "null") + { + if(islocalplayer) + { + // trust server's idea of "own player model" + forceplayermodels_modelisgoodmodel = self.forceplayermodels_isgoodmodel; + forceplayermodels_model = self.forceplayermodels_savemodel; + forceplayermodels_modelindex = self.forceplayermodels_savemodelindex; + forceplayermodels_skin = self.forceplayermodels_saveskin; + forceplayermodels_attempted = 1; + } + } + + // forcemodel finding + if(!forceplayermodels_attempted) + { + forceplayermodels_attempted = 1; + + // only if this failed, find it out on our own + entity e; + e = spawn(); + setmodel(e, autocvar__cl_playermodel); // this is harmless, see below + forceplayermodels_modelisgoodmodel = fexists(e.model); + forceplayermodels_model = e.model; + forceplayermodels_modelindex = e.modelindex; + forceplayermodels_skin = autocvar__cl_playerskin; + remove(e); + } + + if(autocvar_cl_forcemyplayermodel != "" && autocvar_cl_forcemyplayermodel != forceplayermodels_mymodel) + { + entity e; + e = spawn(); + setmodel(e, autocvar_cl_forcemyplayermodel); // this is harmless, see below + forceplayermodels_myisgoodmodel = fexists(e.model); + forceplayermodels_mymodel = e.model; + forceplayermodels_mymodelindex = e.modelindex; + remove(e); + } + + // apply it + if(autocvar_cl_forcemyplayermodel != "" && forceplayermodels_myisgoodmodel && islocalplayer) + { + self.model = forceplayermodels_mymodel; + self.modelindex = forceplayermodels_mymodelindex; + self.skin = autocvar_cl_forcemyplayerskin; + } + else if(autocvar_cl_forceplayermodels && forceplayermodels_modelisgoodmodel) + { + self.model = forceplayermodels_model; + self.modelindex = forceplayermodels_modelindex; + self.skin = forceplayermodels_skin; + } + else if(self.forceplayermodels_isgoodmodel) + { + self.model = self.forceplayermodels_savemodel; + self.modelindex = self.forceplayermodels_savemodelindex; + self.skin = self.forceplayermodels_saveskin; + } + else + { + self.model = forceplayermodels_goodmodel; + self.modelindex = forceplayermodels_goodmodelindex; + self.skin = self.forceplayermodels_saveskin; + } + + // forceplayercolors too + if(!teamplay) + { + if(autocvar_cl_forcemyplayercolors && islocalplayer) + self.colormap = 1024 + autocvar_cl_forcemyplayercolors; + else if(autocvar_cl_forceplayercolors) + self.colormap = player_localnum + 1; + } +} + +// FEATURE: fallback frames +.float csqcmodel_saveframe; +.float csqcmodel_saveframe2; +.float csqcmodel_saveframe3; +.float csqcmodel_saveframe4; +.float csqcmodel_framecount; + +.float csqcmodel_isdead; // for utility code + +#define IS_DEAD_FRAME(f) ((f) == 0 || (f) == 1) +void CSQCPlayer_FallbackFrame_PreUpdate(void) +{ + self.frame = self.csqcmodel_saveframe; + self.frame2 = self.csqcmodel_saveframe2; + self.frame3 = self.csqcmodel_saveframe3; + self.frame4 = self.csqcmodel_saveframe4; +} +void CSQCPlayer_FallbackFrame_PostUpdate(float isnew) +{ + self.csqcmodel_saveframe = self.frame; + self.csqcmodel_saveframe2 = self.frame2; + self.csqcmodel_saveframe3 = self.frame3; + self.csqcmodel_saveframe4 = self.frame4; + + // hack for death animations: set their frametime to zero in case a + // player "pops in" + if(isnew) + { +#define FIX_FRAMETIME(f,ft) \ + if(IS_DEAD_FRAME(self.f)) \ + { \ + self.ft = self.death_time; \ + } + FIX_FRAMETIME(frame, frame1time) + FIX_FRAMETIME(frame2, frame2time) + FIX_FRAMETIME(frame3, frame3time) + FIX_FRAMETIME(frame4, frame4time) + } + self.csqcmodel_isdead = IS_DEAD_FRAME(self.frame); +} +float CSQCPlayer_FallbackFrame(float f) +{ + if(frameduration(self.modelindex, f) > 0) + return f; // goooooood + switch(f) + { + case 23: return 11; // anim_melee -> anim_shoot + case 24: return 4; // anim_duckwalkbackwards -> anim_duckwalk + case 25: return 4; // anim_duckwalkstrafeleft -> anim_duckwalk + case 26: return 4; // anim_duckwalkstraferight -> anim_duckwalk + case 27: return 4; // anim_duckwalkforwardright -> anim_duckwalk + case 28: return 4; // anim_duckwalkforwardleft -> anim_duckwalk + case 29: return 4; // anim_duckwalkbackright -> anim_duckwalk + case 30: return 4; // anim_duckwalkbackleft -> anim_duckwalk + } + print(sprintf("Frame %d missing in model %s, and we have no fallback - FAIL!\n", f, self.model)); + return f; +} +void CSQCPlayer_FallbackFrame_Apply(void) +{ + self.frame = CSQCPlayer_FallbackFrame(self.frame); + self.frame2 = CSQCPlayer_FallbackFrame(self.frame2); + self.frame3 = CSQCPlayer_FallbackFrame(self.frame3); + self.frame4 = CSQCPlayer_FallbackFrame(self.frame4); +} + +// FEATURE: auto tag_index +.entity tag_entity; +.float tag_entity_lastmodelindex; +.float tag_index; +void CSQCModel_AutoTagIndex_Apply(void) +{ + if(self.tag_entity && wasfreed(self.tag_entity)) + self.tag_entity = world; + + if(self.tag_networkentity) + { + // we are ATTACHED! + float changed = 0; + if(self.tag_entity.entnum != self.tag_networkentity) + { + self.tag_entity = findfloat(world, entnum, self.tag_networkentity); + changed = 1; + } + + // recursive predraw call to fix issues with forcemodels and LOD if bone indexes mismatch + { + entity oldself = self; + self = self.tag_entity; + CSQCModel_Hook_PreDraw(); + self = oldself; + } + + if(self.tag_entity.modelindex != self.tag_entity_lastmodelindex) + { + self.tag_entity_lastmodelindex = self.tag_entity.modelindex; + changed = 1; + } + if(changed) + { + if(self.tag_entity) + { + // the best part is: IT EXISTS + if(substring(self.model, 0, 17) == "models/weapons/v_") + if(substring(self.tag_entity.model, 0, 17) == "models/weapons/h_") + { + self.tag_index = gettagindex(self.tag_entity, "weapon"); + if(!self.tag_index) + self.tag_index = gettagindex(self.tag_entity, "tag_weapon"); + if(!self.tag_index) + { + // we need to prevent this from 'appening + self.tag_entity = world; + self.drawmask = 0; + dprint("h_ model lacks weapon attachment, but v_ model is attached to it\n"); + } + } + + if(substring(self.model, 0, 17) == "models/weapons/v_") + if(substring(self.tag_entity.model, 0, 14) == "models/player/") + { + self.tag_index = gettagindex(self.tag_entity, "tag_weapon"); + if(!self.tag_index) + self.tag_index = gettagindex(self.tag_entity, "bip01 r hand"); + } + + if(substring(self.tag_entity.model, 0, 17) == "models/weapons/v_") + { + self.tag_index = gettagindex(self.tag_entity, "shot"); + if(!self.tag_index) + self.tag_index = gettagindex(self.tag_entity, "tag_shot"); + } + } + else + { + // damn, see you next frame + self.drawmask = 0; + } + } + } +} + +// FEATURE: EF_NODRAW workalike +float EF_BRIGHTFIELD = 1; +float EF_BRIGHTLIGHT = 4; +float EF_DIMLIGHT = 8; +float EF_DOUBLESIDED = 32768; +float EF_NOSELFSHADOW = 65536; +float EF_DYNAMICMODELLIGHT = 131072; +float MF_ROCKET = 1; // leave a trail +float MF_GRENADE = 2; // leave a trail +float MF_GIB = 4; // leave a trail +float MF_ROTATE = 8; // rotate (bonus items) +float MF_TRACER = 16; // green split trail +float MF_ZOMGIB = 32; // small blood trail +float MF_TRACER2 = 64; // orange split trail +float MF_TRACER3 = 128; // purple trail +.float csqcmodel_effects; +.float csqcmodel_modelflags; +void CSQCModel_Effects_PreUpdate(void) +{ + self.effects = self.csqcmodel_effects; + self.modelflags = self.csqcmodel_modelflags; +} +void CSQCModel_Effects_PostUpdate(void) +{ + self.csqcmodel_effects = self.effects; + self.csqcmodel_modelflags = self.modelflags; + self.effects = 0; + self.modelflags = 0; + if(self.csqcmodel_teleported) + Projectile_ResetTrail(self.origin); +} +void CSQCModel_Effects_Apply(void) +{ + float eff = self.csqcmodel_effects; + eff &~= CSQCMODEL_EF_RESPAWNGHOST; + + self.renderflags &~= (RF_DEPTHHACK | RF_ADDITIVE | RF_FULLBRIGHT | EF_NOSHADOW | RF_USEAXIS); + self.effects = 0; + self.traileffect = 0; + + if(eff & EF_BRIGHTFIELD) + self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); + // ignoring EF_MUZZLEFLASH + if(eff & EF_BRIGHTLIGHT) + adddynamiclight(self.origin, 400, '3 3 3'); + if(eff & EF_DIMLIGHT) + adddynamiclight(self.origin, 200, '1.5 1.5 1.5'); + if((eff & EF_NODRAW) || (self.alpha < 0)) + self.drawmask = 0; + if(eff & EF_ADDITIVE) + self.renderflags |= RF_ADDITIVE; + if(eff & EF_BLUE) + adddynamiclight(self.origin, 200, '0.15 0.15 1.5'); + if(eff & EF_RED) + adddynamiclight(self.origin, 200, '1.5 0.15 0.15'); + // ignoring EF_NOGUNBOB + if(eff & EF_FULLBRIGHT) + self.renderflags |= RF_FULLBRIGHT; + if(eff & EF_FLAME) + pointparticles(particleeffectnum("EF_FLAME"), self.origin, '0 0 0', bound(0, frametime, 0.1)); + if(eff & EF_STARDUST) + pointparticles(particleeffectnum("EF_STARDUST"), self.origin, '0 0 0', bound(0, frametime, 0.1)); + if(eff & EF_NOSHADOW) + self.renderflags |= RF_NOSHADOW; + if(eff & EF_NODEPTHTEST) + self.renderflags |= RF_DEPTHHACK; + // ignoring EF_SELECTABLE + if(eff & EF_DOUBLESIDED) + self.effects |= EF_DOUBLESIDED; + if(eff & EF_NOSELFSHADOW) + self.effects |= EF_NOSELFSHADOW; + if(eff & EF_DYNAMICMODELLIGHT) + self.renderflags |= RF_DYNAMICMODELLIGHT; + // ignoring EF_UNUSED18, EF_UNUSED19, EF_RESTARTANIM_BIT, EF_TELEPORT_BIT, EF_LOWPRECISION + if(self.csqcmodel_modelflags & MF_ROCKET) + self.traileffect = particleeffectnum("TR_ROCKET"); + if(self.csqcmodel_modelflags & MF_GRENADE) + self.traileffect = particleeffectnum("TR_GRENADE"); + if(self.csqcmodel_modelflags & MF_GIB) + self.traileffect = particleeffectnum("TR_BLOOD"); + if(self.csqcmodel_modelflags & MF_ROTATE) + { + self.renderflags |= RF_USEAXIS; + makevectors(self.angles + '0 100 0' * fmod(time, 3.6)); + } + if(self.csqcmodel_modelflags & MF_TRACER) + self.traileffect = particleeffectnum("TR_WIZSPIKE"); + if(self.csqcmodel_modelflags & MF_ZOMGIB) + self.traileffect = particleeffectnum("TR_SLIGHTBLOOD"); + if(self.csqcmodel_modelflags & MF_TRACER2) + self.traileffect = particleeffectnum("TR_KNIGHTSPIKE"); + if(self.csqcmodel_modelflags & MF_TRACER3) + self.traileffect = particleeffectnum("TR_VORESPIKE"); + + if(self.drawmask) + Projectile_DrawTrail(self.origin); + else + Projectile_ResetTrail(self.origin); + + if(self.csqcmodel_effects & CSQCMODEL_EF_RESPAWNGHOST) + self.renderflags |= RF_ADDITIVE; + // also special in CSQCPlayer_GlowMod_Apply +} + +// FEATURE: auto glowmod +.vector glowmod; +void CSQCPlayer_GlowMod_Apply(void) +{ + float cm = self.colormap; + + if(self.csqcmodel_effects & CSQCMODEL_EF_RESPAWNGHOST) + cm = 1024; + + if(self.colormap > 0) + self.glowmod = colormapPaletteColor(((self.colormap >= 1024) ? self.colormap : stof(getplayerkeyvalue(self.colormap - 1, "colors"))) & 0x0F, TRUE) * 2; + else + self.glowmod = '1 1 1'; + + if(autocvar_cl_deathglow > 0) + if(self.csqcmodel_isdead) + { + self.glowmod = self.glowmod * bound(0, 1 - (time - self.death_time) / autocvar_cl_deathglow, 1); + // prevent the zero vector + if(self.glowmod_x == 0) + self.glowmod_x = -1; + } +} + +// general functions +.float csqcmodel_predraw_run; +void CSQCModel_Hook_PreDraw() +{ + if(self.csqcmodel_predraw_run == framecount) + return; + self.csqcmodel_predraw_run = framecount; + + if(!self.modelindex || self.model == "null") + { + self.drawmask = 0; + return; + } + else + self.drawmask = MASK_NORMAL; + + if(self.isplayermodel) // this checks if it's a player MODEL! + { + CSQCPlayer_ForceModel_Apply(self.entnum == player_localnum + 1); + CSQCPlayer_GlowMod_Apply(); + CSQCPlayer_LOD_Apply(); + CSQCPlayer_FallbackFrame_Apply(); + } + + CSQCModel_AutoTagIndex_Apply(); + + CSQCModel_Effects_Apply(); +} + +void CSQCModel_Hook_PreUpdate(float isnew, float isplayer, float islocalplayer) +{ + // revert to values from server + CSQCModel_Effects_PreUpdate(); + if(self.isplayermodel) + { + CSQCPlayer_FallbackFrame_PreUpdate(); + CSQCPlayer_ForceModel_PreUpdate(); + } +} + +void CSQCModel_Hook_PostUpdate(float isnew, float isplayer, float islocalplayer) +{ + // is it a player model? (shared state) + self.isplayermodel = (substring(self.model, 0, 14) == "models/player/"); + + // save values set by server + if(self.isplayermodel) + { + CSQCPlayer_ForceModel_PostUpdate(); + CSQCPlayer_FallbackFrame_PostUpdate(isnew); + } + CSQCModel_Effects_PostUpdate(); +} diff --git a/qcsrc/client/ctf.qc b/qcsrc/client/ctf.qc deleted file mode 100644 index 0a5375f51d..0000000000 --- a/qcsrc/client/ctf.qc +++ /dev/null @@ -1,216 +0,0 @@ -//include "main.qh" -// NOTE: This file contains lots of debugging stuff -// it is not really used... can be seen as another sample... - -string STR_PLAYER = "player"; -#define FOR_EACH_PLAYER(v) for(v = world; (v = find(v, classname, STR_PLAYER)) != world; ) - -string ctf_temp_1; -float order_page; - -void() menu_close = -{ - menu_visible = false; - menu_show = menu_show_error; - menu_action = menu_sub_null; - - /*if(ctf_temp_1) - strunzone(ctf_temp_1);*/ - - localcmd("\nin_bindmap 0 0;"); -}; - -void() order_menu_render = -{ - local vector ps, po; - local float i, p, n; - local string frags, color; - ps = '0 200 0'; - po = '0 8 0'; - - color = getplayerkey(player_localentnum-1, "topcolor"); - - if(getstati(STAT_CTF_STATE) == CTF_STATE_COMMANDER) { - drawstring(ps, "\x1D\x1E\x1E\x1E\x1E Order Menu \x1E\x1E\x1E\x1E\x1F", '8 8 0', '1 1 0', 1, 0); ps += po; - drawstring(ps, strcat("Order: ", ctf_temp_1), '8 8 0', '1 1 0', 1, 0); ps += po; - drawcolorcodedstring(ps, "1) ^3previous page", '8 8 0', 1, 0); ps += po; - drawcolorcodedstring(ps, "2) ^3next page", '8 8 0', 1, 0); ps += po; - for((n = 2), (p = i = 0); i < maxclients && n > 0; ++i) { - frags = getplayerkey(i, "frags"); - if(!frags || (i+1) == player_localentnum) - continue; - if(frags == "-666" || getplayerkey(i, "topcolor") != color) // FIXME use GetPlayerTeam - continue; - ++p; - if(p > (8*order_page)) - { - // only render current page - ++n; - if(n == 10) - n = 0; - drawcolorcodedstring(ps, strcat(ftos(n), ") ", GetPlayerName(i), " : ", ftos(getstatf(STAT_CTF_STATE))), '8 8 0', 1, 0); ps += po; - } - } - drawstring(ps, "ESC) Exit Menu", '8 8 0', '1 1 0', 1, 0); ps += po; - } else { - menu_close(); - } -}; - -float(float bInputType, float nPrimary, float nSecondary) order_menu_action = -{ - local string arg; - local float p, i, n, chose; - local string frags, color; - if(bInputType != 0) // key down wanted - return FALSE; - - arg = chr2str(nSecondary); - chose = stof(chr2str(nPrimary)); - //str2chr - if(arg == "1") { - color = getplayerkey(player_localentnum-1, "topcolor"); - ++order_page; - for(p = i = 0; i < maxclients; ++i) { - frags = getplayerkey(i, "frags"); - if(!frags || (i+1) == player_localentnum) - continue; - if(frags == "-666" || getplayerkey(i, "topcolor") != color) // FIXME use GetPlayerTeam - continue; - ++p; - } - if(p <= (8*order_page)) // no ppl on page - order_page = 0; - } else if(arg == "2") { - color = getplayerkey(player_localentnum-1, "topcolor"); - --order_page; - if(order_page < 0) { - for(p = i = 0; i < maxclients; ++i) { - frags = getplayerkey(i, "frags"); - if(!frags || (i+1) == player_localentnum) - continue; - if(frags == "-666" || getplayerkey(i, "topcolor") != color) // FIXME use GetPlayerTeam - continue; - ++p; - } - order_page = floor(p/8); - } - } else if(chose >= 3 && chose <= 9 || arg == "0") { // the 10 needs extra checking, assuming that stof(astring) returns 0 - if(chose == 0) - chose = 10; - n = 2; - color = getplayerkey(player_localentnum-1, "topcolor"); - for(p = i = 0; i < maxclients && n > 0; ++i) { - frags = getplayerkey(i, "frags"); - if(!frags || (i+1) == player_localentnum) - continue; - if(frags == "-666" || getplayerkey(i, "topcolor") != color) // FIXME use GetPlayerTeam - continue; - ++p; - if(p > (8*order_page)) - { - // only render current page - ++n; - if(n == chose) { - n = 0; - break; - } - } - } - if(n == 0) { - //print(strcat("Issuing order to: ", ftos(i+1), "\n")); - //print(strcat("cmd order #", ftos(i+1), " ", ctf_temp_1, ";\n")); - localcmd(strcat("\ncmd order #", ftos(i+1), " ", ctf_temp_1, ";")); - } else { - print(strcat("Couldn't find player ", ftos(chose), "\n")); - } - return TRUE; - } else if(nSecondary == K_ESCAPE) { - strunzone(ctf_temp_1); - menu_close(); - } else { - //print(strcat("Menu action ", arg, " does not exist.\n")); - return FALSE; - } - return TRUE; -}; - -void() order_menu_show = -{ - order_page = 0; - menu_show = order_menu_render; - menu_action = order_menu_action; -}; - - -void() ctf_menu_render = -{ - local vector ps, po; - ps = '0 200 0'; - po = '0 8 0'; - - if(getstati(STAT_CTF_STATE) == CTF_STATE_COMMANDER) { - drawstring(ps, "\x1D\x1E\x1E\x1E\x1E Command Menu \x1E\x1E\x1E\x1E\x1F", '8 8 0', '1 1 0', 1, 0); ps += po; - drawstring(ps, "Issue orders:", '8 8 0', '1 1 0', 1, 0); ps += po; - drawstring(ps, " 1) Attack ", '8 8 0', '1 1 0', 1, 0); - drawstring(ps + '80 0 0', " \x0F", '8 8 0', '1 1 1', 1, 0); ps += po; - drawstring(ps, " 2) Defend \x0E", '8 8 0', '1 1 0', 1, 0); ps += po; - ps += po; - drawstring(ps, "3) Resign from command.", '8 8 0', '1 1 0', 1, 0); ps += po; - drawstring(ps, "ESC) Exit Menu", '8 8 0', '1 1 0', 1, 0); ps += po; - } else { - menu_close(); - } -}; - -float(float bInputType, float nPrimary, float nSecondary) ctf_menu_action = -{ - local string arg; - if(bInputType != 0) // key down wanted - return FALSE; - - arg = chr2str(nSecondary); - - if(arg == "1") { - ctf_temp_1 = strzone("attack"); - order_menu_show(); - } else if(arg == "2") { - ctf_temp_1 = strzone("defend"); - order_menu_show(); - } else if(arg == "3") { - localcmd("\ncmd order resign;"); - menu_close(); - } else if(nSecondary == K_ESCAPE) { - menu_close(); - } else { - //print(strcat("Menu action ", arg, " does not exist.\n")); - return FALSE; - } - return TRUE; -}; - -void() ctf_menu_show = -{ - if(getstati(STAT_CTF_STATE) < 0) - return; - menu_show = ctf_menu_render; - menu_action = ctf_menu_action; - menu_visible = TRUE; - //menu_default_binds(); -}; - -void() ctf_view = -{ - local float stat; - stat = getstati(STAT_CTF_STATE); - if(stat == CTF_STATE_ATTACK) { - drawpic('0 0 0', "gfx/ctf_ic_atk.tga", '64 64 0', '1 1 1', 1, 0); - } else if(stat == CTF_STATE_DEFEND) { - drawpic('0 0 0', "gfx/ctf_ic_def.tga", '64 64 0', '1 1 1', 1, 0); - } else if(stat == CTF_STATE_COMMANDER) { - drawstring('0 0 0', "You're commander!", '8 8 0', '1 1 1', 1, 0); - } else if(stat < 0) { - } else { - drawstring('0 0 0', "Awaiting orders...", '8 8 0', '1 1 1', 0.5, 0); - } -}; diff --git a/qcsrc/client/damage.qc b/qcsrc/client/damage.qc index 24c5f0153b..5910dba3e4 100644 --- a/qcsrc/client/damage.qc +++ b/qcsrc/client/damage.qc @@ -30,13 +30,16 @@ void Ent_DamageInfo(float isNew) else forcemul = 1; - for(self = findradius(w_org, rad); self; self = self.chain) + for(self = findradius(w_org, rad + MAX_DAMAGEEXTRARADIUS); self; self = self.chain) { + vector nearest = NearestPointOnBox(self, w_org); if(rad) { - thisdmg = vlen(self.origin - w_org) / rad; + thisdmg = ((vlen (nearest - w_org) - bound(MIN_DAMAGEEXTRARADIUS, self.damageextraradius, MAX_DAMAGEEXTRARADIUS)) / rad); if(thisdmg >= 1) continue; + if(thisdmg < 0) + thisdmg = 0; if(dmg) { thisdmg = dmg + (edge - dmg) * thisdmg; @@ -50,19 +53,18 @@ void Ent_DamageInfo(float isNew) } else { + if(vlen(nearest - w_org) > bound(MIN_DAMAGEEXTRARADIUS, self.damageextraradius, MAX_DAMAGEEXTRARADIUS)) + continue; + thisdmg = dmg; thisforce = forcemul * force; } - //print("check ", ftos(num_for_edict(self)), " ", self.classname, "\n"); - //print(ftos(self.damageforcescale), "\n"); - //print(vtos(thisforce), "\n"); if(self.damageforcescale) if(vlen(thisforce)) { - self.move_velocity = self.move_velocity + self.damageforcescale * thisforce; + self.move_velocity = self.move_velocity + damage_explosion_calcpush(self.damageforcescale * thisforce, self.move_velocity, autocvar_g_balance_damagepush_speedfactor); self.move_flags &~= FL_ONGROUND; - //print("pushed ", ftos(num_for_edict(self)), " loose\n"); } if(w_issilent) @@ -73,9 +75,140 @@ void Ent_DamageInfo(float isNew) } self = oldself; + + if(DEATH_ISVEHICLE(w_deathtype)) + { + traceline(w_org - normalize(force) * 16, w_org + normalize(force) * 16, MOVE_NOMONSTERS, world); + if(trace_plane_normal != '0 0 0') + w_backoff = trace_plane_normal; + else + w_backoff = -1 * normalize(w_org - (w_org + normalize(force) * 16)); + + setorigin(self, w_org + w_backoff * 2); // for sound() calls + + switch(w_deathtype) + { + case DEATH_VHCRUSH: + break; + + case DEATH_SBMINIGUN: + string _snd; + _snd = strcat("weapons/ric", ftos(1 + rint(random() * 2)), ".waw"); + sound(self, CH_SHOTS, _snd, VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("spiderbot_minigun_impact"), self.origin, w_backoff * 1000, 1); + break; + case DEATH_SBROCKET: + sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("spiderbot_rocket_explode"), self.origin, w_backoff * 1000, 1); + break; + case DEATH_SBBLOWUP: + sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_MIN); + pointparticles(particleeffectnum("explosion_big"), self.origin, w_backoff * 1000, 1); + break; + + case DEATH_WAKIGUN: + sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("wakizashi_gun_impact"), self.origin, w_backoff * 1000, 1); + break; + case DEATH_WAKIROCKET: + sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("wakizashi_rocket_explode"), self.origin, w_backoff * 1000, 1); + break; + case DEATH_WAKIBLOWUP: + sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_MIN); + pointparticles(particleeffectnum("explosion_big"), self.origin, w_backoff * 1000, 1); + break; + + case DEATH_RAPTOR_CANNON: + sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("raptor_cannon_impact"), self.origin, w_backoff * 1000, 1); + break; + case DEATH_RAPTOR_BOMB_SPLIT: + float i; + vector ang, vel; + for(i = 1; i < 4; ++i) + { + vel = normalize(w_org - (w_org + normalize(force) * 16)) + randomvec() * 128; + ang = vectoangles(vel); + RaptorCBShellfragToss(w_org, vel, ang + '0 0 1' * (120 * i)); + } + + + sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("raptor_bomb_spread"), self.origin, w_backoff * 1000, 1); + break; + case DEATH_RAPTOR_BOMB: + sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("raptor_bomb_impact"), self.origin, w_backoff * 1000, 1); + break; + case DEATH_RAPTOR_DEATH: + sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_MIN); + pointparticles(particleeffectnum("explosion_big"), self.origin, w_backoff * 1000, 1); + break; + } + } + + + if(DEATH_ISTURRET(w_deathtype)) + { + string _snd; + traceline(w_org - normalize(force) * 16, w_org + normalize(force) * 16, MOVE_NOMONSTERS, world); + if(trace_plane_normal != '0 0 0') + w_backoff = trace_plane_normal; + else + w_backoff = -1 * normalize(w_org - (w_org + normalize(force) * 16)); + + setorigin(self, w_org + w_backoff * 2); // for sound() calls + + switch(w_deathtype) + { + case DEATH_TURRET_EWHEEL: + sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_MIN); + pointparticles(particleeffectnum("laser_impact"), self.origin, w_backoff * 1000, 1); + break; + + case DEATH_TURRET_FLAC: + pointparticles(particleeffectnum("hagar_explode"), w_org, '0 0 0', 1); + _snd = strcat("weapons/hagexp", ftos(1 + rint(random() * 2)), ".waw"); + sound(self, CH_SHOTS, _snd, VOL_BASE, ATTN_NORM); + break; + + case DEATH_TURRET_MLRS: + case DEATH_TURRET_HK: + case DEATH_TURRET_WALKER_ROCKET: + case DEATH_TURRET_HELLION: + sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_MIN); + pointparticles(particleeffectnum("rocket_explode"), self.origin, w_backoff * 1000, 1); + break; + + case DEATH_TURRET_MACHINEGUN: + case DEATH_TURRET_WALKER_GUN: + _snd = strcat("weapons/ric", ftos(1 + rint(random() * 2)), ".waw"); + sound(self, CH_SHOTS, _snd, VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("machinegun_impact"), self.origin, w_backoff * 1000, 1); + break; + + case DEATH_TURRET_PLASMA: + sound(self, CH_SHOTS, "weapons/electro_impact.wav", VOL_BASE, ATTN_MIN); + pointparticles(particleeffectnum("electro_impact"), self.origin, w_backoff * 1000, 1); + break; + + case DEATH_TURRET_WALKER_MEELE: + sound(self, CH_SHOTS, "weapons/ric1.wav", VOL_BASE, ATTN_MIN); + pointparticles(particleeffectnum("TE_SPARK"), self.origin, w_backoff * 1000, 1); + break; - // TODO spawn particle effects and sounds based on w_deathtype + case DEATH_TURRET_PHASER: + break; + + case DEATH_TURRET_TESLA: + te_smallflash(self.origin); + break; + + } + } + // TODO spawn particle effects and sounds based on w_deathtype if(!DEATH_ISSPECIAL(w_deathtype)) { float hitwep; diff --git a/qcsrc/client/effects.qc b/qcsrc/client/effects.qc index 5793ed88b2..b695867ca3 100644 --- a/qcsrc/client/effects.qc +++ b/qcsrc/client/effects.qc @@ -57,19 +57,16 @@ void cl_effetcs_lightningarc(vector from, vector to,float seglength,float drifts dirnew = normalize(direction * (1 - drift) + randomvec() * drift); pos = pos_l + dirnew * steplength; te_lightning1(world,pos_l,pos); - //b_make(pos_l, pos,"particles/lightning2",0.25,64); if(random() < branchfactor) cl_effetcs_lightningarc(pos, pos + (dirnew * length * 0.25),seglength,drifts,drifte,min(branchfactor + branchfactor_add,1),branchfactor_add); pos_l = pos; } te_lightning1(world,pos_l,to); - //b_make(pos_l, to,"particles/lightning2",0.25,64); } else te_lightning1(world,from,to); - //b_make(from, to,"particles/lightning2",0.25,64); } diff --git a/qcsrc/client/gibs.qc b/qcsrc/client/gibs.qc index 1f8af46ca1..6f6316bec1 100644 --- a/qcsrc/client/gibs.qc +++ b/qcsrc/client/gibs.qc @@ -52,8 +52,8 @@ void new_te_bloodshower (float ef, vector org, float explosionspeed, float howma { float i, pmod; pmod = autocvar_cl_particles_quality; - for (i = 0; i < 250 * pmod; ++i) - pointparticles(ef, org, randomvec() * explosionspeed, howmany / 250); + for (i = 0; i < 50 * pmod; ++i) + pointparticles(ef, org, randomvec() * explosionspeed, howmany / 50); } void SUB_RemoveOnNoImpact() @@ -73,7 +73,7 @@ void Gib_Touch() } if(!self.silent) - sound(self, CHAN_PAIN, strcat("misc/gib_splat0", ftos(floor(prandom() * 4 + 1)), ".wav"), VOL_BASE, ATTN_NORM); + sound(self, CH_PAIN, strcat("misc/gib_splat0", ftos(floor(prandom() * 4 + 1)), ".wav"), VOL_BASE, ATTN_NORM); pointparticles(particleeffectnum(strcat(species_prefix(self.cnt), "blood")), self.origin + '0 0 1', '0 0 30', 10); Gib_Delete(); @@ -89,11 +89,17 @@ void Gib_Draw() return; if(self.touch == Gib_Touch) // don't do this for the "chunk" thingie... + // TODO somehow make it spray in a direction dependent on self.angles trailparticles(self, particleeffectnum(strcat(species_prefix(self.cnt), "TR_SLIGHTBLOOD")), oldorg, self.origin); else trailparticles(self, particleeffectnum(strcat(species_prefix(self.cnt), "TR_BLOOD")), oldorg, self.origin); self.renderflags = 0; + + // make gibs die faster at low view quality + // if view_quality is 0.5, we want to have them die twice as fast + self.nextthink -= frametime * (1 / bound(0.01, view_quality, 1.00) - 1); + self.alpha = bound(0, self.nextthink - time, 1); if(self.alpha < ALPHA_MIN_VISIBLE) @@ -103,7 +109,7 @@ void Gib_Draw() } } -void TossGib (string mdlname, vector org, vector vconst, vector vrand, float specnum, float destroyontouch, float issilent) +void TossGib (string mdlname, vector safeorg, vector org, vector vconst, vector vrand, float specnum, float destroyontouch, float issilent) { entity gib; @@ -124,9 +130,16 @@ void TossGib (string mdlname, vector org, vector vconst, vector vrand, float spe else gib.move_touch = SUB_RemoveOnNoImpact; + // don't spawn gibs inside solid - just don't + if(org != safeorg) + { + tracebox(safeorg, gib.mins, gib.maxs, org, MOVE_NOMONSTERS, gib); + org = trace_endpos; + } + gib.move_origin = gib.origin = org; gib.move_velocity = vconst * autocvar_cl_gibs_velocity_scale + vrand * autocvar_cl_gibs_velocity_random + '0 0 1' * autocvar_cl_gibs_velocity_up; - gib.move_avelocity = prandomvec() * vlen(gib.move_velocity); + gib.move_avelocity = prandomvec() * vlen(gib.move_velocity) * autocvar_cl_gibs_avelocity_scale; gib.move_time = time; gib.damageforcescale = autocvar_cl_gibs_damageforcescale; @@ -192,40 +205,40 @@ void Ent_GibSplash(float isNew) { case 0x01: if(!issilent) - sound (self, CHAN_PAIN, "misc/gib.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_PAIN, "misc/gib.wav", VOL_BASE, ATTN_NORM); if(prandom() < amount) - TossGib ("models/gibs/eye.md3", org, vel, prandomvec() * 150, specnum, 0, issilent); + TossGib ("models/gibs/eye.md3", org, org, vel, prandomvec() * 150, specnum, 0, issilent); new_te_bloodshower(particleeffectnum(strcat(specstr, "bloodshower")), org, 1200, amount); if(prandom() < amount) - TossGib ("models/gibs/bloodyskull.md3", org + 16 * prandomvec(), vel, prandomvec() * 100, specnum, 0, issilent); + TossGib ("models/gibs/bloodyskull.md3", org, org + 16 * prandomvec(), vel, prandomvec() * 100, specnum, 0, issilent); for(c = 0; c < amount; ++c) { randomvalue = amount - c; if(prandom() < randomvalue) - TossGib ("models/gibs/arm.md3", org + 16 * prandomvec() + '0 0 8', vel, prandomvec() * (prandom() * 120 + 90), specnum,0, issilent); + TossGib ("models/gibs/arm.md3", org, org + 16 * prandomvec() + '0 0 8', vel, prandomvec() * (prandom() * 120 + 90), specnum,0, issilent); if(prandom() < randomvalue) - TossGib ("models/gibs/arm.md3", org + 16 * prandomvec() + '0 0 8', vel, prandomvec() * (prandom() * 120 + 90), specnum,0, issilent); + TossGib ("models/gibs/arm.md3", org, org + 16 * prandomvec() + '0 0 8', vel, prandomvec() * (prandom() * 120 + 90), specnum,0, issilent); if(prandom() < randomvalue) - TossGib ("models/gibs/chest.md3", org + 16 * prandomvec(), vel, prandomvec() * (prandom() * 120 + 80), specnum,0, issilent); + TossGib ("models/gibs/chest.md3", org, org + 16 * prandomvec(), vel, prandomvec() * (prandom() * 120 + 80), specnum,0, issilent); if(prandom() < randomvalue) - TossGib ("models/gibs/smallchest.md3", org + 16 * prandomvec(), vel, prandomvec() * (prandom() * 120 + 80), specnum,0, issilent); + TossGib ("models/gibs/smallchest.md3", org, org + 16 * prandomvec(), vel, prandomvec() * (prandom() * 120 + 80), specnum,0, issilent); if(prandom() < randomvalue) - TossGib ("models/gibs/leg1.md3", org + 16 * prandomvec() + '0 0 -5', vel, prandomvec() * (prandom() * 120 + 85), specnum,0, issilent); + TossGib ("models/gibs/leg1.md3", org, org + 16 * prandomvec() + '0 0 -5', vel, prandomvec() * (prandom() * 120 + 85), specnum,0, issilent); if(prandom() < randomvalue) - TossGib ("models/gibs/leg2.md3", org + 16 * prandomvec() + '0 0 -5', vel, prandomvec() * (prandom() * 120 + 85), specnum,0, issilent); + TossGib ("models/gibs/leg2.md3", org, org + 16 * prandomvec() + '0 0 -5', vel, prandomvec() * (prandom() * 120 + 85), specnum,0, issilent); // these splat on impact if(prandom() < randomvalue) - TossGib ("models/gibs/chunk.mdl", org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent); + TossGib ("models/gibs/chunk.mdl", org, org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent); if(prandom() < randomvalue) - TossGib ("models/gibs/chunk.mdl", org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent); + TossGib ("models/gibs/chunk.mdl", org, org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent); if(prandom() < randomvalue) - TossGib ("models/gibs/chunk.mdl", org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent); + TossGib ("models/gibs/chunk.mdl", org, org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent); if(prandom() < randomvalue) - TossGib ("models/gibs/chunk.mdl", org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent); + TossGib ("models/gibs/chunk.mdl", org, org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent); } break; case 0x02: @@ -233,7 +246,7 @@ void Ent_GibSplash(float isNew) break; case 0x03: if(prandom() < amount) - TossGib ("models/gibs/chunk.mdl", org, vel, prandomvec() * (prandom() * 30 + 20), specnum, 1, issilent); // TODO maybe adjust to more randomization? + TossGib ("models/gibs/chunk.mdl", org, org, vel, prandomvec() * (prandom() * 30 + 20), specnum, 1, issilent); // TODO maybe adjust to more randomization? break; case 0x81: pointparticles(particleeffectnum(strcat(gentle_prefix, "damage_dissolve")), org, vel, amount); diff --git a/qcsrc/client/hook.qc b/qcsrc/client/hook.qc index 09327e30aa..641d50d634 100644 --- a/qcsrc/client/hook.qc +++ b/qcsrc/client/hook.qc @@ -4,7 +4,7 @@ .float HookSilent; .float HookRange; -void Draw_CylindricLine(vector from, vector to, float thickness, string texture, float aspect, float shift, vector rgb, float alpha, float drawflag, vector vieworg) +void Draw_CylindricLine(vector from, vector to, float thickness, string texture, float aspect, float shift, vector rgb, float theAlpha, float drawflag, vector vieworg) { // I want to draw a quad... // from and to are MIDPOINTS. @@ -18,23 +18,16 @@ void Draw_CylindricLine(vector from, vector to, float thickness, string texture, // direction is perpendicular to the view normal, and perpendicular to the axis thickdir = normalize(cross(axis, vieworg - from)); -/* - print("from ", vtos(from), "\n"); - print("to ", vtos(to), "\n"); - print("org ", vtos(view_origin), "\n"); - print("dir ", vtos(thickdir), "\n"); -*/ - A = from - thickdir * (thickness / 2); B = from + thickdir * (thickness / 2); C = to + thickdir * (thickness / 2); D = to - thickdir * (thickness / 2); R_BeginPolygon(texture, drawflag); - R_PolygonVertex(A, '0 0 0' + shift * '1 0 0', rgb, alpha); - R_PolygonVertex(B, '0 1 0' + shift * '1 0 0', rgb, alpha); - R_PolygonVertex(C, '0 1 0' + (shift + length_tex) * '1 0 0', rgb, alpha); - R_PolygonVertex(D, '0 0 0' + (shift + length_tex) * '1 0 0', rgb, alpha); + R_PolygonVertex(A, '0 0 0' + shift * '1 0 0', rgb, theAlpha); + R_PolygonVertex(B, '0 1 0' + shift * '1 0 0', rgb, theAlpha); + R_PolygonVertex(C, '0 1 0' + (shift + length_tex) * '1 0 0', rgb, theAlpha); + R_PolygonVertex(D, '0 0 0' + (shift + length_tex) * '1 0 0', rgb, theAlpha); R_EndPolygon(); } @@ -66,7 +59,7 @@ void Draw_GrapplingHook() if(self.teleport_time) if(time > self.teleport_time) { - sound (self, CHAN_PROJECTILE, "misc/null.wav", VOL_BASE, ATTN_NORM); // safeguard + sound (self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTN_NORM); // safeguard self.teleport_time = 0; } @@ -222,7 +215,7 @@ void Draw_GrapplingHook() void Remove_GrapplingHook() { - sound (self, CHAN_PROJECTILE, "misc/null.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTN_NORM); } void Ent_ReadHook(float bIsNew, float type) @@ -282,10 +275,10 @@ void Ent_ReadHook(float bIsNew, float type) self.drawmask = MASK_NORMAL; break; case ENT_CLIENT_LGBEAM: - sound (self, CHAN_PROJECTILE, "weapons/lgbeam_fly.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_SHOTS_SINGLE, "weapons/lgbeam_fly.wav", VOL_BASE, ATTN_NORM); break; case ENT_CLIENT_GAUNTLET: - sound (self, CHAN_PROJECTILE, "weapons/gauntletbeam_fly.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_SHOTS_SINGLE, "weapons/gauntletbeam_fly.wav", VOL_BASE, ATTN_NORM); break; } } diff --git a/qcsrc/client/hud.qc b/qcsrc/client/hud.qc index 2f3ec3b174..8db3f00eb3 100644 --- a/qcsrc/client/hud.qc +++ b/qcsrc/client/hud.qc @@ -89,11 +89,12 @@ void draw_BorderPicture(vector theOrigin, string pic, vector theSize, vector the vector HUD_Get_Num_Color (float x, float maxvalue) { + float blinkingamt; vector color; - if(x > maxvalue) { - color_x = 0; + if(x >= maxvalue) { + color_x = sin(2*M_PI*time); color_y = 1; - color_z = 0; + color_z = sin(2*M_PI*time); } else if(x > maxvalue * 0.75) { color_x = 0.4 - (x-150)*0.02 * 0.4; //red value between 0.4 -> 0 @@ -120,6 +121,14 @@ vector HUD_Get_Num_Color (float x, float maxvalue) color_y = 0; color_z = 0; } + + blinkingamt = (1 - x/maxvalue/0.25); + if(blinkingamt > 0) + { + color_x = color_x - color_x * blinkingamt * sin(2*M_PI*time); + color_y = color_y - color_y * blinkingamt * sin(2*M_PI*time); + color_z = color_z - color_z * blinkingamt * sin(2*M_PI*time); + } return color; } @@ -133,207 +142,28 @@ float stringwidth_nocolors(string s, vector theSize) return stringwidth(s, FALSE, theSize); } -#define CENTERPRINT_MAX_LINES 30 -string centerprint_messages[CENTERPRINT_MAX_LINES]; -float centerprint_width[CENTERPRINT_MAX_LINES]; -float centerprint_time; -float centerprint_expire; -float centerprint_num; -float centerprint_offset_hint; -vector centerprint_fontsize; - -void centerprint(string strMessage) -{ - float i, j, n, hcount; - string s; - - centerprint_fontsize = HUD_GetFontsize("scr_centersize"); - - centerprint_expire = min(centerprint_expire, time); // if any of the returns happens, this message will fade out - - if(autocvar_scr_centertime <= 0) - return; - - if(strMessage == "") - return; - - // strip trailing newlines - j = strlen(strMessage) - 1; - while(substring(strMessage, j, 1) == "\n" && j >= 0) - j = j - 1; - strMessage = substring(strMessage, 0, j + 1); - - if(strMessage == "") - return; - - // strip leading newlines and remember them, they are a hint that the message should be lower on the screen - j = 0; - while(substring(strMessage, j, 1) == "\n" && j < strlen(strMessage)) - j = j + 1; - strMessage = substring(strMessage, j, strlen(strMessage) - j); - centerprint_offset_hint = j; - - if(strMessage == "") - return; - - // if we get here, we have a message. Initialize its height. - centerprint_num = 0; - - n = tokenizebyseparator(strMessage, "\n"); - i = hcount = 0; - for(j = 0; j < n; ++j) - { - getWrappedLine_remaining = argv(j); - while(getWrappedLine_remaining) - { - s = getWrappedLine(vid_conwidth * 0.75, centerprint_fontsize, stringwidth_colors); - if(centerprint_messages[i] != s) // don't fade the same message in, looks stupid - centerprint_time = time; - if(centerprint_messages[i]) - strunzone(centerprint_messages[i]); - centerprint_messages[i] = strzone(s); - centerprint_width[i] = stringwidth(s, TRUE, centerprint_fontsize); - ++i; - - // half height for empty lines looks better - if(s == "") - hcount += 0.5; - else - hcount += 1; - - if(i >= CENTERPRINT_MAX_LINES) - break; - } - } - - float h, havail; - h = centerprint_fontsize_y*hcount; - - havail = vid_conheight; - if(autocvar_con_chatpos < 0) - havail -= (-autocvar_con_chatpos + autocvar_con_chat) * autocvar_con_chatsize; // avoid overlapping chat - if(havail > vid_conheight - 70) - havail = vid_conheight - 70; // avoid overlapping HUD - -#if 0 - float forbiddenmin, forbiddenmax, allowedmin, allowedmax, preferred; - - // here, the centerprint would cover the crosshair. REALLY BAD. - forbiddenmin = vid_conheight * 0.5 - h - 16; - forbiddenmax = vid_conheight * 0.5 + 16; - - allowedmin = scoreboard_bottom; - allowedmax = havail - h; - preferred = (havail - h)/2; - - - // possible orderings (total: 4! / 4 = 6) - // allowedmin allowedmax forbiddenmin forbiddenmax - // forbiddenmin forbiddenmax allowedmin allowedmax - if(allowedmax < forbiddenmin || allowedmin > forbiddenmax) - { - // forbidden doesn't matter in this case - centerprint_start_y = bound(allowedmin, preferred, allowedmax); - } - // allowedmin forbiddenmin allowedmax forbiddenmax - else if(allowedmin < forbiddenmin && allowedmax < forbiddenmax) - { - centerprint_start_y = bound(allowedmin, preferred, forbiddenmin); - } - // allowedmin forbiddenmin forbiddenmax allowedmax - else if(allowedmin < forbiddenmin) - { - // make sure the forbidden zone is not covered - if(preferred > (forbiddenmin + forbiddenmax) * 0.5) - centerprint_start_y = bound(allowedmin, preferred, forbiddenmin); - else - centerprint_start_y = bound(forbiddenmax, preferred, allowedmin); - } - // forbiddenmin allowedmin allowedmax forbiddenmax - else if(allowedmax < forbiddenmax) - { - // it's better to leave the allowed zone (overlap with scoreboard) than - // to cover the forbidden zone (crosshair) - if(preferred > (forbiddenmin + forbiddenmax) * 0.5) - centerprint_start_y = forbiddenmax; - else - centerprint_start_y = forbiddenmin; - } - // forbiddenmin allowedmin forbiddenmax allowedmax - else - { - centerprint_start_y = bound(forbiddenmax, preferred, allowedmax); - } -#else -#endif - - centerprint_num = i; - - centerprint_expire = time + autocvar_scr_centertime; -} - -void HUD_DrawCenterPrint (void) -{ - float i; - vector pos; - string ts; - float a, sz; - - if(time - centerprint_time < 0.25) - a = (time - centerprint_time) / 0.25; - else - a = bound(0, 1 - 4 * (time - centerprint_expire), 1); - - if(a <= 0) - return; - - sz = 0.8 + (a / 5); - - if(centerprint_num * autocvar_scr_centersize > 24 && scoreboard_active) // 24 = height of Scoreboard text - centerprint_start_y = scoreboard_bottom + centerprint_fontsize_y; - - pos = centerprint_start; - for (i=0; i<centerprint_num; i = i + 1) - { - ts = centerprint_messages[i]; - drawfontscale = sz * '1 1 0'; - drawfont = hud_bigfont; - pos_x = (vid_conwidth - stringwidth(ts, TRUE, centerprint_fontsize)) * 0.5; - if (ts != "") - { - drawcolorcodedstring(pos + '0 1 0' * (1 - sz) * 0.5 *centerprint_fontsize_y, ts, centerprint_fontsize, a, DRAWFLAG_NORMAL); - pos_y = pos_y + centerprint_fontsize_y; - } - else - // half height for empty lines looks better - pos_y = pos_y + sz * centerprint_fontsize_y * 0.5; - drawfontscale = '1 1 0'; - drawfont = hud_font; - } -} - -void drawstringright(vector position, string text, vector scale, vector rgb, float alpha, float flag) +void drawstringright(vector position, string text, vector scale, vector rgb, float theAlpha, float flag) { position_x -= 2 / 3 * strlen(text) * scale_x; - drawstring(position, text, scale, rgb, alpha, flag); + drawstring(position, text, scale, rgb, theAlpha, flag); } -void drawstringcenter(vector position, string text, vector scale, vector rgb, float alpha, float flag) +void drawstringcenter(vector position, string text, vector scale, vector rgb, float theAlpha, float flag) { position_x = 0.5 * (vid_conwidth - 0.6025 * strlen(text) * scale_x); - drawstring(position, text, scale, rgb, alpha, flag); + drawstring(position, text, scale, rgb, theAlpha, flag); } // return the string of the given race place string race_PlaceName(float pos) { if(pos == 1) - return "1st"; + return _("1st"); else if(pos == 2) - return "2nd"; + return _("2nd"); else if(pos == 3) - return "3rd"; + return _("3rd"); else - return strcat(ftos(pos), "th"); + return sprintf(_("%dth"), pos); } // return the string of the onscreen race timer @@ -365,12 +195,12 @@ string MakeRaceString(float cp, float mytime, float histime, float lapdelta, str if(lapdelta > 0) { - lapstr = strcat(" (-", ftos(lapdelta), "L)"); + lapstr = sprintf(_(" (-%dL)"), lapdelta); col = "^2"; } else if(lapdelta < 0) { - lapstr = strcat(" (+", ftos(-lapdelta), "L)"); + lapstr = sprintf(_(" (+%dL)"), -lapdelta); col = "^1"; } } @@ -386,20 +216,20 @@ string MakeRaceString(float cp, float mytime, float histime, float lapdelta, str col = "^7"; if(cp == 254) - cpname = "Start line"; + cpname = _("Start line"); else if(cp == 255) - cpname = "Finish line"; + cpname = _("Finish line"); else if(cp) - cpname = strcat("Intermediate ", ftos(cp)); + cpname = sprintf(_("Intermediate %d"), cp); else - cpname = "Finish line"; + cpname = _("Finish line"); if(histime < 0) return strcat(col, cpname); else if(hisname == "") - return strcat(col, cpname, " (", timestr, ")"); + return strcat(col, sprintf(_("%s (%s)"), cpname, timestr)); else - return strcat(col, cpname, " (", timestr, " ", strcat(hisname, col, lapstr), ")"); + return strcat(col, sprintf(_("%s (%s %s)"), cpname, timestr, strcat(hisname, col, lapstr))); } // Check if the given name already exist in race rankings? In that case, where? (otherwise return 0) @@ -417,1053 +247,134 @@ HUD panels ================== */ -#define HUD_Write(s) fputs(fh, s) -// q: quoted, n: not quoted -#define HUD_Write_Cvar_n(cvar) HUD_Write(strcat("seta ", cvar, " ", cvar_string(cvar), "\n")) -#define HUD_Write_Cvar_q(cvar) HUD_Write(strcat("seta ", cvar, " \"", cvar_string(cvar), "\"\n")) -#define HUD_Write_PanelCvar_n(cvar_suf) HUD_Write_Cvar_n(strcat("hud_panel_", panel_name, cvar_suf)) -#define HUD_Write_PanelCvar_q(cvar_suf) HUD_Write_Cvar_q(strcat("hud_panel_", panel_name, cvar_suf)) -// Save the config -void HUD_Panel_ExportCfg(string cfgname) -{ - float fh; - string filename = strcat("hud_", autocvar_hud_skin, "_", cfgname, ".cfg"); - fh = fopen(filename, FILE_WRITE); - if(fh >= 0) - { - HUD_Write_Cvar_q("hud_skin"); - HUD_Write_Cvar_q("hud_panel_bg"); - HUD_Write_Cvar_q("hud_panel_bg_color"); - HUD_Write_Cvar_q("hud_panel_bg_color_team"); - HUD_Write_Cvar_q("hud_panel_bg_alpha"); - HUD_Write_Cvar_q("hud_panel_bg_border"); - HUD_Write_Cvar_q("hud_panel_bg_padding"); - HUD_Write_Cvar_q("hud_panel_fg_alpha"); - HUD_Write("\n"); - - HUD_Write_Cvar_q("hud_dock"); - HUD_Write_Cvar_q("hud_dock_color"); - HUD_Write_Cvar_q("hud_dock_color_team"); - HUD_Write_Cvar_q("hud_dock_alpha"); - HUD_Write("\n"); - - HUD_Write_Cvar_q("hud_progressbar_alpha"); - HUD_Write_Cvar_q("hud_progressbar_strength_color"); - HUD_Write_Cvar_q("hud_progressbar_shield_color"); - HUD_Write_Cvar_q("hud_progressbar_health_color"); - HUD_Write_Cvar_q("hud_progressbar_armor_color"); - HUD_Write_Cvar_q("hud_progressbar_fuel_color"); - HUD_Write_Cvar_q("hud_progressbar_nexball_color"); - HUD_Write("\n"); - - HUD_Write_Cvar_q("_hud_panelorder"); - HUD_Write("\n"); - - HUD_Write_Cvar_q("hud_configure_grid"); - HUD_Write_Cvar_q("hud_configure_grid_xsize"); - HUD_Write_Cvar_q("hud_configure_grid_ysize"); - HUD_Write("\n"); - - HUD_Write_Cvar_q("scr_centerpos"); - HUD_Write("\n"); - - // common cvars for all panels - float i; - for (i = 0; i < HUD_PANEL_NUM; ++i) - { - HUD_Panel_GetName(i); - - HUD_Write_PanelCvar_n(""); - HUD_Write_PanelCvar_q("_pos"); - HUD_Write_PanelCvar_q("_size"); - HUD_Write_PanelCvar_q("_bg"); - HUD_Write_PanelCvar_q("_bg_color"); - HUD_Write_PanelCvar_q("_bg_color_team"); - HUD_Write_PanelCvar_q("_bg_alpha"); - HUD_Write_PanelCvar_q("_bg_border"); - HUD_Write_PanelCvar_q("_bg_padding"); - switch(i) { - case HUD_PANEL_WEAPONS: - HUD_Write_PanelCvar_q("_complainbubble"); - HUD_Write_PanelCvar_q("_complainbubble_padding"); - HUD_Write_PanelCvar_q("_complainbubble_color_outofammo"); - HUD_Write_PanelCvar_q("_complainbubble_color_donthave"); - HUD_Write_PanelCvar_q("_complainbubble_color_unavailable"); - HUD_Write_PanelCvar_q("_ammo_color"); - HUD_Write_PanelCvar_q("_ammo_alpha"); - HUD_Write_PanelCvar_q("_aspect"); - HUD_Write_PanelCvar_q("_timeout"); - HUD_Write_PanelCvar_q("_timeout_effect"); - break; - case HUD_PANEL_AMMO: - HUD_Write_PanelCvar_q("_onlycurrent"); - HUD_Write_PanelCvar_q("_iconalign"); - HUD_Write_PanelCvar_q("_progressbar"); - HUD_Write_PanelCvar_q("_progressbar_name"); - HUD_Write_PanelCvar_q("_progressbar_xoffset"); - HUD_Write_PanelCvar_q("_text"); - break; - case HUD_PANEL_POWERUPS: - HUD_Write_PanelCvar_q("_flip"); - HUD_Write_PanelCvar_q("_iconalign"); - HUD_Write_PanelCvar_q("_baralign"); - HUD_Write_PanelCvar_q("_progressbar"); - HUD_Write_PanelCvar_q("_progressbar_strength"); - HUD_Write_PanelCvar_q("_progressbar_shield"); - break; - case HUD_PANEL_HEALTHARMOR: - HUD_Write_PanelCvar_q("_flip"); - HUD_Write_PanelCvar_q("_iconalign"); - HUD_Write_PanelCvar_q("_baralign"); - HUD_Write_PanelCvar_q("_progressbar"); - HUD_Write_PanelCvar_q("_progressbar_health"); - HUD_Write_PanelCvar_q("_progressbar_armor"); - HUD_Write_PanelCvar_q("_text"); - break; - case HUD_PANEL_NOTIFY: - HUD_Write_PanelCvar_q("_flip"); - HUD_Write_PanelCvar_q("_print"); - break; - case HUD_PANEL_RADAR: - HUD_Write_PanelCvar_q("_foreground_alpha"); - break; - case HUD_PANEL_VOTE: - HUD_Write_PanelCvar_q("_alreadyvoted_alpha"); - break; - case HUD_PANEL_PRESSEDKEYS: - HUD_Write_PanelCvar_q("_aspect"); - break; - case HUD_PANEL_INFOMESSAGES: - HUD_Write_PanelCvar_q("_flip"); - break; - } - HUD_Write("\n"); - } - HUD_Write("menu_sync\n"); // force the menu to reread the cvars, so that the dialogs are updated - - print("^2Successfully exported to ", filename, "! (Note: It's saved in data/data/)\n"); - fclose(fh); - } - else - print("^1Couldn't write to ", filename, "\n"); -} - -const float hlBorderSize = 4; -const string hlBorder = "gfx/hud/default/border_highlighted"; -const string hlBorder2 = "gfx/hud/default/border_highlighted2"; -void HUD_Panel_HlBorder(float myBorder, vector color, float alpha) -{ - drawfill(panel_pos - '1 1 0' * myBorder, panel_size + '2 2 0' * myBorder, '0 0.5 1', .5 * alpha, DRAWFLAG_NORMAL); - drawpic_tiled(panel_pos - '1 1 0' * myBorder, hlBorder, '8 1 0' * hlBorderSize, eX * (panel_size_x + 2 * myBorder) + eY * hlBorderSize, color, alpha, DRAWFLAG_NORMAL); - drawpic_tiled(panel_pos - '1 1 0' * myBorder + eY * (panel_size_y + 2 * myBorder - hlBorderSize), hlBorder, '8 1 0' * hlBorderSize, eX * (panel_size_x + 2 * myBorder) + eY * hlBorderSize, color, alpha, DRAWFLAG_NORMAL); - drawpic_tiled(panel_pos - '1 1 0' * myBorder + eY * hlBorderSize, hlBorder2, '1 8 0' * hlBorderSize, eY * (panel_size_y + 2 * myBorder - 2 * hlBorderSize) + eX * hlBorderSize, color, alpha, DRAWFLAG_NORMAL); - drawpic_tiled(panel_pos - '1 1 0' * myBorder + eY * hlBorderSize + eX * (panel_size_x + 2 * myBorder - hlBorderSize), hlBorder2, '1 8 0' * hlBorderSize, eY * (panel_size_y + 2 * myBorder - 2 * hlBorderSize) + eX * hlBorderSize, color, alpha, DRAWFLAG_NORMAL); -} - // draw the background/borders -#define HUD_Panel_DrawBg(alpha)\ +#define HUD_Panel_DrawBg(theAlpha)\ if(panel_bg != "0")\ - draw_BorderPicture(panel_pos - '1 1 0' * panel_bg_border, panel_bg, panel_size + '1 1 0' * 2 * panel_bg_border, panel_bg_color, panel_bg_alpha * alpha, '1 1 0' * (panel_bg_border/BORDER_MULTIPLIER));\ -if(highlightedPanel_prev == active_panel && autocvar__hud_configure)\ -{\ - HUD_Panel_HlBorder(panel_bg_border + 1.5 * hlBorderSize, '0 0.5 1', 0.25 * (1 - autocvar__menu_alpha) * alpha);\ -} ENDS_WITH_CURLY_BRACE + draw_BorderPicture(panel_pos - '1 1 0' * panel_bg_border, panel_bg, panel_size + '1 1 0' * 2 * panel_bg_border, panel_bg_color, panel_bg_alpha * theAlpha, '1 1 0' * (panel_bg_border/BORDER_MULTIPLIER)) -void HUD_Panel_DrawProgressBar(vector pos, vector mySize, string pic, float vertical, float barflip, float x, vector color, float alpha, float drawflag) +//basically the same code of draw_ButtonPicture and draw_VertButtonPicture for the menu +void HUD_Panel_DrawProgressBar(vector theOrigin, vector theSize, string pic, float length_ratio, float vertical, float baralign, vector theColor, float theAlpha, float drawflag) { - if(!alpha || x == 0) + if(!length_ratio || !theAlpha) + return; + if(length_ratio > 1) + length_ratio = 1; + if (baralign == 3) + { + if(length_ratio < -1) + length_ratio = -1; + } + else if(length_ratio < 0) return; - x = bound(0, x, 1); - + vector square; + vector width, height; if(vertical) { pic = strcat(hud_skin_path, "/", pic, "_vertical"); if(precache_pic(pic) == "") { - pic = "gfx/hud/default/statusbar_vertical"; - } - - if(barflip) - drawsetcliparea(pos_x, pos_y + mySize_y * (1 - x), mySize_x, mySize_y * x); - else - drawsetcliparea(pos_x, pos_y, mySize_x, mySize_y * x); - } else { - pic = strcat(hud_skin_path, "/", pic); - if(precache_pic(pic) == "") { - pic = "gfx/hud/default/statusbar"; + pic = "gfx/hud/default/progressbar_vertical"; } - if(barflip) - drawsetcliparea(pos_x + mySize_x * (1 - x), pos_y, mySize_x * x, mySize_y); - else - drawsetcliparea(pos_x, pos_y, mySize_x * x, mySize_y); - } - - drawpic(pos, pic, mySize, color, alpha, drawflag); - drawresetcliparea(); -} - -void HUD_Panel_DrawHighlight(vector pos, vector mySize, vector color, float alpha, float drawflag) -{ - if(!alpha) - return; - - string pic; - pic = strcat(hud_skin_path, "/num_leading"); - if(precache_pic(pic) == "") { - pic = "gfx/hud/default/num_leading"; - } - - drawsubpic(pos, eX * min(mySize_x * 0.5, mySize_y) + eY * mySize_y, pic, '0 0 0', '0.25 1 0', color, alpha, drawflag); - if(mySize_x/mySize_y > 2) - drawsubpic(pos + eX * mySize_y, eX * (mySize_x - 2 * mySize_y) + eY * mySize_y, pic, '0.25 0 0', '0.5 1 0', color, alpha, drawflag); - drawsubpic(pos + eX * mySize_x - eX * min(mySize_x * 0.5, mySize_y), eX * min(mySize_x * 0.5, mySize_y) + eY * mySize_y, pic, '0.75 0 0', '0.25 1 0', color, alpha, drawflag); -} - -// check if move will result in panel being moved into another panel. If so, return snapped vector, otherwise return the given vector -vector HUD_Panel_CheckMove(vector myPos, vector mySize) -{ - float i; - - vector myTarget; - myTarget = myPos; - - vector myCenter; - vector targCenter; - myCenter = '0 0 0'; // shut up fteqcc, there IS a reference - targCenter = '0 0 0'; // shut up fteqcc, there IS a reference - - for (i = 0; i < HUD_PANEL_NUM; ++i) { - if(i == highlightedPanel || !panel_enabled) - continue; - - HUD_Panel_UpdatePosSizeForId(i); - - panel_pos -= '1 1 0' * panel_bg_border; - panel_size += '2 2 0' * panel_bg_border; - - if(myPos_y + mySize_y < panel_pos_y) - continue; - if(myPos_y > panel_pos_y + panel_size_y) - continue; - - if(myPos_x + mySize_x < panel_pos_x) - continue; - if(myPos_x > panel_pos_x + panel_size_x) - continue; - - // OK, there IS a collision. - - myCenter_x = myPos_x + 0.5 * mySize_x; - myCenter_y = myPos_y + 0.5 * mySize_y; - - targCenter_x = panel_pos_x + 0.5 * panel_size_x; - targCenter_y = panel_pos_y + 0.5 * panel_size_y; - - if(myCenter_x < targCenter_x && myCenter_y < targCenter_y) // top left (of the target panel) - { - if(myPos_x + mySize_x - panel_pos_x < myPos_y + mySize_y - panel_pos_y) // push it to the side - myTarget_x = panel_pos_x - mySize_x; - else // push it upwards - myTarget_y = panel_pos_y - mySize_y; - } - else if(myCenter_x > targCenter_x && myCenter_y < targCenter_y) // top right - { - if(panel_pos_x + panel_size_x - myPos_x < myPos_y + mySize_y - panel_pos_y) // push it to the side - myTarget_x = panel_pos_x + panel_size_x; - else // push it upwards - myTarget_y = panel_pos_y - mySize_y; - } - else if(myCenter_x < targCenter_x && myCenter_y > targCenter_y) // bottom left - { - if(myPos_x + mySize_x - panel_pos_x < panel_pos_y + panel_size_y - myPos_y) // push it to the side - myTarget_x = panel_pos_x - mySize_x; - else // push it downwards - myTarget_y = panel_pos_y + panel_size_y; - } - else if(myCenter_x > targCenter_x && myCenter_y > targCenter_y) // bottom right - { - if(panel_pos_x + panel_size_x - myPos_x < panel_pos_y + panel_size_y - myPos_y) // push it to the side - myTarget_x = panel_pos_x + panel_size_x; - else // push it downwards - myTarget_y = panel_pos_y + panel_size_y; - } - //if(cvar("hud_configure_checkcollisions_debug")) - //drawfill(panel_pos, panel_size, '1 1 0', .3, DRAWFLAG_NORMAL); - } - - return myTarget; -} - -void HUD_Panel_SetPos(vector pos) -{ - HUD_Panel_UpdatePosSizeForId(highlightedPanel); - vector mySize; - mySize = panel_size; - - //if(cvar("hud_configure_checkcollisions_debug")) - //drawfill(pos, mySize, '1 1 1', .2, DRAWFLAG_NORMAL); - - if(autocvar_hud_configure_grid) - { - pos_x = floor((pos_x/vid_conwidth)/bound(0.005, autocvar_hud_configure_grid_xsize, 0.2) + 0.5) * bound(0.005, autocvar_hud_configure_grid_xsize, 0.2) * vid_conwidth; - pos_y = floor((pos_y/vid_conheight)/bound(0.005, autocvar_hud_configure_grid_ysize, 0.2) + 0.5) * bound(0.005, autocvar_hud_configure_grid_ysize, 0.2) * vid_conheight; - } - - if(hud_configure_checkcollisions) - pos = HUD_Panel_CheckMove(pos, mySize); - - pos_x = bound(0, pos_x, vid_conwidth - mySize_x); - pos_y = bound(0, pos_y, vid_conheight - mySize_y); - - string s; - s = strcat(ftos(pos_x/vid_conwidth), " ", ftos(pos_y/vid_conheight)); - - HUD_Panel_GetName(highlightedPanel); - cvar_set(strcat("hud_panel_", panel_name, "_pos"), s); -} - -// check if resize will result in panel being moved into another panel. If so, return snapped vector, otherwise return the given vector -vector HUD_Panel_CheckResize(vector mySize, vector resizeorigin) { - float i; - - vector targEndPos; - - float dist_x, dist_y; - float ratio; - ratio = mySize_x/mySize_y; - - for (i = 0; i < HUD_PANEL_NUM; ++i) { - if(i == highlightedPanel || !panel_enabled) - continue; - - HUD_Panel_UpdatePosSizeForId(i); - - panel_pos -= '1 1 0' * panel_bg_border; - panel_size += '2 2 0' * panel_bg_border; - - targEndPos = panel_pos + panel_size; - - // resizeorigin is WITHIN target panel, just abort any collision testing against that particular panel to produce expected behaviour! - if(resizeorigin_x > panel_pos_x && resizeorigin_x < targEndPos_x && resizeorigin_y > panel_pos_y && resizeorigin_y < targEndPos_y) - continue; - - if (resizeCorner == 1) + if (baralign == 1) // bottom align + theOrigin_y += (1 - length_ratio) * theSize_y; + else if (baralign == 2) // center align + theOrigin_y += 0.5 * (1 - length_ratio) * theSize_y; + else if (baralign == 3) // center align, positive values down, negative up { - // check if this panel is on our way - if (resizeorigin_x <= panel_pos_x) - continue; - if (resizeorigin_y <= panel_pos_y) - continue; - if (targEndPos_x <= resizeorigin_x - mySize_x) - continue; - if (targEndPos_y <= resizeorigin_y - mySize_y) - continue; - - // there is a collision: - // detect which side of the panel we are facing is actually limiting the resizing - // (which side the resize direction finds for first) and reduce the size up to there - // - // dist is the distance between resizeorigin and the "analogous" point of the panel - // in this case resizeorigin (bottom-right point) and the bottom-right point of the panel - dist_x = resizeorigin_x - targEndPos_x; - dist_y = resizeorigin_y - targEndPos_y; - if (dist_y <= 0 || dist_x / dist_y > ratio) - mySize_x = min(mySize_x, dist_x); + theSize_y *= 0.5; + if (length_ratio > 0) + theOrigin_y += theSize_y; else - mySize_y = min(mySize_y, dist_y); - } - else if (resizeCorner == 2) - { - if (resizeorigin_x >= targEndPos_x) - continue; - if (resizeorigin_y <= panel_pos_y) - continue; - if (panel_pos_x >= resizeorigin_x + mySize_x) - continue; - if (targEndPos_y <= resizeorigin_y - mySize_y) - continue; - - dist_x = panel_pos_x - resizeorigin_x; - dist_y = resizeorigin_y - targEndPos_y; - if (dist_y <= 0 || dist_x / dist_y > ratio) - mySize_x = min(mySize_x, dist_x); - else - mySize_y = min(mySize_y, dist_y); - } - else if (resizeCorner == 3) - { - if (resizeorigin_x <= panel_pos_x) - continue; - if (resizeorigin_y >= targEndPos_y) - continue; - if (targEndPos_x <= resizeorigin_x - mySize_x) - continue; - if (panel_pos_y >= resizeorigin_y + mySize_y) - continue; - - dist_x = resizeorigin_x - targEndPos_x; - dist_y = panel_pos_y - resizeorigin_y; - if (dist_y <= 0 || dist_x / dist_y > ratio) - mySize_x = min(mySize_x, dist_x); - else - mySize_y = min(mySize_y, dist_y); - } - else if (resizeCorner == 4) - { - if (resizeorigin_x >= targEndPos_x) - continue; - if (resizeorigin_y >= targEndPos_y) - continue; - if (panel_pos_x >= resizeorigin_x + mySize_x) - continue; - if (panel_pos_y >= resizeorigin_y + mySize_y) - continue; - - dist_x = panel_pos_x - resizeorigin_x; - dist_y = panel_pos_y - resizeorigin_y; - if (dist_y <= 0 || dist_x / dist_y > ratio) - mySize_x = min(mySize_x, dist_x); - else - mySize_y = min(mySize_y, dist_y); + { + theOrigin_y += (1 + length_ratio) * theSize_y; + length_ratio = -length_ratio; + } } - //if(cvar("hud_configure_checkcollisions_debug")) - //drawfill(panel_pos, panel_size, '1 1 0', .3, DRAWFLAG_NORMAL); - } - - return mySize; -} - -void HUD_Panel_SetPosSize(vector mySize) -{ - HUD_Panel_UpdatePosSizeForId(highlightedPanel); - vector resizeorigin; - resizeorigin = panel_click_resizeorigin; - vector myPos; - - // minimum panel size cap - mySize_x = max(0.025 * vid_conwidth, mySize_x); - mySize_y = max(0.025 * vid_conheight, mySize_y); - - if(highlightedPanel == HUD_PANEL_CHAT) // some panels have their own restrictions, like the chat panel (which actually only moves the engine chat print around). Looks bad if it's too small. - { - mySize_x = max(17 * autocvar_con_chatsize, mySize_x); - mySize_y = max(2 * autocvar_con_chatsize + 2 * panel_bg_padding, mySize_y); - } - - // collision testing| - // -----------------+ - - // we need to know pos at this stage, but it might still change later if we hit a screen edge/other panel (?) - if(resizeCorner == 1) { - myPos_x = resizeorigin_x - mySize_x; - myPos_y = resizeorigin_y - mySize_y; - } else if(resizeCorner == 2) { - myPos_x = resizeorigin_x; - myPos_y = resizeorigin_y - mySize_y; - } else if(resizeCorner == 3) { - myPos_x = resizeorigin_x - mySize_x; - myPos_y = resizeorigin_y; - } else { // resizeCorner == 4 - myPos_x = resizeorigin_x; - myPos_y = resizeorigin_y; - } - - // left/top screen edges - if(myPos_x < 0) - mySize_x = mySize_x + myPos_x; - if(myPos_y < 0) - mySize_y = mySize_y + myPos_y; - - // bottom/right screen edges - if(myPos_x + mySize_x > vid_conwidth) - mySize_x = vid_conwidth - myPos_x; - if(myPos_y + mySize_y > vid_conheight) - mySize_y = vid_conheight - myPos_y; - - //if(cvar("hud_configure_checkcollisions_debug")) - //drawfill(myPos, mySize, '1 1 1', .2, DRAWFLAG_NORMAL); - - // before checkresize, otherwise panel can be snapped partially inside another panel or panel aspect ratio can be broken - if(autocvar_hud_configure_grid) - { - mySize_x = floor((mySize_x/vid_conwidth)/bound(0.005, autocvar_hud_configure_grid_xsize, 0.2) + 0.5) * bound(0.005, autocvar_hud_configure_grid_xsize, 0.2) * vid_conwidth; - mySize_y = floor((mySize_y/vid_conheight)/bound(0.005, autocvar_hud_configure_grid_ysize, 0.2) + 0.5) * bound(0.005, autocvar_hud_configure_grid_ysize, 0.2) * vid_conheight; - } - - if(hud_configure_checkcollisions) - mySize = HUD_Panel_CheckResize(mySize, resizeorigin); - - // minimum panel size cap, do this once more so we NEVER EVER EVER have a panel smaller than this, JUST IN CASE above code still makes the panel eg negative (impossible to resize back without changing cvars manually then) - mySize_x = max(0.025 * vid_conwidth, mySize_x); - mySize_y = max(0.025 * vid_conheight, mySize_y); - - // do another pos check, as size might have changed by now - if(resizeCorner == 1) { - myPos_x = resizeorigin_x - mySize_x; - myPos_y = resizeorigin_y - mySize_y; - } else if(resizeCorner == 2) { - myPos_x = resizeorigin_x; - myPos_y = resizeorigin_y - mySize_y; - } else if(resizeCorner == 3) { - myPos_x = resizeorigin_x - mySize_x; - myPos_y = resizeorigin_y; - } else { // resizeCorner == 4 - myPos_x = resizeorigin_x; - myPos_y = resizeorigin_y; - } - - //if(cvar("hud_configure_checkcollisions_debug")) - //drawfill(myPos, mySize, '0 1 0', .3, DRAWFLAG_NORMAL); - - HUD_Panel_GetName(highlightedPanel); - string s; - s = strcat(ftos(mySize_x/vid_conwidth), " ", ftos(mySize_y/vid_conheight)); - cvar_set(strcat("hud_panel_", panel_name, "_size"), s); - - s = strcat(ftos(myPos_x/vid_conwidth), " ", ftos(myPos_y/vid_conheight)); - cvar_set(strcat("hud_panel_", panel_name, "_pos"), s); -} - -float mouseClicked; -float prevMouseClicked; // previous state -float prevMouseClickedTime; // time during previous mouse click, to check for doubleclicks -vector prevMouseClickedPos; // pos during previous mouse click, to check for doubleclicks + theSize_y *= length_ratio; -float pressed_key_time; -void HUD_Panel_Arrow_Action(float nPrimary) -{ - if (highlightedPanel_prev == -1 || mouseClicked) - return; - - hud_configure_checkcollisions = (!(hudShiftState & S_CTRL) && autocvar_hud_configure_checkcollisions); - - float step; - if(autocvar_hud_configure_grid) - { - if (nPrimary == K_UPARROW || nPrimary == K_DOWNARROW) + vector bH; + width = eX * theSize_x; + height = eY * theSize_y; + if(theSize_y <= theSize_x * 2) { - if (hudShiftState & S_SHIFT) - step = bound(0.005, autocvar_hud_configure_grid_ysize, 0.2) * vid_conheight; - else - step = 2 * bound(0.005, autocvar_hud_configure_grid_ysize, 0.2) * vid_conheight; + // button not high enough + // draw just upper and lower part then + square = eY * theSize_y * 0.5; + bH = eY * (0.25 * theSize_y / (theSize_x * 2)); + drawsubpic(theOrigin, square + width, pic, '0 0 0', eX + bH, theColor, theAlpha, drawflag); + drawsubpic(theOrigin + square, square + width, pic, eY - bH, eX + bH, theColor, theAlpha, drawflag); } else { - if (hudShiftState & S_SHIFT) - step = bound(0.005, autocvar_hud_configure_grid_xsize, 0.2) * vid_conwidth; - else - step = 2 * bound(0.005, autocvar_hud_configure_grid_xsize, 0.2) * vid_conwidth; + square = eY * theSize_x; + drawsubpic(theOrigin, width + square, pic, '0 0 0', '1 0.25 0', theColor, theAlpha, drawflag); + drawsubpic(theOrigin + square, theSize - 2 * square, pic, '0 0.25 0', '1 0.5 0', theColor, theAlpha, drawflag); + drawsubpic(theOrigin + height - square, width + square, pic, '0 0.75 0', '1 0.25 0', theColor, theAlpha, drawflag); } - } - else - { - if (nPrimary == K_UPARROW || nPrimary == K_DOWNARROW) - step = vid_conheight; - else - step = vid_conwidth; - if (hudShiftState & S_SHIFT) - step = (step / 256); // more precision - else - step = (step / 64) * (1 + 2 * (time - pressed_key_time)); - } - - highlightedPanel = highlightedPanel_prev; - - HUD_Panel_UpdatePosSizeForId(highlightedPanel); - - vector prev_pos, prev_size; - prev_pos = panel_pos; - prev_size = panel_size; - - if (hudShiftState & S_ALT) // resize - { - highlightedAction = 1; - if(nPrimary == K_UPARROW) - resizeCorner = 1; - else if(nPrimary == K_RIGHTARROW) - resizeCorner = 2; - else if(nPrimary == K_LEFTARROW) - resizeCorner = 3; - else // if(nPrimary == K_DOWNARROW) - resizeCorner = 4; - - // ctrl+arrow reduces the size, instead of increasing it - // Note that ctrl disables collisions check too, but it's fine - // since we don't collide with anything reducing the size - if (hudShiftState & S_CTRL) { - step = -step; - resizeCorner = 5 - resizeCorner; - } - - vector mySize; - mySize = panel_size; - panel_click_resizeorigin = panel_pos; - if(resizeCorner == 1) { - panel_click_resizeorigin += mySize; - mySize_y += step; - } else if(resizeCorner == 2) { - panel_click_resizeorigin_y += mySize_y; - mySize_x += step; - } else if(resizeCorner == 3) { - panel_click_resizeorigin_x += mySize_x; - mySize_x += step; - } else { // resizeCorner == 4 - mySize_y += step; - } - HUD_Panel_SetPosSize(mySize); - } - else // move - { - highlightedAction = 2; - vector pos; - pos = panel_pos; - if(nPrimary == K_UPARROW) - pos_y -= step; - else if(nPrimary == K_DOWNARROW) - pos_y += step; - else if(nPrimary == K_LEFTARROW) - pos_x -= step; - else // if(nPrimary == K_RIGHTARROW) - pos_x += step; - - HUD_Panel_SetPos(pos); - } - - HUD_Panel_UpdatePosSizeForId(highlightedPanel); - - if (prev_pos != panel_pos || prev_size != panel_size) - { - // backup! - panel_pos_backup = prev_pos; - panel_size_backup = prev_size; - highlightedPanel_backup = highlightedPanel; - } -} - -float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary) -{ - string s; - - if(!autocvar__hud_configure) - return false; - - // allow console bind to work - string con_keys; - float keys; - con_keys = findkeysforcommand("toggleconsole"); - keys = tokenize(con_keys); - - float hit_con_bind, i; - for (i = 0; i < keys; ++i) - { - if(nPrimary == stof(argv(i))) - hit_con_bind = 1; - } - - if(bInputType == 0) { - if(nPrimary == K_ALT) hudShiftState |= S_ALT; - if(nPrimary == K_CTRL) hudShiftState |= S_CTRL; - if(nPrimary == K_SHIFT) hudShiftState |= S_SHIFT; - } - else if(bInputType == 1) { - if(nPrimary == K_ALT) hudShiftState -= (hudShiftState & S_ALT); - if(nPrimary == K_CTRL) hudShiftState -= (hudShiftState & S_CTRL); - if(nPrimary == K_SHIFT) hudShiftState -= (hudShiftState & S_SHIFT); - } - - if(nPrimary == K_MOUSE1) - { - if(bInputType == 0) { // key pressed - mouseClicked = 1; - return true; - } - else if(bInputType == 1) {// key released - mouseClicked = 0; - return true; + } else { + pic = strcat(hud_skin_path, "/", pic); + if(precache_pic(pic) == "") { + pic = "gfx/hud/default/progressbar"; } - } - else if(nPrimary == K_ESCAPE) - { - if (bInputType == 1) - return true; - menu_enabled = 1; - menu_enabled_time = time; - localcmd("menu_showhudexit\n"); - } - else if(hudShiftState & S_CTRL) - { - if (mouseClicked) - return true; - if(nPrimary == K_SPACE) // enable/disable highlighted panel or dock + if (baralign == 1) // right align + theOrigin_x += (1 - length_ratio) * theSize_x; + else if (baralign == 2) // center align + theOrigin_x += 0.5 * (1 - length_ratio) * theSize_x; + else if (baralign == 3) // center align, positive values on the right, negative on the left { - if (bInputType == 1) - return true; - - if (highlightedPanel_prev != -1) - cvar_set(strcat("hud_panel_", panel_name), ftos(!(panel_enabled))); + theSize_x *= 0.5; + if (length_ratio > 0) + theOrigin_x += theSize_x; else - cvar_set(strcat("hud_dock"), (autocvar_hud_dock == "") ? "dock" : ""); - } - if(nPrimary == 'c') // copy highlighted panel size - { - if (bInputType == 1) - return true; - - if (highlightedPanel_prev != -1) - { - panel_size_copied = panel_size; - highlightedPanel_copied = highlightedPanel_prev; - } - } - else if(nPrimary == 'v') // past copied size on the highlighted panel - { - if (bInputType == 1) - return true; - - if (highlightedPanel_copied == -1 || highlightedPanel_prev == -1) - return true; - - HUD_Panel_UpdatePosSizeForId(highlightedPanel_prev); - - // reduce size if it'd go beyond screen boundaries - vector tmp_size = panel_size_copied; - if (panel_pos_x + panel_size_copied_x > vid_conwidth) - tmp_size_x = vid_conwidth - panel_pos_x; - if (panel_pos_y + panel_size_copied_y > vid_conheight) - tmp_size_y = vid_conheight - panel_pos_y; - - if (panel_size == tmp_size) - return true; - - // backup first! - panel_pos_backup = panel_pos; - panel_size_backup = panel_size; - highlightedPanel_backup = highlightedPanel_prev; - - s = strcat(ftos(tmp_size_x/vid_conwidth), " ", ftos(tmp_size_y/vid_conheight)); - cvar_set(strcat("hud_panel_", panel_name, "_size"), s); - } - else if(nPrimary == 'z') // undo last action - { - if (bInputType == 1) - return true; - //restore previous values - if (highlightedPanel_backup != -1) { - HUD_Panel_GetName(highlightedPanel_backup); - s = strcat(ftos(panel_pos_backup_x/vid_conwidth), " ", ftos(panel_pos_backup_y/vid_conheight)); - cvar_set(strcat("hud_panel_", panel_name, "_pos"), s); - s = strcat(ftos(panel_size_backup_x/vid_conwidth), " ", ftos(panel_size_backup_y/vid_conheight)); - cvar_set(strcat("hud_panel_", panel_name, "_size"), s); - highlightedPanel_backup = -1; + theOrigin_x += (1 + length_ratio) * theSize_x; + length_ratio = -length_ratio; } } - } - else if(nPrimary == K_UPARROW || nPrimary == K_DOWNARROW || nPrimary == K_LEFTARROW || nPrimary == K_RIGHTARROW) - { - if (bInputType == 1) - { - pressed_key_time = 0; - return true; - } - else if (pressed_key_time == 0) - pressed_key_time = time; - - HUD_Panel_Arrow_Action(nPrimary); //move or resize panel - } - else if(hit_con_bind) - return false; - - return true; // Suppress ALL other input -} - -float HUD_Panel_HighlightCheck() -{ - float i, j, border; - vector panelPos; - vector panelSize; + theSize_x *= length_ratio; - while(j <= HUD_PANEL_NUM) - { - i = panel_order[j]; - j += 1; - - HUD_Panel_UpdatePosSizeForId(i); - - panelPos = panel_pos; - panelSize = panel_size; - border = max(8, panel_bg_border); // FORCED border so a small border size doesn't mean you can't resize - - // move - if(mousepos_x >= panelPos_x && mousepos_y >= panelPos_y && mousepos_x <= panelPos_x + panelSize_x && mousepos_y <= panelPos_y + panelSize_y) - { - return 1; - } - // resize from topleft border - else if(mousepos_x >= panelPos_x - border && mousepos_y >= panelPos_y - border && mousepos_x <= panelPos_x + 0.5 * panelSize_x && mousepos_y <= panelPos_y + 0.5 * panelSize_y) - { - return 2; - } - // resize from topright border - else if(mousepos_x >= panelPos_x + 0.5 * panelSize_x && mousepos_y >= panelPos_y - border && mousepos_x <= panelPos_x + panelSize_x + border && mousepos_y <= panelPos_y + 0.5 * panelSize_y) - { - return 3; - } - // resize from bottomleft border - else if(mousepos_x >= panelPos_x - border && mousepos_y >= panelPos_y + 0.5 * panelSize_y && mousepos_x <= panelPos_x + 0.5 * panelSize_x && mousepos_y <= panelPos_y + panelSize_y + border) - { - return 3; - } - // resize from bottomright border - else if(mousepos_x >= panelPos_x + 0.5 * panelSize_x && mousepos_y >= panelPos_y + 0.5 * panelSize_y && mousepos_x <= panelPos_x + panelSize_x + border && mousepos_y <= panelPos_y + panelSize_y + border) - { - return 2; - } - } - return 0; -} - -// move a panel to the beginning of the panel order array (which means it gets drawn last, on top of everything else) -void HUD_Panel_FirstInDrawQ(float id) -{ - float i; - var float place = -1; - // find out where in the array our current id is, save into place - for(i = 0; i < HUD_PANEL_NUM; ++i) - { - if(panel_order[i] == id) - { - place = i; - break; - } - } - // place last if we didn't find a place for it yet (probably new panel, or screwed up cvar) - if(place == -1) - place = HUD_PANEL_NUM - 1; - - // move all ids up by one step in the array until "place" - for(i = place; i > 0; --i) - { - panel_order[i] = panel_order[i-1]; - } - // now save the new top id - panel_order[0] = id; - - // let's save them into the cvar by some strcat trickery - string s; - for(i = 0; i < HUD_PANEL_NUM; ++i) - { - s = strcat(s, ftos(panel_order[i]), " "); - } - cvar_set("_hud_panelorder", s); - if(hud_panelorder_prev) - strunzone(hud_panelorder_prev); - hud_panelorder_prev = strzone(autocvar__hud_panelorder); // prevent HUD_Main from doing useless update, we already updated here -} - -void HUD_Panel_Highlight() -{ - float i, j, border; - vector panelPos; - vector panelSize; - - while(j <= HUD_PANEL_NUM) - { - i = panel_order[j]; - j += 1; - - HUD_Panel_UpdatePosSizeForId(i); - - panelPos = panel_pos; - panelSize = panel_size; - border = max(8, panel_bg_border); // FORCED border so a small border size doesn't mean you can't resize - - // move - if(mousepos_x >= panelPos_x && mousepos_y >= panelPos_y && mousepos_x <= panelPos_x + panelSize_x && mousepos_y <= panelPos_y + panelSize_y) - { - highlightedPanel = i; - HUD_Panel_FirstInDrawQ(i); - highlightedAction = 1; - panel_click_distance = mousepos - panelPos; - return; - } - // resize from topleft border - else if(mousepos_x >= panelPos_x - border && mousepos_y >= panelPos_y - border && mousepos_x <= panelPos_x + 0.5 * panelSize_x && mousepos_y <= panelPos_y + 0.5 * panelSize_y) - { - highlightedPanel = i; - HUD_Panel_FirstInDrawQ(i); - highlightedAction = 2; - resizeCorner = 1; - panel_click_distance = mousepos - panelPos; - panel_click_resizeorigin = panelPos + panelSize; - return; - } - // resize from topright border - else if(mousepos_x >= panelPos_x + 0.5 * panelSize_x && mousepos_y >= panelPos_y - border && mousepos_x <= panelPos_x + panelSize_x + border && mousepos_y <= panelPos_y + 0.5 * panelSize_y) + vector bW; + width = eX * theSize_x; + height = eY * theSize_y; + if(theSize_x <= theSize_y * 2) { - highlightedPanel = i; - HUD_Panel_FirstInDrawQ(i); - highlightedAction = 2; - resizeCorner = 2; - panel_click_distance_x = panelSize_x - mousepos_x + panelPos_x; - panel_click_distance_y = mousepos_y - panelPos_y; - panel_click_resizeorigin = panelPos + eY * panelSize_y; - return; - } - // resize from bottomleft border - else if(mousepos_x >= panelPos_x - border && mousepos_y >= panelPos_y + 0.5 * panelSize_y && mousepos_x <= panelPos_x + 0.5 * panelSize_x && mousepos_y <= panelPos_y + panelSize_y + border) - { - highlightedPanel = i; - HUD_Panel_FirstInDrawQ(i); - highlightedAction = 2; - resizeCorner = 3; - panel_click_distance_x = mousepos_x - panelPos_x; - panel_click_distance_y = panelSize_y - mousepos_y + panelPos_y; - panel_click_resizeorigin = panelPos + eX * panelSize_x; - return; - } - // resize from bottomright border - else if(mousepos_x >= panelPos_x + 0.5 * panelSize_x && mousepos_y >= panelPos_y + 0.5 * panelSize_y && mousepos_x <= panelPos_x + panelSize_x + border && mousepos_y <= panelPos_y + panelSize_y + border) - { - highlightedPanel = i; - HUD_Panel_FirstInDrawQ(i); - highlightedAction = 2; - resizeCorner = 4; - panel_click_distance = panelSize - mousepos + panelPos; - panel_click_resizeorigin = panelPos; - return; + // button not wide enough + // draw just left and right part then + square = eX * theSize_x * 0.5; + bW = eX * (0.25 * theSize_x / (theSize_y * 2)); + drawsubpic(theOrigin, square + height, pic, '0 0 0', eY + bW, theColor, theAlpha, drawflag); + drawsubpic(theOrigin + square, square + height, pic, eX - bW, eY + bW, theColor, theAlpha, drawflag); } else { - highlightedPanel_prev = -1; + square = eX * theSize_y; + drawsubpic(theOrigin, height + square, pic, '0 0 0', '0.25 1 0', theColor, theAlpha, drawflag); + drawsubpic(theOrigin + square, theSize - 2 * square, pic, '0.25 0 0', '0.5 1 0', theColor, theAlpha, drawflag); + drawsubpic(theOrigin + width - square, height + square, pic, '0.75 0 0', '0.25 1 0', theColor, theAlpha, drawflag); } } } -float highlightcheck; -vector prev_pos, prev_size; -void HUD_Panel_Mouse() +void HUD_Panel_DrawHighlight(vector pos, vector mySize, vector color, float theAlpha, float drawflag) { - // TODO: needs better check... is there any float that contains the current state of the menu? _menu_alpha isn't apparently updated the frame the menu gets enabled - if (autocvar__menu_alpha == 0 && time - menu_enabled_time > 0.5) - menu_enabled = 0; - - /* - print("menu_enabled: ", ftos(menu_enabled), "\n"); - print("Highlighted: ", ftos(highlightedPanel), "\n"); - print("Menu alpha: ", ftos(autocvar__menu_alpha), "\n"); - */ - - // instantly hide the editor cursor if we open the HUDExit dialog - // as hud_fade_alpha doesn't decrease to 0 in this case - // TODO: find a way to fade the cursor out even in this case - if(menu_enabled == 1 || (menu_enabled == 2 && !hud_fade_alpha)) + if(!theAlpha) return; - if(mouseClicked == 0 && menu_enabled != 2 && highlightedPanel >= 0) { // don't reset these variables in menu_enabled mode 2! - highlightedPanel = -1; - highlightedAction = 0; - } - if(highlightedPanel != -1) - highlightedPanel_prev = highlightedPanel; - - mousepos = mousepos + getmousepos() * autocvar_menu_mouse_speed; - - mousepos_x = bound(0, mousepos_x, vid_conwidth); - mousepos_y = bound(0, mousepos_y, vid_conheight); - - if(mouseClicked) - { - if(prevMouseClicked == 0) - { - HUD_Panel_Highlight(); // sets highlightedPanel, highlightedAction, panel_click_distance, panel_click_resizeorigin - // and calls HUD_Panel_UpdatePosSizeForId() for the highlighted panel - prev_pos = panel_pos; - prev_size = panel_size; - } - else - HUD_Panel_UpdatePosSizeForId(highlightedPanel); - - if (prev_pos != panel_pos || prev_size != panel_size) - { - hud_configure_checkcollisions = (!(hudShiftState & S_CTRL) && autocvar_hud_configure_checkcollisions); - // backup! - panel_pos_backup = prev_pos; - panel_size_backup = prev_size; - highlightedPanel_backup = highlightedPanel; - } - else - // in case the clicked panel is inside another panel and we aren't - // moving it, avoid the immediate "fix" of its position/size - // (often unwanted and hateful) by disabling collisions check - hud_configure_checkcollisions = false; - - if(highlightedAction == 1) - HUD_Panel_SetPos(mousepos - panel_click_distance); - else if(highlightedAction == 2) - { - vector mySize; - if(resizeCorner == 1) { - mySize_x = panel_click_resizeorigin_x - (mousepos_x - panel_click_distance_x); - mySize_y = panel_click_resizeorigin_y - (mousepos_y - panel_click_distance_y); - } else if(resizeCorner == 2) { - mySize_x = mousepos_x + panel_click_distance_x - panel_click_resizeorigin_x; - mySize_y = panel_click_distance_y + panel_click_resizeorigin_y - mousepos_y; - } else if(resizeCorner == 3) { - mySize_x = panel_click_resizeorigin_x + panel_click_distance_x - mousepos_x; - mySize_y = mousepos_y + panel_click_distance_y - panel_click_resizeorigin_y; - } else { // resizeCorner == 4 - mySize_x = mousepos_x - (panel_click_resizeorigin_x - panel_click_distance_x); - mySize_y = mousepos_y - (panel_click_resizeorigin_y - panel_click_distance_y); - } - HUD_Panel_SetPosSize(mySize); - } - - // doubleclick check - if(time - prevMouseClickedTime < 0.4 && prevMouseClicked == 0 && prevMouseClickedPos == mousepos && highlightedPanel >= 0) - { - mouseClicked = 0; // to prevent spam, I guess. - menu_enabled = 2; - menu_enabled_time = time; - HUD_Panel_GetName(highlightedPanel); - localcmd("menu_showhudoptions ", panel_name, "\n"); - return; - } - if(prevMouseClicked == 0) - { - prevMouseClickedTime = time; - prevMouseClickedPos = mousepos; - } - } - else - { - highlightcheck = HUD_Panel_HighlightCheck(); + string pic; + pic = strcat(hud_skin_path, "/num_leading"); + if(precache_pic(pic) == "") { + pic = "gfx/hud/default/num_leading"; } - // draw cursor after performing move/resize to have the panel pos/size updated before highlightcheck - vector cursorsize; - cursorsize = '32 32 0'; - if(highlightcheck == 0) - drawpic(mousepos, strcat("gfx/menu/", autocvar_menu_skin, "/cursor.tga"), '32 32 0', '1 1 1', hud_fade_alpha, DRAWFLAG_NORMAL); - else if(highlightcheck == 1) - drawpic(mousepos - cursorsize * 0.5, strcat("gfx/menu/", autocvar_menu_skin, "/cursor_move.tga"), '32 32 0', '1 1 1', hud_fade_alpha, DRAWFLAG_NORMAL); - else if(highlightcheck == 2) - drawpic(mousepos - cursorsize * 0.5, strcat("gfx/menu/", autocvar_menu_skin, "/cursor_resize.tga"), '32 32 0', '1 1 1', hud_fade_alpha, DRAWFLAG_NORMAL); - else - drawpic(mousepos - cursorsize * 0.5, strcat("gfx/menu/", autocvar_menu_skin, "/cursor_resize2.tga"), '32 32 0', '1 1 1', hud_fade_alpha, DRAWFLAG_NORMAL); - - prevMouseClicked = mouseClicked; + drawsubpic(pos, eX * min(mySize_x * 0.5, mySize_y) + eY * mySize_y, pic, '0 0 0', '0.25 1 0', color, theAlpha, drawflag); + if(mySize_x/mySize_y > 2) + drawsubpic(pos + eX * mySize_y, eX * (mySize_x - 2 * mySize_y) + eY * mySize_y, pic, '0.25 0 0', '0.5 1 0', color, theAlpha, drawflag); + drawsubpic(pos + eX * mySize_x - eX * min(mySize_x * 0.5, mySize_y), eX * min(mySize_x * 0.5, mySize_y) + eY * mySize_y, pic, '0.75 0 0', '0.25 1 0', color, theAlpha, drawflag); } // Weapon icons (#0) // -float weaponspace[10]; -#define HUD_Weapons_Clear()\ - float idx;\ - for(idx = 0; idx < 10; ++idx)\ - weaponspace[idx] = 0 - entity weaponorder[WEP_MAXCOUNT]; void weaponorder_swap(float i, float j, entity pass) { @@ -1508,7 +419,7 @@ float GetAmmoTypeForWep(float i) case WEP_HLAC: return 3; case WEP_MINSTANEX: return 3; case WEP_NEX: return 3; - case WEP_CAMPINGRIFLE: return 1; + case WEP_RIFLE: return 1; case WEP_HAGAR: return 2; case WEP_ROCKET_LAUNCHER: return 2; case WEP_SEEKER: return 2; @@ -1520,109 +431,63 @@ float GetAmmoTypeForWep(float i) void HUD_Weapons(void) { - float f, screen_ar; - float center_x, center_y; + // declarations + float weapons_stat = getstati(STAT_WEAPONS); + float i, f, a, j, factor; + float screen_ar, center_x, center_y; + float weapon_count, weapon_id, weapon_alpha; + float row, column, rows, columns; + float aspect = autocvar_hud_panel_weapons_aspect; - if(!autocvar_hud_panel_weapons && !autocvar__hud_configure) - return; + float show_accuracy, panel_weapon_accuracy; float timeout = autocvar_hud_panel_weapons_timeout; - float timeout_effect_length, timein_effect_length; - if (autocvar_hud_panel_weapons_timeout_effect == 0) - { - timeout_effect_length = 0; - timein_effect_length = 0; - } - else - { - timeout_effect_length = 0.75; - timein_effect_length = 0.375; - } + float timein_effect_length = (autocvar_hud_panel_weapons_timeout_effect ? 0.375 : 0); + float timeout_effect_length = (autocvar_hud_panel_weapons_timeout_effect ? 0.75 : 0); - if (timeout && time >= weapontime + timeout + timeout_effect_length && !autocvar__hud_configure) - { - weaponprevtime = time; - return; - } + float ammo_type, ammo_full, ammo_alpha; + float barsize_x, barsize_y, baroffset_x, baroffset_y; - active_panel = HUD_PANEL_WEAPONS; - HUD_Panel_UpdateCvars(weapons); + float when = autocvar_hud_panel_weapons_complainbubble_time; + float fadetime = autocvar_hud_panel_weapons_complainbubble_fadetime; - if (timeout && time >= weapontime + timeout && !autocvar__hud_configure) - { - f = (time - (weapontime + timeout)) / timeout_effect_length; - if (autocvar_hud_panel_weapons_timeout_effect) - { - panel_bg_alpha *= (1 - f); - panel_fg_alpha *= (1 - f); - } - if (autocvar_hud_panel_weapons_timeout_effect == 1) - { - f *= f; // for a cooler movement - center_x = panel_pos_x + panel_size_x/2; - center_y = panel_pos_y + panel_size_y/2; - screen_ar = vid_conwidth/vid_conheight; - if (center_x/center_y < screen_ar) //bottom left - { - if ((vid_conwidth - center_x)/center_y < screen_ar) //bottom - panel_pos_y += f * (vid_conheight - panel_pos_y); - else //left - panel_pos_x -= f * (panel_pos_x + panel_size_x); - } - else //top right - { - if ((vid_conwidth - center_x)/center_y < screen_ar) //right - panel_pos_x += f * (vid_conwidth - panel_pos_x); - else //top - panel_pos_y -= f * (panel_pos_y + panel_size_y); - } - } - weaponprevtime = time - (1 - f) * timein_effect_length; - } - else if (timeout && time < weaponprevtime + timein_effect_length && !autocvar__hud_configure) + vector weapon_pos, weapon_size; + local noref vector old_panel_size; // fteqcc sucks + vector color, ammo_color; + + // check to see if we want to continue + if(hud != HUD_NORMAL) { return; } + + if(!autocvar__hud_configure) { - f = (time - weaponprevtime) / timein_effect_length; - if (autocvar_hud_panel_weapons_timeout_effect) - { - panel_bg_alpha *= (f); - panel_fg_alpha *= (f); - } - if (autocvar_hud_panel_weapons_timeout_effect == 1) + if((!autocvar_hud_panel_weapons) || (spectatee_status == -1)) + return; + else if(timeout && time >= weapontime + timeout + timeout_effect_length) { - f *= f; // for a cooler movement - f = 1 - f; - center_x = panel_pos_x + panel_size_x/2; - center_y = panel_pos_y + panel_size_y/2; - screen_ar = vid_conwidth/vid_conheight; - if (center_x/center_y < screen_ar) //bottom left - { - if ((vid_conwidth - center_x)/center_y < screen_ar) //bottom - panel_pos_y += f * (vid_conheight - panel_pos_y); - else //left - panel_pos_x -= f * (panel_pos_x + panel_size_x); - } - else //top right - { - if ((vid_conwidth - center_x)/center_y < screen_ar) //right - panel_pos_x += f * (vid_conwidth - panel_pos_x); - else //top - panel_pos_y -= f * (panel_pos_y + panel_size_y); - } + weaponprevtime = time; + return; } } + else + hud_configure_active_panel = HUD_PANEL_WEAPONS; + + // update generic hud functions + HUD_Panel_UpdateCvars(weapons); + HUD_Panel_ApplyFadeAlpha(); - float i, weapid, wpnalpha, weapon_cnt; - weapon_cnt = 0; - for(i = WEP_FIRST; i <= WEP_LAST; ++i) + // calculate fading effect to weapon images for when the panel is idle + if(autocvar_hud_panel_weapons_fade) { - self = get_weaponinfo(i); - if(self.impulse >= 0) - ++weapon_cnt; + weapon_alpha = 3.2 - 2 * (time - weapontime); + weapon_alpha = bound(0.7, weapon_alpha, 1) * panel_fg_alpha; } + else + weapon_alpha = panel_fg_alpha; - // TODO make this configurable - if(weaponorder_bypriority != autocvar_cl_weaponpriority) + // figure out weapon order (how the weapons are sorted) // TODO make this configurable + if(weaponorder_bypriority != autocvar_cl_weaponpriority || !weaponorder[0]) { + float weapon_cnt; if(weaponorder_bypriority) strunzone(weaponorder_bypriority); if(weaponorder_byimpulse) @@ -1632,21 +497,135 @@ void HUD_Weapons(void) weaponorder_byimpulse = strzone(W_FixWeaponOrder_BuildImpulseList(W_FixWeaponOrder_ForceComplete(W_NumberWeaponOrder(weaponorder_bypriority)))); weaponorder_cmp_str = strcat(" ", weaponorder_byimpulse, " "); - weapon_cnt = 0; - for(i = WEP_FIRST; i <= WEP_LAST; ++i) + weapon_cnt = 0; + for(i = WEP_FIRST; i <= WEP_LAST; ++i) + { + self = get_weaponinfo(i); + if(self.impulse >= 0) + { + weaponorder[weapon_cnt] = self; + ++weapon_cnt; + } + } + for(i = weapon_cnt; i < WEP_MAXCOUNT; ++i) + weaponorder[i] = world; + heapsort(weapon_cnt, weaponorder_swap, weaponorder_cmp, world); + + weaponorder_cmp_str = string_null; + } + + // determine which weapons are going to be shown + if (autocvar_hud_panel_weapons_onlyowned) + { + if(autocvar__hud_configure) + { + if (weapons_stat == 0) // create some fake weapons anyway + for(i = 0; i <= WEP_LAST-WEP_FIRST; i += floor((WEP_LAST-WEP_FIRST)/5)) + weapons_stat |= power2of(i); + + if(menu_enabled != 2) + HUD_Panel_DrawBg(1); // also draw the bg of the entire panel + } + + // do we own this weapon? + for(i = 0; i <= WEP_LAST-WEP_FIRST; ++i) + if(weapons_stat & weaponorder[i].weapons) + ++weapon_count; + + // add it anyway if weaponcomplain is shown + if((!autocvar__hud_configure) + && (autocvar_hud_panel_weapons_complainbubble + && time - complain_weapon_time < when + fadetime)) + ++weapon_count; + + // might as well commit suicide now, no reason to live ;) + if (weapon_count == 0) { return; } + + // reduce size of the panel + if (panel_size_y > panel_size_x) + { + old_panel_size_y = panel_size_y; + panel_size_y *= weapon_count / WEP_COUNT; + panel_pos_y += (old_panel_size_y - panel_size_y) / 2; + } + else + { + old_panel_size_x = panel_size_x; + panel_size_x *= weapon_count / WEP_COUNT; + panel_pos_x += (old_panel_size_x - panel_size_x) / 2; + } + } + else + weapon_count = WEP_COUNT; + + // animation for fading in/out the panel respectively when not in use + if(!autocvar__hud_configure) + { + if (timeout && time >= weapontime + timeout) // apply timeout effect if needed { - self = get_weaponinfo(i); - if(self.impulse >= 0) + f = (time - (weapontime + timeout)) / timeout_effect_length; + if (autocvar_hud_panel_weapons_timeout_effect == 1 || autocvar_hud_panel_weapons_timeout_effect == 3) { - weaponorder[weapon_cnt] = self; - ++weapon_cnt; + panel_bg_alpha *= (1 - f); + panel_fg_alpha *= (1 - f); + } + if (autocvar_hud_panel_weapons_timeout_effect == 2 || autocvar_hud_panel_weapons_timeout_effect == 3) + { + f *= f; // for a cooler movement + center_x = panel_pos_x + panel_size_x/2; + center_y = panel_pos_y + panel_size_y/2; + screen_ar = vid_conwidth/vid_conheight; + if (center_x/center_y < screen_ar) //bottom left + { + if ((vid_conwidth - center_x)/center_y < screen_ar) //bottom + panel_pos_y += f * (vid_conheight - panel_pos_y); + else //left + panel_pos_x -= f * (panel_pos_x + panel_size_x); + } + else //top right + { + if ((vid_conwidth - center_x)/center_y < screen_ar) //right + panel_pos_x += f * (vid_conwidth - panel_pos_x); + else //top + panel_pos_y -= f * (panel_pos_y + panel_size_y); + } + } + weaponprevtime = time - (1 - f) * timein_effect_length; + } + else if (timeout && time < weaponprevtime + timein_effect_length) // apply timein effect if needed + { + f = (time - weaponprevtime) / timein_effect_length; + if (autocvar_hud_panel_weapons_timeout_effect == 1 || autocvar_hud_panel_weapons_timeout_effect == 3) + { + panel_bg_alpha *= (f); + panel_fg_alpha *= (f); + } + if (autocvar_hud_panel_weapons_timeout_effect == 2 || autocvar_hud_panel_weapons_timeout_effect == 3) + { + f *= f; // for a cooler movement + f = 1 - f; + center_x = panel_pos_x + panel_size_x/2; + center_y = panel_pos_y + panel_size_y/2; + screen_ar = vid_conwidth/vid_conheight; + if (center_x/center_y < screen_ar) //bottom left + { + if ((vid_conwidth - center_x)/center_y < screen_ar) //bottom + panel_pos_y += f * (vid_conheight - panel_pos_y); + else //left + panel_pos_x -= f * (panel_pos_x + panel_size_x); + } + else //top right + { + if ((vid_conwidth - center_x)/center_y < screen_ar) //right + panel_pos_x += f * (vid_conwidth - panel_pos_x); + else //top + panel_pos_y -= f * (panel_pos_y + panel_size_y); + } } } - heapsort(weapon_cnt, weaponorder_swap, weaponorder_cmp, world); - - weaponorder_cmp_str = string_null; } + // draw the background, then change the virtual size of it to better fit other items inside HUD_Panel_DrawBg(1); if(panel_bg_padding) { @@ -1654,67 +633,32 @@ void HUD_Weapons(void) panel_size -= '2 2 0' * panel_bg_padding; } - if(autocvar_hud_panel_weapons_fade) - { - wpnalpha = 3.2 - 2 * (time - weapontime); - wpnalpha = bound(0.7, wpnalpha, 1) * panel_fg_alpha; - } - else - wpnalpha = panel_fg_alpha; - - HUD_Weapons_Clear(); - - float rows, columns; - float aspect = autocvar_hud_panel_weapons_aspect; + // after the sizing and animations are done, update the other values rows = panel_size_y/panel_size_x; - rows = bound(1, floor((sqrt(4 * aspect * rows * WEP_COUNT + rows * rows) + rows + 0.5) / 2), WEP_COUNT); - - columns = ceil(WEP_COUNT/rows); - float row, column; + rows = bound(1, floor((sqrt(4 * aspect * rows * weapon_count + rows * rows) + rows + 0.5) / 2), weapon_count); + columns = ceil(weapon_count/rows); + weapon_size = eX * panel_size_x*(1/columns) + eY * panel_size_y*(1/rows); - float a, type, fullammo; - float when; - when = autocvar_hud_panel_weapons_complainbubble_time; - float fadetime; - fadetime = autocvar_hud_panel_weapons_complainbubble_fadetime; - - vector color; - vector wpnpos; - vector wpnsize; - - float fullammo_shells, fullammo_nails, fullammo_rockets, fullammo_cells, fullammo_fuel; - vector ammo_color; - float ammo_alpha; - wpnsize = eX * panel_size_x*(1/columns) + eY * panel_size_y*(1/rows); - float barsize_x, barsize_y, baroffset_x, baroffset_y; - float show_ammo = autocvar_hud_panel_weapons_ammo; - if (show_ammo) - { - fullammo_shells = autocvar_hud_panel_weapons_ammo_full_shells; - fullammo_nails = autocvar_hud_panel_weapons_ammo_full_nails; - fullammo_rockets = autocvar_hud_panel_weapons_ammo_full_rockets; - fullammo_cells = autocvar_hud_panel_weapons_ammo_full_cells; - fullammo_fuel = autocvar_hud_panel_weapons_ammo_full_fuel; + // calculate position/size for visual bar displaying ammount of ammo status + if (autocvar_hud_panel_weapons_ammo) + { ammo_color = stov(autocvar_hud_panel_weapons_ammo_color); ammo_alpha = panel_fg_alpha * autocvar_hud_panel_weapons_ammo_alpha; - - if(wpnsize_x/wpnsize_y > aspect) + if(weapon_size_x/weapon_size_y > aspect) { - barsize_x = aspect * wpnsize_y; - barsize_y = wpnsize_y; - baroffset_x = (wpnsize_x - barsize_x) / 2; + barsize_x = aspect * weapon_size_y; + barsize_y = weapon_size_y; + baroffset_x = (weapon_size_x - barsize_x) / 2; } else { - barsize_y = 1/aspect * wpnsize_x; - barsize_x = wpnsize_x; - baroffset_y = (wpnsize_y - barsize_y) / 2; + barsize_y = 1/aspect * weapon_size_x; + barsize_x = weapon_size_x; + baroffset_y = (weapon_size_y - barsize_y) / 2; } } - float show_accuracy; - float weapon_stats; if(autocvar_hud_panel_weapons_accuracy && acc_levels) { show_accuracy = true; @@ -1723,124 +667,139 @@ void HUD_Weapons(void) acc_col[i] = stov(cvar_string(strcat("accuracy_color", ftos(i)))); } - float weapons_st = getstati(STAT_WEAPONS); - float label = autocvar_hud_panel_weapons_label; - - for(i = 0; i < weapon_cnt; ++i) + for(i = 0; i <= WEP_LAST-WEP_FIRST; ++i) { - wpnpos = panel_pos + eX * column * wpnsize_x + eY * row * wpnsize_y; - + // retrieve information about the current weapon to be drawn self = weaponorder[i]; - weapid = self.impulse; + weapon_id = self.impulse; + + // skip if this weapon doesn't exist + if (!self || self.impulse < 0) { continue; } + + // skip this weapon if we don't own it (and onlyowned is enabled)-- or if weapons_complainbubble is showing for this weapon + if (autocvar_hud_panel_weapons_onlyowned + && !((weapons_stat & self.weapons) + || (self.weapon == complain_weapon + && time - complain_weapon_time < when + fadetime + && autocvar_hud_panel_weapons_complainbubble))) + continue; + + // figure out the drawing position of weapon + weapon_pos = (panel_pos + + eX * column * weapon_size_x + + eY * row * weapon_size_y); // draw background behind currently selected weapon - if(self.weapon == activeweapon) - drawpic_aspect_skin(wpnpos, "weapon_current_bg", wpnsize, '1 1 1', wpnalpha, DRAWFLAG_NORMAL); + if(self.weapon == switchweapon) + drawpic_aspect_skin(weapon_pos, "weapon_current_bg", weapon_size, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL); // draw the weapon accuracy if(show_accuracy) { - weapon_stats = weapon_accuracy[self.weapon-WEP_FIRST]; - if(weapon_stats >= 0) + panel_weapon_accuracy = weapon_accuracy[self.weapon-WEP_FIRST]; + if(panel_weapon_accuracy >= 0) { - // find the max level lower than weapon_stats - float j; + // find the max level lower than weapon_accuracy j = acc_levels-1; - while ( j && weapon_stats < acc_lev[j] ) + while ( j && panel_weapon_accuracy < acc_lev[j] ) --j; - // inject color j+1 in color j, how much depending on how much weapon_stats is higher than level j - float factor; - factor = (weapon_stats - acc_lev[j]) / (acc_lev[j+1] - acc_lev[j]); + // inject color j+1 in color j, how much depending on how much weapon_accuracy is higher than level j + factor = (panel_weapon_accuracy - acc_lev[j]) / (acc_lev[j+1] - acc_lev[j]); color = acc_col[j]; color = color + factor * (acc_col[j+1] - color); - drawpic_aspect_skin(wpnpos, "weapon_accuracy", wpnsize, color, panel_fg_alpha, DRAWFLAG_NORMAL); + drawpic_aspect_skin(weapon_pos, "weapon_accuracy", weapon_size, color, panel_fg_alpha, DRAWFLAG_NORMAL); } } - // draw the weapon icon - if((weapid >= 0) && (weapons_st & self.weapons)) + // drawing all the weapon items + if(weapons_stat & self.weapons) { - drawpic_aspect_skin(wpnpos, strcat("weapon", self.netname), wpnsize, '1 1 1', wpnalpha, DRAWFLAG_NORMAL); + // draw the weapon image + drawpic_aspect_skin(weapon_pos, strcat("weapon", self.netname), weapon_size, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL); + + // draw weapon label string + switch(autocvar_hud_panel_weapons_label) + { + case 1: // weapon number + drawstring(weapon_pos, ftos(weapon_id), '1 1 0' * 0.5 * weapon_size_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + break; + + case 2: // bind + drawstring(weapon_pos, getcommandkey(ftos(weapon_id), strcat("impulse ", ftos(weapon_id))), '1 1 0' * 0.5 * weapon_size_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + break; + + case 3: // weapon name + drawstring(weapon_pos, self.netname, '1 1 0' * 0.5 * weapon_size_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + break; - if(label == 1) // weapon number - drawstring(wpnpos, ftos(weapid), '1 1 0' * 0.5 * wpnsize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); - else if(label == 2) // bind - drawstring(wpnpos, getcommandkey(ftos(weapid), strcat("impulse ", ftos(weapid))), '1 1 0' * 0.5 * wpnsize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + default: // nothing + break; + } // draw ammo status bar - if(show_ammo && self.weapon != WEP_TUBA && self.weapon != WEP_LASER && self.weapon != WEP_PORTO) + if(autocvar_hud_panel_weapons_ammo && self.weapon != WEP_TUBA && self.weapon != WEP_LASER && self.weapon != WEP_PORTO) { a = 0; - type = GetAmmoTypeForWep(self.weapon); - if(type != -1) - a = getstati(GetAmmoStat(type)); // how much ammo do we have? + ammo_type = GetAmmoTypeForWep(self.weapon); + if(ammo_type != -1) + a = getstati(GetAmmoStat(ammo_type)); // how much ammo do we have? if(a > 0) { - switch(type) { - case 0: fullammo = fullammo_shells; break; - case 1: fullammo = fullammo_nails; break; - case 2: fullammo = fullammo_rockets; break; - case 3: fullammo = fullammo_cells; break; - case 4: fullammo = fullammo_fuel; break; - default: fullammo = 60; + switch(ammo_type) { + case 0: ammo_full = autocvar_hud_panel_weapons_ammo_full_shells; break; + case 1: ammo_full = autocvar_hud_panel_weapons_ammo_full_nails; break; + case 2: ammo_full = autocvar_hud_panel_weapons_ammo_full_rockets; break; + case 3: ammo_full = autocvar_hud_panel_weapons_ammo_full_cells; break; + case 4: ammo_full = autocvar_hud_panel_weapons_ammo_full_fuel; break; + default: ammo_full = 60; } drawsetcliparea( - wpnpos_x + baroffset_x, - wpnpos_y + baroffset_y, - barsize_x * bound(0, a/fullammo, 1), + weapon_pos_x + baroffset_x, + weapon_pos_y + baroffset_y, + barsize_x * bound(0, a/ammo_full, 1), barsize_y); - drawpic_aspect_skin(wpnpos, "weapon_ammo", wpnsize, ammo_color, ammo_alpha, DRAWFLAG_NORMAL); + drawpic_aspect_skin(weapon_pos, "weapon_ammo", weapon_size, ammo_color, ammo_alpha, DRAWFLAG_NORMAL); drawresetcliparea(); } } } - - // draw a "ghost weapon icon" if you don't have the weapon - else + else // draw a "ghost weapon icon" if you don't have the weapon { - drawpic_aspect_skin(wpnpos, strcat("weapon", self.netname), wpnsize, '0 0 0', panel_fg_alpha * 0.5, DRAWFLAG_NORMAL); + drawpic_aspect_skin(weapon_pos, strcat("weapon", self.netname), weapon_size, '0 0 0', panel_fg_alpha * 0.5, DRAWFLAG_NORMAL); } // draw the complain message if(time - complain_weapon_time < when + fadetime && self.weapon == complain_weapon && autocvar_hud_panel_weapons_complainbubble) { if(fadetime) - { - if(complain_weapon_time + when > time) - a = 1; - else - a = bound(0, (complain_weapon_time + when + fadetime - time) / fadetime, 1); - } + a = ((complain_weapon_time + when > time) ? 1 : bound(0, (complain_weapon_time + when + fadetime - time) / fadetime, 1)); else - { - if(complain_weapon_time + when > time) - a = 1; - else - a = 0; - } + a = ((complain_weapon_time + when > time) ? 1 : 0); + string s; if(complain_weapon_type == 0) { - s = "Out of ammo"; + s = _("Out of ammo"); color = stov(autocvar_hud_panel_weapons_complainbubble_color_outofammo); } else if(complain_weapon_type == 1) { - s = "Don't have"; + s = _("Don't have"); color = stov(autocvar_hud_panel_weapons_complainbubble_color_donthave); } else { - s = "Unavailable"; + s = _("Unavailable"); color = stov(autocvar_hud_panel_weapons_complainbubble_color_unavailable); } float padding = autocvar_hud_panel_weapons_complainbubble_padding; - drawpic_aspect_skin(wpnpos + '1 1 0' * padding, "weapon_complainbubble", wpnsize - '2 2 0' * padding, color, a * panel_fg_alpha, DRAWFLAG_NORMAL); - drawstring_aspect(wpnpos + '1 1 0' * padding, s, wpnsize - '2 2 0' * padding, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); + drawpic_aspect_skin(weapon_pos + '1 1 0' * padding, "weapon_complainbubble", weapon_size - '2 2 0' * padding, color, a * panel_fg_alpha, DRAWFLAG_NORMAL); + drawstring_aspect(weapon_pos + '1 1 0' * padding, s, weapon_size - '2 2 0' * padding, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); } + // continue with new position for the next weapon ++row; if(row >= rows) { @@ -1848,7 +807,6 @@ void HUD_Weapons(void) ++column; } } - } // Ammo (#1) @@ -1880,28 +838,30 @@ string GetAmmoPicture(float i) } } -void DrawAmmoItem(vector myPos, vector mySize, float itemcode, float currently_selected) +void DrawAmmoItem(vector myPos, vector mySize, float itemcode, float currently_selected, float infinite_ammo) { float a; if(autocvar__hud_configure) { currently_selected = (itemcode == 2); //rockets always selected - a = 100; + a = 31 + mod(itemcode*93, 128); } else a = getstati(GetAmmoStat(itemcode)); // how much ammo do we have of type itemcode? vector color; - if(a < 10) + if(infinite_ammo) + color = '0 0.5 0.75'; + else if(a < 10) color = '0.7 0 0'; else color = '1 1 1'; - float alpha; + float theAlpha; if(currently_selected) - alpha = 1; + theAlpha = 1; else - alpha = 0.7; + theAlpha = 0.7; vector picpos, numpos; if(autocvar_hud_panel_ammo_iconalign) @@ -1919,28 +879,34 @@ void DrawAmmoItem(vector myPos, vector mySize, float itemcode, float currently_s drawpic_aspect_skin(myPos, "ammo_current_bg", mySize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); if(a > 0 && autocvar_hud_panel_ammo_progressbar) - HUD_Panel_DrawProgressBar(myPos + eX * autocvar_hud_panel_ammo_progressbar_xoffset * mySize_x, mySize - eX * autocvar_hud_panel_ammo_progressbar_xoffset * mySize_x, autocvar_hud_panel_ammo_progressbar_name, 0, 0, min(1, a/autocvar_hud_panel_ammo_maxammo), color, autocvar_hud_progressbar_alpha * panel_fg_alpha * alpha, DRAWFLAG_NORMAL); + HUD_Panel_DrawProgressBar(myPos + eX * autocvar_hud_panel_ammo_progressbar_xoffset * mySize_x, mySize - eX * autocvar_hud_panel_ammo_progressbar_xoffset * mySize_x, autocvar_hud_panel_ammo_progressbar_name, a/autocvar_hud_panel_ammo_maxammo, 0, 0, color, autocvar_hud_progressbar_alpha * panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL); if(autocvar_hud_panel_ammo_text) { - if(a > 0) - drawstring_aspect(numpos, ftos(a), eX * (2/3) * mySize_x + eY * mySize_y, color, panel_fg_alpha * alpha, DRAWFLAG_NORMAL); + if(a > 0 || infinite_ammo) + drawstring_aspect(numpos, ftos(a), eX * (2/3) * mySize_x + eY * mySize_y, color, panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL); else // "ghost" ammo count - drawstring_aspect(numpos, ftos(a), eX * (2/3) * mySize_x + eY * mySize_y, '0 0 0', panel_fg_alpha * alpha * 0.5, DRAWFLAG_NORMAL); + drawstring_aspect(numpos, ftos(a), eX * (2/3) * mySize_x + eY * mySize_y, '0 0 0', panel_fg_alpha * theAlpha * 0.5, DRAWFLAG_NORMAL); } - if(a > 0) - drawpic_aspect_skin(picpos, GetAmmoPicture(itemcode), '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha * alpha, DRAWFLAG_NORMAL); + if(a > 0 || infinite_ammo) + drawpic_aspect_skin(picpos, GetAmmoPicture(itemcode), '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL); else // "ghost" ammo icon - drawpic_aspect_skin(picpos, GetAmmoPicture(itemcode), '1 1 0' * mySize_y, '0 0 0', panel_fg_alpha * alpha * 0.5, DRAWFLAG_NORMAL); + drawpic_aspect_skin(picpos, GetAmmoPicture(itemcode), '1 1 0' * mySize_y, '0 0 0', panel_fg_alpha * theAlpha * 0.5, DRAWFLAG_NORMAL); } void HUD_Ammo(void) { - if(!autocvar_hud_panel_ammo && !autocvar__hud_configure) - return; + if(hud != HUD_NORMAL) return; + if(!autocvar__hud_configure) + { + if(!autocvar_hud_panel_ammo) return; + if(spectatee_status == -1) return; + } + else + hud_configure_active_panel = HUD_PANEL_AMMO; - active_panel = HUD_PANEL_AMMO; HUD_Panel_UpdateCvars(ammo); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -1967,7 +933,7 @@ void HUD_Ammo(void) ammo_size = eX * mySize_x*(1/columns) + eY * mySize_y*(1/rows); } - vector offset; + local noref vector offset; // fteqcc sucks float newSize; if(ammo_size_x/ammo_size_y > 3) { @@ -1984,31 +950,35 @@ void HUD_Ammo(void) ammo_size_y = newSize; } - drawfont = hud_bigfont; - float i, stat_items, currently_selected; + float i, stat_items, currently_selected, infinite_ammo; + infinite_ammo = FALSE; if (autocvar_hud_panel_ammo_onlycurrent) { if(autocvar__hud_configure) { - DrawAmmoItem(pos, ammo_size, 2, true); //show rockets + DrawAmmoItem(pos, ammo_size, 2, true, FALSE); //show rockets return; } - stat_items = getstati(STAT_ITEMS); + stat_items = getstati(STAT_ITEMS, 0, 24); + if (stat_items & IT_UNLIMITED_WEAPON_AMMO) + infinite_ammo = TRUE; for (i = 0; i < AMMO_COUNT; ++i) { currently_selected = stat_items & GetAmmoItemCode(i); if (currently_selected) { - DrawAmmoItem(pos, ammo_size, i, true); + DrawAmmoItem(pos, ammo_size, i, true, infinite_ammo); return; } } return; // nothing to display } - stat_items = getstati(STAT_ITEMS); + stat_items = getstati(STAT_ITEMS, 0, 24); + if (stat_items & IT_UNLIMITED_WEAPON_AMMO) + infinite_ammo = TRUE; for (i = 0; i < AMMO_COUNT; ++i) { currently_selected = stat_items & GetAmmoItemCode(i); - DrawAmmoItem(pos + eX * column * (ammo_size_x + offset_x) + eY * row * (ammo_size_y + offset_y), ammo_size, i, currently_selected); + DrawAmmoItem(pos + eX * column * (ammo_size_x + offset_x) + eY * row * (ammo_size_y + offset_y), ammo_size, i, currently_selected, infinite_ammo); ++row; if(row >= rows) { @@ -2016,13 +986,53 @@ void HUD_Ammo(void) column = column + 1; } } - drawfont = hud_font; } -void DrawNumIcon(float iconalign, vector myPos, vector mySize, float x, string icon, float left, vector color, float alpha) +void DrawNumIcon(vector myPos, vector mySize, float x, string icon, float vertical, float icon_right_align, vector color, float theAlpha) { - vector newPos; - float newSize_x, newSize_y; + vector newPos, newSize; + vector picpos, numpos; + + if (vertical) + { + if(mySize_y/mySize_x > 2) + { + newSize_y = 2 * mySize_x; + newSize_x = mySize_x; + + newPos_y = myPos_y + (mySize_y - newSize_y) / 2; + newPos_x = myPos_x; + } + else + { + newSize_x = 1/2 * mySize_y; + newSize_y = mySize_y; + + newPos_x = myPos_x + (mySize_x - newSize_x) / 2; + newPos_y = myPos_y; + } + + if(icon_right_align) + { + numpos = newPos; + picpos = newPos + eY * newSize_x; + } + else + { + picpos = newPos; + numpos = newPos + eY * newSize_x; + } + + newSize_y /= 2; + drawpic_aspect_skin(picpos, icon, newSize, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL); + // make number smaller than icon, it looks better + // reduce only y to draw numbers with different number of digits with the same y size + numpos_y += newSize_y * ((1 - 0.7) / 2); + newSize_y *= 0.7; + drawstring_aspect(numpos, ftos(x), newSize, color, panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL); + return; + } + if(mySize_x/mySize_y > 3) { newSize_x = 3 * mySize_y; @@ -2040,303 +1050,209 @@ void DrawNumIcon(float iconalign, vector myPos, vector mySize, float x, string i newPos_x = myPos_x; } - vector picpos, numpos; - if(left) + if(icon_right_align) // right align { - if(iconalign == 1 || iconalign == 3) // right align - { - numpos = newPos; - picpos = newPos + eX * 2 * newSize_y; - } - else // left align - { - numpos = newPos + eX * newSize_y; - picpos = newPos; - } + numpos = newPos; + picpos = newPos + eX * 2 * newSize_y; } - else + else // left align { - if(iconalign == 0 || iconalign == 3) // left align - { - numpos = newPos + eX * newSize_y; - picpos = newPos; - } - else // right align - { - numpos = newPos; - picpos = newPos + eX * 2 * newSize_y; - } + numpos = newPos + eX * newSize_y; + picpos = newPos; } - drawfont = hud_bigfont; - drawstring_aspect(numpos, ftos(x), eX * (2/3) * newSize_x + eY * newSize_y, color, panel_fg_alpha * alpha, DRAWFLAG_NORMAL); - drawfont = hud_font; - drawpic_aspect_skin(picpos, icon, '1 1 0' * newSize_y, '1 1 1', panel_fg_alpha * alpha, DRAWFLAG_NORMAL); + drawstring_aspect(numpos, ftos(x), '2 1 0' * newSize_y, color, panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL); + drawpic_aspect_skin(picpos, icon, '1 1 0' * newSize_y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL); } -void DrawNumIcon_expanding(float iconalign, vector myPos, vector mySize, float x, string icon, float left, vector color, float fadelerp) +void DrawNumIcon_expanding(vector myPos, vector mySize, float x, string icon, float vertical, float icon_right_align, vector color, float fadelerp) { float sz; sz = expandingbox_sizefactor_from_fadelerp(fadelerp); - DrawNumIcon(iconalign, myPos + expandingbox_resize_centered_box_offset(sz, mySize, 1), mySize * sz, x, icon, left, color, (1 - fadelerp)); + DrawNumIcon(myPos + expandingbox_resize_centered_box_offset(sz, mySize, 1), mySize * sz, x, icon, vertical, icon_right_align, color, (1 - fadelerp)); } // Powerups (#2) // -void HUD_Powerups(void) { - if(!autocvar_hud_panel_powerups && !autocvar__hud_configure) - return; - +void HUD_Powerups(void) +{ + float strength_time, shield_time; if(!autocvar__hud_configure) { - if not(getstati(STAT_ITEMS) & (IT_STRENGTH | IT_INVINCIBLE)) - return; + if(!autocvar_hud_panel_powerups) return; + if(spectatee_status == -1) return; + if not(getstati(STAT_ITEMS, 0, 24) & (IT_STRENGTH | IT_INVINCIBLE)) return; + if (getstati(STAT_HEALTH) <= 0) return; - if (getstati(STAT_HEALTH) <= 0) - return; + strength_time = bound(0, getstatf(STAT_STRENGTH_FINISHED) - time, 99); + shield_time = bound(0, getstatf(STAT_INVINCIBLE_FINISHED) - time, 99); + } + else + { + hud_configure_active_panel = HUD_PANEL_POWERUPS; + + strength_time = 15; + shield_time = 27; } - active_panel = HUD_PANEL_POWERUPS; HUD_Panel_UpdateCvars(powerups); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; - float strength_time, shield_time; - if(autocvar__hud_configure) + HUD_Panel_DrawBg(bound(0, max(strength_time, shield_time), 1)); + if(panel_bg_padding) { - strength_time = 15; - shield_time = 27; + pos += '1 1 0' * panel_bg_padding; + mySize -= '2 2 0' * panel_bg_padding; + } + + float panel_ar = mySize_x/mySize_y; + float is_vertical = (panel_ar < 1); + vector shield_offset, strength_offset; + if (panel_ar >= 4 || (panel_ar >= 1/4 && panel_ar < 1)) + { + mySize_x *= 0.5; + if (autocvar_hud_panel_powerups_flip) + shield_offset_x = mySize_x; + else + strength_offset_x = mySize_x; } else { - strength_time = bound(0, getstatf(STAT_STRENGTH_FINISHED) - time, 99); - shield_time = bound(0, getstatf(STAT_INVINCIBLE_FINISHED) - time, 99); + mySize_y *= 0.5; + if (autocvar_hud_panel_powerups_flip) + shield_offset_y = mySize_y; + else + strength_offset_y = mySize_y; } - HUD_Panel_DrawBg(bound(0, max(strength_time, shield_time), 1)); - if(panel_bg_padding) + float shield_baralign, strength_baralign; + float shield_iconalign, strength_iconalign; + if (autocvar_hud_panel_powerups_flip) { - pos += '1 1 0' * panel_bg_padding; - mySize -= '2 2 0' * panel_bg_padding; + strength_baralign = (autocvar_hud_panel_powerups_baralign == 2 || autocvar_hud_panel_powerups_baralign == 1); + shield_baralign = (autocvar_hud_panel_powerups_baralign == 3 || autocvar_hud_panel_powerups_baralign == 1); + strength_iconalign = (autocvar_hud_panel_powerups_iconalign == 2 || autocvar_hud_panel_powerups_iconalign == 1); + shield_iconalign = (autocvar_hud_panel_powerups_iconalign == 3 || autocvar_hud_panel_powerups_iconalign == 1); + } + else + { + shield_baralign = (autocvar_hud_panel_powerups_baralign == 2 || autocvar_hud_panel_powerups_baralign == 1); + strength_baralign = (autocvar_hud_panel_powerups_baralign == 3 || autocvar_hud_panel_powerups_baralign == 1); + shield_iconalign = (autocvar_hud_panel_powerups_iconalign == 2 || autocvar_hud_panel_powerups_iconalign == 1); + strength_iconalign = (autocvar_hud_panel_powerups_iconalign == 3 || autocvar_hud_panel_powerups_iconalign == 1); } - vector barpos, barsize; - vector picpos; - vector numpos; - - string leftname, rightname; - string leftprogressname, rightprogressname; - float leftcnt, rightcnt; - float leftexact, rightexact; - float flip = autocvar_hud_panel_powerups_flip; - if (flip) { - leftname = "strength"; - leftprogressname = autocvar_hud_panel_powerups_progressbar_strength; - leftcnt = ceil(strength_time); - leftexact = strength_time; - - rightname = "shield"; - rightprogressname = autocvar_hud_panel_powerups_progressbar_shield; - rightcnt = ceil(shield_time); - rightexact = shield_time; - } else { - leftname = "shield"; - leftprogressname = autocvar_hud_panel_powerups_progressbar_shield; - leftcnt = ceil(shield_time); - leftexact = shield_time; - - rightname = "strength"; - rightprogressname = autocvar_hud_panel_powerups_progressbar_strength; - rightcnt = ceil(strength_time); - rightexact = strength_time; - } - - drawfont = hud_bigfont; - float baralign = autocvar_hud_panel_powerups_baralign; - float barflip; - float iconalign = autocvar_hud_panel_powerups_iconalign; - float progressbar = autocvar_hud_panel_powerups_progressbar; - if (mySize_x/mySize_y > 4) - { - barsize = eX * 0.5 * mySize_x + eY * mySize_y; - if(leftcnt) + if(shield_time) + { + const float maxshield = 30; + float shield = ceil(shield_time); + if(autocvar_hud_panel_powerups_progressbar) { - if(baralign == 1 || baralign == 3) { // right align - barpos = pos + eX * 0.5 * mySize_x; - barflip = 1; - } else { // left align - barpos = pos; - barflip = 0; - } - - if(progressbar) - { - HUD_Panel_GetProgressBarColorForString(leftname); - HUD_Panel_DrawProgressBar(barpos, barsize, leftprogressname, 0, barflip, min(1, leftcnt/30), progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha * bound(0, max(strength_time, shield_time), 1), DRAWFLAG_NORMAL); - } - if(autocvar_hud_panel_powerups_text) - { - if(leftcnt > 1) - DrawNumIcon(iconalign, pos, eX * 0.5 * mySize_x + eY * mySize_y, leftcnt, leftname, 1, '1 1 1', 1); - if(leftcnt <= 5) - DrawNumIcon_expanding(iconalign, pos, eX * 0.5 * mySize_x + eY * mySize_y, leftcnt, leftname, 1, '1 1 1', bound(0, (leftcnt - leftexact) / 0.5, 1)); - } + HUD_Panel_GetProgressBarColor(shield); + HUD_Panel_DrawProgressBar(pos + shield_offset, mySize, autocvar_hud_panel_powerups_progressbar_shield, shield/maxshield, is_vertical, shield_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); } - - if(rightcnt) + if(autocvar_hud_panel_powerups_text) { - if(baralign == 0 || baralign == 3) { // left align - barpos = pos; - barflip = 0; - } else { // right align - barpos = pos + eX * 0.5 * mySize_x; - barflip = 1; - } - - if(progressbar) - { - HUD_Panel_GetProgressBarColorForString(rightname); - HUD_Panel_DrawProgressBar(barpos, barsize, rightprogressname, 0, barflip, min(1, rightcnt/30), progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha * bound(0, max(strength_time, shield_time), 1), DRAWFLAG_NORMAL); - } - if(autocvar_hud_panel_powerups_text) - { - if(rightcnt > 1) - DrawNumIcon(iconalign, pos + eX * 0.5 * mySize_x, eX * 0.5 * mySize_x + eY * mySize_y, rightcnt, rightname, 0, '1 1 1', 1); - if(rightcnt <= 5) - DrawNumIcon_expanding(iconalign, pos + eX * 0.5 * mySize_x, eX * 0.5 * mySize_x + eY * mySize_y, rightcnt, rightname, 0, '1 1 1', bound(0, (rightcnt - rightexact) / 0.5, 1)); - } + if(shield > 1) + DrawNumIcon(pos + shield_offset, mySize, shield, "shield", is_vertical, shield_iconalign, '1 1 1', 1); + if(shield <= 5) + DrawNumIcon_expanding(pos + shield_offset, mySize, shield, "shield", is_vertical, shield_iconalign, '1 1 1', bound(0, (shield - shield_time) / 0.5, 1)); } } - else if (mySize_x/mySize_y > 1.5) + + if(strength_time) { - barsize = eX * mySize_x + eY * 0.5 * mySize_y; - if(leftcnt) + const float maxstrength = 30; + float strength = ceil(strength_time); + if(autocvar_hud_panel_powerups_progressbar) { - barpos = pos; - if(baralign == 1 || baralign == 3) { // right/down align - barflip = 1; - } else { // left/up align - barflip = 0; - } - - if(progressbar) - { - HUD_Panel_GetProgressBarColorForString(leftname); - HUD_Panel_DrawProgressBar(barpos, barsize, leftprogressname, 0, barflip, min(1, leftcnt/30), progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha * bound(0, max(strength_time, shield_time), 1), DRAWFLAG_NORMAL); - } - if(autocvar_hud_panel_powerups_text) - { - if(leftcnt > 1) - DrawNumIcon(iconalign, pos, eX * mySize_x + eY * 0.5 * mySize_y, leftcnt, leftname, 1, '1 1 1', 1); - if(leftcnt <= 5) - DrawNumIcon_expanding(iconalign, pos, eX * mySize_x + eY * 0.5 * mySize_y, leftcnt, leftname, 1, '1 1 1', bound(0, (leftcnt - leftexact) / 0.5, 1)); - } + HUD_Panel_GetProgressBarColor(strength); + HUD_Panel_DrawProgressBar(pos + strength_offset, mySize, autocvar_hud_panel_powerups_progressbar_strength, strength/maxstrength, is_vertical, strength_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); } - - if(rightcnt) + if(autocvar_hud_panel_powerups_text) { - barpos = pos + eY * 0.5 * mySize_y; - if(baralign == 0 || baralign == 3) { // left align - barflip = 0; - } else { // right align - barflip = 1; - } - - if(progressbar) - { - HUD_Panel_GetProgressBarColorForString(rightname); - HUD_Panel_DrawProgressBar(barpos, barsize, rightprogressname, 0, barflip, min(1, rightcnt/30), progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha * bound(0, max(strength_time, shield_time), 1), DRAWFLAG_NORMAL); - } - if(autocvar_hud_panel_powerups_text) - { - if(rightcnt > 1) - DrawNumIcon(iconalign, pos + eY * 0.5 * mySize_y, eX * mySize_x + eY * 0.5 * mySize_y, rightcnt, rightname, 0, '1 1 1', 1); - if(rightcnt <= 5) - DrawNumIcon_expanding(iconalign, pos + eY * 0.5 * mySize_y, eX * mySize_x + eY * 0.5 * mySize_y, rightcnt, rightname, 0, '1 1 1', bound(0, (rightcnt - rightexact) / 0.5, 1)); - } + if(strength > 1) + DrawNumIcon(pos + strength_offset, mySize, strength, "strength", is_vertical, strength_iconalign, '1 1 1', 1); + if(strength <= 5) + DrawNumIcon_expanding(pos + strength_offset, mySize, strength, "strength", is_vertical, strength_iconalign, '1 1 1', bound(0, (strength - strength_time) / 0.5, 1)); } } - else - { - barsize = eX * 0.5 * mySize_x + eY * mySize_y; - if(leftcnt) - { - barpos = pos; - if(baralign == 1 || baralign == 3) { // down align - barflip = 1; - } else { // up align - barflip = 0; - } +} - if(iconalign == 1 || iconalign == 3) { // down align - picpos = pos + eX * 0.05 * mySize_x + eY * (mySize_y - 0.65 * mySize_x); - numpos = pos + eY * mySize_y - eY * 0.25 * mySize_x; - } else { // up align - picpos = pos + eX * 0.05 * mySize_x; - numpos = pos + eY * 0.4 * mySize_x; - } +// Health/armor (#3) +// - if(progressbar) - { - HUD_Panel_GetProgressBarColorForString(leftname); - HUD_Panel_DrawProgressBar(barpos, barsize, leftprogressname, 1, barflip, min(1, leftcnt/30), progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha * bound(0, max(strength_time, shield_time), 1), DRAWFLAG_NORMAL); - } - if(autocvar_hud_panel_powerups_text) - { - if(leftcnt <= 5) - drawpic_aspect_skin_expanding(picpos, leftname, '0.4 0.4 0' * mySize_x, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, bound(0, (leftcnt - leftexact) / 0.5, 1)); - if(leftcnt > 1) - drawpic_aspect_skin(picpos, leftname, '0.4 0.4 0' * mySize_x, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); - drawstring_aspect(numpos, ftos(leftcnt), eX * 0.5 * mySize_x + eY * 0.25 * mySize_x, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); - } - } +// prev_* vars contain the health/armor at the previous FRAME +// set to -1 when player is dead or was not playing +float prev_health, prev_armor; +float health_damagetime, armor_damagetime; +float health_beforedamage, armor_beforedamage; +// old_p_* vars keep track of previous values when smoothing value changes of the progressbar +float old_p_health, old_p_armor; +float old_p_healthtime, old_p_armortime; +// prev_p_* vars contain the health/armor progressbar value at the previous FRAME +// set to -1 to forcedly stop effects when we switch spectated player (e.g. from playerX: 70h to playerY: 50h) +float prev_p_health, prev_p_armor; + +void HUD_HealthArmor(void) +{ + float armor, health, fuel; + if(!autocvar__hud_configure) + { + if(!autocvar_hud_panel_healtharmor) return; + if(hud != HUD_NORMAL) return; + if(spectatee_status == -1) return; - if(rightcnt) + health = getstati(STAT_HEALTH); + if(health <= 0) { - barpos = pos + eX * 0.5 * mySize_x; - if(baralign == 0 || baralign == 3) { // down align - barflip = 1; - } else { // up align - barflip = 0; - } + prev_health = -1; + return; + } + armor = getstati(STAT_ARMOR); - if(iconalign == 0 || iconalign == 3) { // up align - picpos = pos + eX * 0.05 * mySize_x + eX * 0.5 * mySize_x; - numpos = pos + eY * 0.4 * mySize_x + eX * 0.5 * mySize_x; - } else { // down align - picpos = pos + eX * 0.05 * mySize_x + eY * (mySize_y - 0.65 * mySize_x) + eX * 0.5 * mySize_x; - numpos = pos + eY * mySize_y - eY * 0.25 * mySize_x + eX * 0.5 * mySize_x; - } + // code to check for spectatee_status changes is in Ent_ClientData() + // prev_p_health and prev_health can be set to -1 there - if(progressbar) - { - HUD_Panel_GetProgressBarColorForString(rightname); - HUD_Panel_DrawProgressBar(barpos, barsize, rightprogressname, 1, barflip, min(1, rightcnt/30), progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha * bound(0, max(strength_time, shield_time), 1), DRAWFLAG_NORMAL); - } - if(autocvar_hud_panel_powerups_text) - { - if(rightcnt <= 5) - drawpic_aspect_skin_expanding(picpos, rightname, '0.4 0.4 0' * mySize_x, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, bound(0, (rightcnt - rightexact) / 0.5, 1)); - if(rightcnt > 1) - drawpic_aspect_skin(picpos, rightname, '0.4 0.4 0' * mySize_x, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); - drawstring_aspect(numpos, ftos(rightcnt), eX * 0.5 * mySize_x + eY * 0.25 * mySize_x, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); - } + if (prev_p_health == -1) + { + // no effect + health_beforedamage = 0; + armor_beforedamage = 0; + health_damagetime = 0; + armor_damagetime = 0; + prev_health = health; + prev_armor = armor; + old_p_health = health; + old_p_armor = armor; + prev_p_health = health; + prev_p_armor = armor; + } + else if (prev_health == -1) + { + //start the load effect + health_damagetime = 0; + armor_damagetime = 0; + prev_health = 0; + prev_armor = 0; } + fuel = getstati(STAT_FUEL); } - drawfont = hud_font; -} + else + { + hud_configure_active_panel = HUD_PANEL_HEALTHARMOR; -// Health/armor (#3) -// -void HUD_HealthArmor(void) -{ - if(!autocvar_hud_panel_healtharmor && !autocvar__hud_configure) - return; + health = 150; + armor = 75; + fuel = 20; + } - active_panel = HUD_PANEL_HEALTHARMOR; HUD_Panel_UpdateCvars(healtharmor); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -2348,29 +1264,8 @@ void HUD_HealthArmor(void) mySize -= '2 2 0' * panel_bg_padding; } - float armor, health, fuel; - armor = getstati(STAT_ARMOR); - health = getstati(STAT_HEALTH); - fuel = getstati(STAT_FUEL); - - if(autocvar__hud_configure) - { - armor = 75; - health = 150; - fuel = 20; - } - - if(health <= 0) - return; - - vector barpos, barsize; - vector picpos; - vector numpos; - - drawfont = hud_bigfont; float baralign = autocvar_hud_panel_healtharmor_baralign; float iconalign = autocvar_hud_panel_healtharmor_iconalign; - float progressbar = autocvar_hud_panel_healtharmor_progressbar; float maxhealth = autocvar_hud_panel_healtharmor_maxhealth; float maxarmor = autocvar_hud_panel_healtharmor_maxarmor; @@ -2383,18 +1278,14 @@ void HUD_HealthArmor(void) x = floor(v_x + 1); float maxtotal = maxhealth + maxarmor; - - barpos = pos; - barsize = mySize; - string biggercount; if(v_z) // NOT fully armored { biggercount = "health"; - if(progressbar) + if(autocvar_hud_panel_healtharmor_progressbar) { HUD_Panel_GetProgressBarColor(health); - HUD_Panel_DrawProgressBar(barpos, barsize, autocvar_hud_panel_healtharmor_progressbar_health, 0, mod(baralign, 2), x/maxtotal, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); + HUD_Panel_DrawProgressBar(pos, mySize, autocvar_hud_panel_healtharmor_progressbar_health, x/maxtotal, 0, (baralign == 1 || baralign == 2), progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); } if(armor) if(autocvar_hud_panel_healtharmor_text) @@ -2403,234 +1294,182 @@ void HUD_HealthArmor(void) else { biggercount = "armor"; - if(progressbar) + if(autocvar_hud_panel_healtharmor_progressbar) { HUD_Panel_GetProgressBarColor(armor); - HUD_Panel_DrawProgressBar(barpos, barsize, autocvar_hud_panel_healtharmor_progressbar_armor, 0, mod(baralign, 2), x/maxtotal, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); + HUD_Panel_DrawProgressBar(pos, mySize, autocvar_hud_panel_healtharmor_progressbar_armor, x/maxtotal, 0, (baralign == 1 || baralign == 2), progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); } if(health) if(autocvar_hud_panel_healtharmor_text) drawpic_aspect_skin(pos + eX * mySize_x - eX * 0.5 * mySize_y, "health", '0.5 0.5 0' * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); } if(autocvar_hud_panel_healtharmor_text) - DrawNumIcon(iconalign, pos, mySize, x, biggercount, 1, HUD_Get_Num_Color(x, maxtotal), 1); + DrawNumIcon(pos, mySize, x, biggercount, 0, iconalign, HUD_Get_Num_Color(x, maxtotal), 1); - // fuel if(fuel) { - barpos = pos; - barsize = eX * mySize_x + eY * 0.2 * mySize_y; HUD_Panel_GetProgressBarColor(fuel); - HUD_Panel_DrawProgressBar(barpos, barsize, "progressbar", 0, mod(baralign, 2), min(1, fuel/100), progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha * 0.8, DRAWFLAG_NORMAL); + HUD_Panel_DrawProgressBar(pos, eX * mySize_x + eY * 0.2 * mySize_y, "progressbar", fuel/100, 0, (baralign == 1 || baralign == 3), progressbar_color, panel_fg_alpha * 0.8, DRAWFLAG_NORMAL); } } else { - string leftname, rightname; - string leftprogressname, rightprogressname; - float leftcnt, rightcnt; - float leftmax, rightmax; - float leftactive, rightactive; - float leftalpha, rightalpha; - float flip = autocvar_hud_panel_healtharmor_flip; - float barflip; - if (flip) { // old style layout with armor left/top of health - leftname = "armor"; - leftprogressname = autocvar_hud_panel_healtharmor_progressbar_armor; - leftcnt = armor; - if(leftcnt) - leftactive = 1; - leftalpha = min((armor+10)/55, 1); - leftmax = maxarmor; - - rightname = "health"; - rightprogressname = autocvar_hud_panel_healtharmor_progressbar_health; - rightcnt = health; - rightactive = 1; - rightalpha = 1; - rightmax = maxhealth; - } else { - leftname = "health"; - leftprogressname = autocvar_hud_panel_healtharmor_progressbar_health; - leftcnt = health; - leftactive = 1; - leftalpha = 1; - leftmax = maxhealth; - - rightname = "armor"; - rightprogressname = autocvar_hud_panel_healtharmor_progressbar_armor; - rightcnt = armor; - if(rightcnt) - rightactive = 1; - rightalpha = min((armor+10)/55, 1); - rightmax = maxarmor; - } - - if (mySize_x/mySize_y > 4) + float panel_ar = mySize_x/mySize_y; + float is_vertical = (panel_ar < 1); + vector health_offset, armor_offset; + if (panel_ar >= 4 || (panel_ar >= 1/4 && panel_ar < 1)) { - barsize = eX * 0.5 * mySize_x + eY * mySize_y; - if(leftactive) - { - barpos = pos; - if(baralign == 1 || baralign == 3) { // right align - barflip = 1; - } else { // left align - barflip = 0; - } - - if(progressbar) - { - HUD_Panel_GetProgressBarColorForString(leftname); - HUD_Panel_DrawProgressBar(barpos, barsize, leftprogressname, 0, barflip, min(1, leftcnt/leftmax), progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); - } - if(autocvar_hud_panel_healtharmor_text) - DrawNumIcon(iconalign, pos, eX * 0.5 * mySize_x + eY * mySize_y, leftcnt, leftname, 1, HUD_Get_Num_Color(leftcnt, leftmax), 1); - } - - if(rightactive) - { - barpos = pos + eX * 0.5 * mySize_x; - if(baralign == 0 || baralign == 3) { // left align - barflip = 0; - } else { // right align - barflip = 1; - } - - if(progressbar) - { - HUD_Panel_GetProgressBarColorForString(rightname); - HUD_Panel_DrawProgressBar(barpos, barsize, rightprogressname, 0, barflip, min(1, rightcnt/rightmax), progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); - } - if(autocvar_hud_panel_healtharmor_text) - DrawNumIcon(iconalign, pos + eX * 0.5 * mySize_x, eX * 0.5 * mySize_x + eY * mySize_y, rightcnt, rightname, 0, HUD_Get_Num_Color(rightcnt, rightmax), 1); - } - - if(fuel) - { - barpos = pos; - barsize = eX * mySize_x + eY * 0.2 * mySize_y; - HUD_Panel_GetProgressBarColor(fuel); - HUD_Panel_DrawProgressBar(barpos, barsize, "progressbar", 0, mod(baralign, 2), min(1, fuel/100), progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha * 0.8, DRAWFLAG_NORMAL); - } + mySize_x *= 0.5; + if (autocvar_hud_panel_healtharmor_flip) + health_offset_x = mySize_x; + else + armor_offset_x = mySize_x; } - else if (mySize_x/mySize_y > 1.5) + else { - barsize = eX * mySize_x + eY * 0.5 * mySize_y; - if(leftactive) - { - barpos = pos; - if(baralign == 1 || baralign == 3) { // right align - barflip = 1; - } else { // left align - barflip = 0; - } - - if(progressbar) - { - HUD_Panel_GetProgressBarColorForString(leftname); - HUD_Panel_DrawProgressBar(barpos, barsize, leftprogressname, 0, barflip, min(1, leftcnt/leftmax), progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); - } - if(autocvar_hud_panel_healtharmor_text) - DrawNumIcon(iconalign, pos, eX * mySize_x + eY * 0.5 * mySize_y, leftcnt, leftname, 1, HUD_Get_Num_Color(leftcnt, leftmax), 1); - } - - if(rightactive) - { - barpos = pos + eY * 0.5 * mySize_y; - if(baralign == 0 || baralign == 3) { // left align - barflip = 0; - } else { // right align - barflip = 1; - } - - if(progressbar) - { - HUD_Panel_GetProgressBarColorForString(rightname); - HUD_Panel_DrawProgressBar(barpos, barsize, rightprogressname, 0, barflip, min(1, rightcnt/rightmax), progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); - } - if(autocvar_hud_panel_healtharmor_text) - DrawNumIcon(iconalign, pos + eY * 0.5 * mySize_y, eX * mySize_x + eY * 0.5 * mySize_y, rightcnt, rightname, 0, HUD_Get_Num_Color(rightcnt, rightmax), 1); - } + mySize_y *= 0.5; + if (autocvar_hud_panel_healtharmor_flip) + health_offset_y = mySize_y; + else + armor_offset_y = mySize_y; + } - if(fuel) - { - barpos = pos; - barsize = eX * mySize_x + eY * 0.2 * mySize_y; - HUD_Panel_GetProgressBarColor(fuel); - HUD_Panel_DrawProgressBar(barpos, barsize, "progressbar", 0, mod(baralign, 2), min(1, fuel/100), progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha * 0.8, DRAWFLAG_NORMAL); - } + float health_baralign, armor_baralign, fuel_baralign; + float 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; + 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); } else { - barsize = eX * 0.5 * mySize_x + eY * mySize_y; - if(leftactive) + 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; + 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) + { + if(autocvar_hud_panel_healtharmor_progressbar) { - barpos = pos; - if(baralign == 1 || baralign == 3) { // right align - barflip = 1; - } else { // left align - barflip = 0; - } - - if(iconalign == 1 || iconalign == 3) { // down align - picpos = pos + eX * 0.05 * mySize_x + eY * (mySize_y - 0.65 * mySize_x); - numpos = pos + eY * mySize_y - eY * 0.25 * mySize_x; - } else { // up align - picpos = pos + eX * 0.05 * mySize_x; - numpos = pos + eY * 0.4 * mySize_x; - } - - if(progressbar) + HUD_Panel_GetProgressBarColor(health); + float p_health, pain_health_alpha; + p_health = health; + pain_health_alpha = 1; + if (autocvar_hud_panel_healtharmor_progressbar_gfx) { - HUD_Panel_GetProgressBarColorForString(leftname); - HUD_Panel_DrawProgressBar(barpos, barsize, leftprogressname, 1, barflip, min(1, leftcnt/leftmax), progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); + if (autocvar_hud_panel_healtharmor_progressbar_gfx_smooth > 0) + { + if (fabs(prev_health - health) >= autocvar_hud_panel_healtharmor_progressbar_gfx_smooth) + { + if (time - old_p_healthtime < 1) + old_p_health = prev_p_health; + else + old_p_health = prev_health; + old_p_healthtime = time; + } + if (time - old_p_healthtime < 1) + { + p_health += (old_p_health - health) * (1 - (time - old_p_healthtime)); + prev_p_health = p_health; + } + } + if (autocvar_hud_panel_healtharmor_progressbar_gfx_damage > 0) + { + if (prev_health - health >= autocvar_hud_panel_healtharmor_progressbar_gfx_damage) + { + if (time - health_damagetime >= 1) + health_beforedamage = prev_health; + health_damagetime = time; + } + if (time - health_damagetime < 1) + { + float health_damagealpha = 1 - (time - health_damagetime)*(time - health_damagetime); + HUD_Panel_DrawProgressBar(pos + health_offset, mySize, autocvar_hud_panel_healtharmor_progressbar_health, health_beforedamage/maxhealth, is_vertical, health_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha * health_damagealpha, DRAWFLAG_NORMAL); + } + } + prev_health = health; + + 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); + } } - if(autocvar_hud_panel_healtharmor_text) - { - drawpic_aspect_skin(picpos, leftname, '0.4 0.4 0' * mySize_x, '1 1 1', leftalpha * panel_fg_alpha, DRAWFLAG_NORMAL); - drawstring_aspect(numpos, ftos(leftcnt), eX * 0.5 * mySize_x + eY * 0.25 * mySize_x, HUD_Get_Num_Color(leftcnt, leftmax), panel_fg_alpha, DRAWFLAG_NORMAL); - } + HUD_Panel_DrawProgressBar(pos + health_offset, mySize, autocvar_hud_panel_healtharmor_progressbar_health, p_health/maxhealth, is_vertical, health_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha * pain_health_alpha, DRAWFLAG_NORMAL); } + if(autocvar_hud_panel_healtharmor_text) + DrawNumIcon(pos + health_offset, mySize, health, "health", is_vertical, health_iconalign, HUD_Get_Num_Color(health, maxhealth), 1); + } - if(rightactive) + if(armor) + { + if(autocvar_hud_panel_healtharmor_progressbar) { - barpos = pos + eX * 0.5 * mySize_x; - if(baralign == 0 || baralign == 3) { // left align - barflip = 0; - } else { // right align - barflip = 1; - } - - if(iconalign == 0 || iconalign == 3) { // up align - picpos = pos + eX * 0.05 * mySize_x + eX * 0.5 * mySize_x; - numpos = pos + eY * 0.4 * mySize_x + eX * 0.5 * mySize_x; - } else { // down align - picpos = pos + eX * 0.05 * mySize_x + eY * (mySize_y - 0.65 * mySize_x) + eX * 0.5 * mySize_x; - numpos = pos + eY * mySize_y - eY * 0.25 * mySize_x + eX * 0.5 * mySize_x; - } - - if(progressbar) + HUD_Panel_GetProgressBarColor(armor); + float p_armor; + p_armor = armor; + if (autocvar_hud_panel_healtharmor_progressbar_gfx) { - HUD_Panel_GetProgressBarColorForString(rightname); - HUD_Panel_DrawProgressBar(barpos, barsize, rightprogressname, 1, barflip, min(1, rightcnt/rightmax), progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); + if (autocvar_hud_panel_healtharmor_progressbar_gfx_smooth > 0) + { + if (fabs(prev_armor - armor) >= autocvar_hud_panel_healtharmor_progressbar_gfx_smooth) + { + if (time - old_p_armortime < 1) + old_p_armor = prev_p_armor; + else + old_p_armor = prev_armor; + old_p_armortime = time; + } + if (time - old_p_armortime < 1) + { + p_armor += (old_p_armor - armor) * (1 - (time - old_p_armortime)); + prev_p_armor = p_armor; + } + } + if (autocvar_hud_panel_healtharmor_progressbar_gfx_damage > 0) + { + if (prev_armor - armor >= autocvar_hud_panel_healtharmor_progressbar_gfx_damage) + { + if (time - armor_damagetime >= 1) + armor_beforedamage = prev_armor; + armor_damagetime = time; + } + if (time - armor_damagetime < 1) + { + float armor_damagealpha = 1 - (time - armor_damagetime)*(time - armor_damagetime); + HUD_Panel_DrawProgressBar(pos + armor_offset, mySize, autocvar_hud_panel_healtharmor_progressbar_armor, armor_beforedamage/maxarmor, is_vertical, armor_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha * armor_damagealpha, DRAWFLAG_NORMAL); + } + } + prev_armor = armor; } - if(autocvar_hud_panel_healtharmor_text) - { - drawpic_aspect_skin(picpos, rightname, '0.4 0.4 0' * mySize_x, '1 1 1', rightalpha * panel_fg_alpha, DRAWFLAG_NORMAL); - drawstring_aspect(numpos, ftos(rightcnt), eX * 0.5 * mySize_x + eY * 0.25 * mySize_x, HUD_Get_Num_Color(rightcnt, rightmax), panel_fg_alpha, DRAWFLAG_NORMAL); - } + HUD_Panel_DrawProgressBar(pos + armor_offset, mySize, autocvar_hud_panel_healtharmor_progressbar_armor, p_armor/maxarmor, is_vertical, armor_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); } + if(autocvar_hud_panel_healtharmor_text) + DrawNumIcon(pos + armor_offset, mySize, armor, "armor", is_vertical, armor_iconalign, HUD_Get_Num_Color(armor, maxarmor), 1); + } - if(fuel) - { - barpos = pos; - barsize = eX * 0.05 * mySize_x + eY * mySize_y; - HUD_Panel_GetProgressBarColor(fuel); - HUD_Panel_DrawProgressBar(barpos, barsize, "progressbar", 1, mod(baralign, 2), min(1, fuel/100), progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha * 0.8, DRAWFLAG_NORMAL); - } + if(fuel) + { + if (is_vertical) + mySize_x *= 0.2 / 2; //if vertical always halve x to not cover too much numbers with 3 digits + else + mySize_y *= 0.2; + if (panel_ar >= 4) + mySize_x *= 2; //restore full panel size + else if (panel_ar < 1/4) + mySize_y *= 2; //restore full panel size + HUD_Panel_GetProgressBarColor(fuel); + HUD_Panel_DrawProgressBar(pos, mySize, "progressbar", fuel/100, is_vertical, fuel_baralign, progressbar_color, panel_fg_alpha * 0.8, DRAWFLAG_NORMAL); } } - drawfont = hud_font; } // Notification area (#4) @@ -2680,7 +1519,7 @@ void HUD_KillNotify(string s1, string s2, string s3, float type, float msg) // s alsoprint = (autocvar_hud_panel_notify_print || !panel_enabled); // print message to console if: notify panel disabled, or cvar to do so enabled gentle = (autocvar_cl_gentle || autocvar_cl_gentle_messages); - if ((msg == MSG_SUICIDE || msg == MSG_KILL || msg == MSG_KILL_ACTION) && gametype == GAME_CTS) // selfkill isn't interesting in CTS and only spams up the notify panel + if ((msg == MSG_SUICIDE || msg == MSG_KILL || msg == MSG_KILL_ACTION) && gametype == MAPINFO_TYPE_CTS) // selfkill isn't interesting in CTS and only spams up the notify panel return; if(msg == MSG_SUICIDE) { @@ -2692,47 +1531,43 @@ void HUD_KillNotify(string s1, string s2, string s3, float type, float msg) // s } else if (type == DEATH_KILL) { HUD_KillNotify_Push(s1, "", 0, DEATH_KILL); if (alsoprint) - print ("^1",s1, "^1 couldn't take it anymore\n"); + print (sprintf(_("^1%s^1 couldn't take it anymore\n"), s1)); } else if (type == DEATH_ROT) { HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); if (alsoprint) - print ("^1",s1, "^1 died\n"); + print (sprintf(_("^1%s^1 died\n"), s1)); } else if (type == DEATH_NOAMMO) { HUD_KillNotify_Push(s1, "", 0, DEATH_NOAMMO); if (alsoprint) - print ("^7",s1, "^7 committed suicide. What's the point of living without ammo?\n"); + print (sprintf(_("^7%s^7 committed suicide. What's the point of living without ammo?\n"), s1)); } else if (type == DEATH_CAMP) { HUD_KillNotify_Push(s1, "", 0, DEATH_CAMP); if (alsoprint) - print ("^1",s1, "^1 thought they found a nice camping ground\n"); + print (sprintf(_("^1%s^1 thought they found a nice camping ground\n"), s1)); } else if (type == KILL_TEAM_RED || type == KILL_TEAM_BLUE) { HUD_KillNotify_Push(s1, "", 0, type); if (alsoprint) - print ("^1",s1, "^1 didn't become friends with the Lord of Teamplay\n"); + print (sprintf(_("^1%s^1 didn't become friends with the Lord of Teamplay\n"), s1)); } else if (type == DEATH_CHEAT) { HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); if (alsoprint) - print ("^1",s1, "^1 unfairly eliminated themself\n"); + print (sprintf(_("^1%s^1 unfairly eliminated themself\n"), s1)); } else if (type == DEATH_FIRE) { HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); if (alsoprint) - print ("^1",s1, "^1 burned to death\n"); + print (sprintf(_("^1%s^1 burned to death\n"), s1)); } else if (type != DEATH_TEAMCHANGE && type != DEATH_QUIET) { HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); if (alsoprint) - print ("^1",s1, "^1 couldn't resist the urge to self-destruct\n"); + print (sprintf(_("^1%s^1 couldn't resist the urge to self-destruct\n"), s1)); } if (stof(s2) > 2) // killcount > 2 - print ("^1",s1,"^1 ended it all after a ",s2," kill spree\n"); + print (sprintf(_("^1%s^1 ended it all after a %d kill spree\n"), s1, stof(s2))); } else if(msg == MSG_KILL) { w = DEATH_WEAPONOF(type); if(WEP_VALID(w)) { - if((w == WEP_CAMPINGRIFLE || w == WEP_MINSTANEX) && type & HITTYPE_HEADSHOT) // all headshot weapons go here - HUD_KillNotify_Push(s1, s2, 1, DEATH_HEADSHOT); - else - HUD_KillNotify_Push(s1, s2, 1, type); - + HUD_KillNotify_Push(s1, s2, 1, type); if (alsoprint) print("^1", sprintf(Weapon_KillMessage(type), strcat(s2, "^1"), strcat(s1, "^1")), "\n"); // default order: victim, killer } @@ -2741,112 +1576,124 @@ void HUD_KillNotify(string s1, string s2, string s3, float type, float msg) // s if(alsoprint) { if(gentle) { - print ("^1", s1, "^1 took action against a team mate\n"); + print (sprintf(_("^1%s^1 took action against a team mate\n"), s1)); } else { - print ("^1", s1, "^1 mows down a team mate\n"); + print (sprintf(_("^1%s^1 mows down a team mate\n"), s1)); } } if (stof(s2) > 2 && type == KILL_TEAM_SPREE) { if(gentle) - print ("^1",s1,"^1 ended a ",s3," scoring spree by going against a team mate\n"); + print (sprintf(_("^1%s^1 ended a %d scoring spree by going against a team mate\n"), s1, stof(s3))); else - print ("^1",s1,"^1 ended a ",s3," kill spree by killing a team mate\n"); + print (sprintf(_("^1%s^1 ended a %d kill spree by killing a team mate\n"), s1, stof(s3))); } else if (stof(s2) > 2) { if(gentle) - print ("^1",s1,"'s ^1",s3," scoring spree was ended by a team mate!\n"); + print (sprintf(_("^1%s^1's %s scoring spree was ended by a team mate!\n"), s1, stof(s3))); else - print ("^1",s1,"'s ^1",s3," kill spree was ended by a team mate!\n"); + print (sprintf(_("^1%s^1's %s kill spree was ended by a team mate!\n"), s1, stof(s3))); } } else if(type == KILL_FIRST_BLOOD) - print("^1",s1, "^1 drew first blood", "\n"); + print(sprintf(_("^1%s^1 drew first blood\n"), s1)); else if (type == DEATH_TELEFRAG) { HUD_KillNotify_Push(s1, s2, 1, DEATH_TELEFRAG); if(gentle) - print ("^1",s2, "^1 tried to occupy ", s1, "^1's teleport destination space\n"); + print (sprintf(_("^1%s^1 tried to occupy %s^1's teleport destination space\n"), s2, s1)); else - print ("^1",s2, "^1 was telefragged by ", s1, "\n"); + print (sprintf(_("^1%s^1 was telefragged by %s\n"), s2, s1)); } else if (type == DEATH_DROWN) { HUD_KillNotify_Push(s1, s2, 1, DEATH_DROWN); if(alsoprint) - print ("^1",s2, "^1 was drowned by ", s1, "\n"); + print (sprintf(_("^1%s^1 was drowned by %s\n"), s2, s1)); } else if (type == DEATH_SLIME) { HUD_KillNotify_Push(s1, s2, 1, DEATH_SLIME); if(alsoprint) - print ("^1",s2, "^1 was slimed by ", s1, "\n"); + print (sprintf(_("^1%s^1 was slimed by %s\n"), s2, s1)); } else if (type == DEATH_LAVA) { HUD_KillNotify_Push(s1, s2, 1, DEATH_LAVA); if(alsoprint) - print ("^1",s2, "^1 was cooked by ", s1, "\n"); + print (sprintf(_("^1%s^1 was cooked by %s\n"), s2, s1)); } else if (type == DEATH_FALL) { HUD_KillNotify_Push(s1, s2, 1, DEATH_FALL); if(alsoprint) - print ("^1",s2, "^1 was grounded by ", s1, "\n"); + print (sprintf(_("^1%s^1 was grounded by %s\n"), s2, s1)); } else if (type == DEATH_SHOOTING_STAR) { HUD_KillNotify_Push(s1, s2, 1, DEATH_SHOOTING_STAR); if(alsoprint) - print ("^1",s2, "^1 was shot into space by ", s1, "\n"); + print (sprintf(_("^1%s^1 was shot into space by %s\n"), s2, s1)); } else if (type == DEATH_SWAMP) { HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); if(alsoprint) - print ("^1",s2, "^1 was conserved by ", s1, "\n"); + print (sprintf(_("^1%s^1 was conserved by %s\n"), s2, s1)); } else if (type == DEATH_HURTTRIGGER) { HUD_KillNotify_Push(s1, s2, 1, DEATH_HURTTRIGGER); if(alsoprint) - print("^1",s2, "^1 was thrown into a world of hurt by ", s1, "\n"); - } else if(type == DEATH_SBCRUSH) { + print(sprintf(_("^1%s^1 was thrown into a world of hurt by %s\n"), s2, s1)); + } else if(type == DEATH_VHCRUSH) { HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); if(alsoprint) - print ("^1",s2, "^1 was crushed by ^1", s1, "\n"); + print (sprintf(_("^1%s^1 was crushed by %s\n"), s2, s1)); } else if(type == DEATH_SBMINIGUN) { HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); if(alsoprint) - print ("^1",s2, "^1 got shredded by ^1", s1, "\n"); + print (sprintf(_("^1%s^1 got shredded by %s\n"), s2, s1)); } else if(type == DEATH_SBROCKET) { HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); if(alsoprint) - print ("^1",s2, "^1 was blased to bits by ^1", s1, "\n"); + print (sprintf(_("^1%s^1 was blasted to bits by %s\n"), s2, s1)); } else if(type == DEATH_SBBLOWUP) { HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); if(alsoprint) - print ("^1",s2, "^1 got caught in the destruction of ^1", s1, "'s vehicle\n"); + print (sprintf(_("^1%s^1 got caught in the destruction of %s^1's vehicle\n"), s2, s1)); } else if(type == DEATH_WAKIGUN) { HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); if(alsoprint) - print ("^1",s2, "^1 was bolted down by ^1", s1, "\n"); + print (sprintf(_("^1%s^1 was bolted down by %s\n"), s2, s1)); } else if(type == DEATH_WAKIROCKET) { HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); if(alsoprint) - print ("^1",s2, "^1 could find no shelter from ^1", s1, "'s rockets\n"); + print (sprintf(_("^1%s^1 could find no shelter from %s^1's rockets\n"), s2, s1)); } else if(type == DEATH_WAKIBLOWUP) { HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); if(alsoprint) - print ("^1",s2, "^1 dies when ^1", s1, "'s wakizashi dies.\n"); + print (sprintf(_("^1%s^1 dies when %s^1's wakizashi dies.\n"), s2, s1)); + } else if(type == DEATH_RAPTOR_CANNON) { + HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); + if(alsoprint) + print (sprintf(_("^1%s^1 nailed to hell by %s\n"), s2, s1)); + } else if(type == DEATH_RAPTOR_BOMB) { + HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); + if(alsoprint) + print (sprintf(_("^1%s^1 cluster crushed by %s\n"), s2, s1)); + } else if(type == DEATH_RAPTOR_DEATH) { + HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); + if(alsoprint) + print (sprintf(_("^1%s^1 dies when %s^1's raptor dies.\n"), s2, s1)); } else if(type == DEATH_TURRET) { HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); if(alsoprint) - print ("^1",s2, "^1 was pushed into the line of fire by ^1", s1, "\n"); + print (sprintf(_("^1%s^1 was pushed into the line of fire by %s\n"), s2, s1)); } else if(type == DEATH_TOUCHEXPLODE) { HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); if(alsoprint) - print ("^1",s2, "^1 was pushed into an accident by ^1", s1, "\n"); + print (sprintf(_("^1%s^1 was pushed into an accident by %s\n"), s2, s1)); } else if(type == DEATH_CHEAT) { HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); if(alsoprint) - print ("^1",s2, "^1 was unfairly eliminated by ^1", s1, "\n"); + print (sprintf(_("^1%s^1 was unfairly eliminated by %s\n"), s2, s1)); } else if (type == DEATH_FIRE) { HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); if(alsoprint) - print ("^1",s2, "^1 was burnt to death by ^1", s1, "\n"); + print (sprintf(_("^1%s^1 was burnt to death by %s\n"), s2, s1)); } else if (type == DEATH_CUSTOM) { HUD_KillNotify_Push(s1, s2, 1, DEATH_CUSTOM); if(alsoprint) @@ -2858,54 +1705,54 @@ void HUD_KillNotify(string s1, string s2, string s3, float type, float msg) // s } else { HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); if(alsoprint) - print ("^1",s2, "^1 was fragged by ", s1, "\n"); + print (sprintf(_("^1%s^1 was fragged by %s\n"), s2, s1)); } } else if(msg == MSG_SPREE) { if(type == KILL_END_SPREE) { if(gentle) - print ("^1",s1,"'s ^1", s2, " scoring spree was ended by ", s3, "\n"); + print (sprintf(_("^1%s^1's %s scoring spree was ended by %s\n"), s1, s2, s3)); else - print ("^1",s1,"'s ^1", s2, " kill spree was ended by ", s3, "\n"); + print (sprintf(_("^1%s^1's %s kill spree was ended by %s\n"), s1, s2, s3)); } else if(type == KILL_SPREE) { if(gentle) - print ("^1",s1,"^1 made ",s2," scores in a row\n"); + print (sprintf(_("^1%s^1 made %s scores in a row\n"), s1, s2)); else - print ("^1",s1,"^1 has ",s2," frags in a row\n"); + print (sprintf(_("^1%s^1 has %s frags in a row\n"), s1, s2)); } else if(type == KILL_SPREE_3) { if(gentle) - print (s1,"^7 made a ^1TRIPLE SCORE\n"); + print (sprintf(_("%s^7 made a ^1TRIPLE SCORE\n"), s1)); else - print (s1,"^7 made a ^1TRIPLE FRAG\n"); + print (sprintf(_("%s^7 made a ^1TRIPLE FRAG\n"), s1)); } else if(type == KILL_SPREE_5) { if(gentle) - print (s1,"^7 unleashes ^1SCORING RAGE\n"); + print (sprintf(_("%s^7 unleashes ^1SCORING RAGE\n"), s1)); else - print (s1,"^7 unleashes ^1RAGE\n"); + print (sprintf(_("%s^7 unleashes ^1RAGE\n"), s1)); } else if(type == KILL_SPREE_10) { if(gentle) - print (s1,"^7 made ^1TEN SCORES IN A ROW!\n"); + print (sprintf(_("%s^7 made ^1TEN SCORES IN A ROW!\n"), s1)); else - print (s1,"^7 starts the ^1MASSACRE!\n"); + print (sprintf(_("%s^7 starts the ^1MASSACRE!\n"), s1)); } else if(type == KILL_SPREE_15) { if(gentle) - print (s1,"^7 made ^1FIFTEEN SCORES IN A ROW!\n"); + print (sprintf(_("%s^7 made ^1FIFTEEN SCORES IN A ROW!\n"), s1)); else - print (s1,"^7 executes ^1MAYHEM!\n"); + print (sprintf(_("%s^7 executes ^1MAYHEM!\n"), s1)); } else if(type == KILL_SPREE_20) { if(gentle) - print (s1,"^7 made ^1TWENTY SCORES IN A ROW!\n"); + print (sprintf(_("%s^7 made ^1TWENTY SCORES IN A ROW!\n"), s1)); else - print (s1,"^7 is a ^1BERSERKER!\n"); + print (sprintf(_("%s^7 is a ^1BERSERKER!\n"), s1)); } else if(type == KILL_SPREE_25) { if(gentle) - print (s1,"^7 made ^1TWENTY FIFE SCORES IN A ROW!\n"); + print (sprintf(_("%s^7 made ^1TWENTY FIVE SCORES IN A ROW!\n"), s1)); else - print (s1,"^7 inflicts ^1CARNAGE!\n"); + print (sprintf(_("%s^7 inflicts ^1CARNAGE!\n"), s1)); } else if(type == KILL_SPREE_30) { if(gentle) - print (s1,"^7 made ^1THIRTY SCORES IN A ROW!\n"); + print (sprintf(_("%s^7 made ^1THIRTY SCORES IN A ROW!\n"), s1)); else - print (s1,"^7 unleashes ^1ARMAGEDDON!\n"); + print (sprintf(_("%s^7 unleashes ^1ARMAGEDDON!\n"), s1)); } } else if(msg == MSG_KILL_ACTION) { // wtf is this? isnt it basically the same as MSG_SUICIDE? if (type == DEATH_DROWN) { @@ -2913,49 +1760,94 @@ void HUD_KillNotify(string s1, string s2, string s3, float type, float msg) // s if(alsoprint) { if(gentle) - print ("^1",s1, "^1 was in the water for too long\n"); + print (sprintf(_("^1%s^1 was in the water for too long\n"), s1)); else - print ("^1",s1, "^1 drowned\n"); + print (sprintf(_("^1%s^1 drowned\n"), s1)); } } else if (type == DEATH_SLIME) { HUD_KillNotify_Push(s1, "", 0, DEATH_SLIME); if(alsoprint) - print ("^1",s1, "^1 was slimed\n"); + print (sprintf(_("^1%s^1 was slimed\n"), s1)); } else if (type == DEATH_LAVA) { HUD_KillNotify_Push(s1, "", 0, DEATH_LAVA); if(alsoprint) { if(gentle) - print ("^1",s1, "^1 found a hot place\n"); + print (sprintf(_("^1%s^1 found a hot place\n"), s1)); else - print ("^1",s1, "^1 turned into hot slag\n"); + print (sprintf(_("^1%s^1 turned into hot slag\n"), s1)); } } else if (type == DEATH_FALL) { HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); if(alsoprint) { if(gentle) - print ("^1",s1, "^1 tested gravity (and it worked)\n"); + print (sprintf(_("^1%s^1 tested gravity (and it worked)\n"), s1)); else - print ("^1",s1, "^1 hit the ground with a crunch\n"); + print (sprintf(_("^1%s^1 hit the ground with a crunch\n"), s1)); } } else if (type == DEATH_SHOOTING_STAR) { HUD_KillNotify_Push(s1, "", 0, DEATH_SHOOTING_STAR); if(alsoprint) - print ("^1",s1, "^1 became a shooting star\n"); + print (sprintf(_("^1%s^1 became a shooting star\n"), s1)); } else if (type == DEATH_SWAMP) { HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); if(alsoprint) { if(gentle) - print ("^1",s1, "^1 discovered a swamp\n"); + print (sprintf(_("^1%s^1 discovered a swamp\n"), s1)); else - print ("^1",s1, "^1 is now conserved for centuries to come\n"); + print (sprintf(_("^1%s^1 is now conserved for centuries to come\n"), s1)); } - } else if(type == DEATH_TURRET) { + } else if(DEATH_ISTURRET(type)) { HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); if(alsoprint) - print ("^1",s1, "^1 was mowed down by a turret \n"); + { + if(gentle) + print (sprintf(_("^1%s^1 ran into a turret\n"), s1)); + else + { + switch(type) + { + case DEATH_TURRET_EWHEEL: + print (sprintf(_("^1%s^1 was laserd down by a eWheel turret \n"), s1)); + break; + case DEATH_TURRET_FLAC: + print (sprintf(_("^1%s^1 got caught in the flac \n"), s1)); + break; + case DEATH_TURRET_MACHINEGUN: + print (sprintf(_("^1%s^1 was riddeld full of riddled by a machinegun turret \n"), s1)); + break; + case DEATH_TURRET_WALKER_GUN: + print (sprintf(_("^1%s^1 got served a led enrichment by a walker turret \n"), s1)); + break; + case DEATH_TURRET_WALKER_MEELE: + print (sprintf(_("^1%s^1 was impaled by a walker turret \n"), s1)); + break; + case DEATH_TURRET_WALKER_ROCKET: + print (sprintf(_("^1%s^1 was rocketed to hell by a walker turret \n"), s1)); + break; + case DEATH_TURRET_HELLION: + print (sprintf(_("^1%s^1 was blasted away hellion turret \n"), s1)); + break; + case DEATH_TURRET_HK: + print (sprintf(_("^1%s^1 could not hide from the hunter turret \n"), s1)); + break; + case DEATH_TURRET_MLRS: + print (sprintf(_("^1%s^1 got turned into smoldering gibs by a mlrs turret \n"), s1)); + break; + case DEATH_TURRET_PLASMA: + print (sprintf(_("^1%s^1 got served some superheated plasma from a plasma turret \n"), s1)); + break; + case DEATH_TURRET_PHASER: + print (sprintf(_("^1%s^1 was phased out \n"), s1)); + break; + case DEATH_TURRET_TESLA: + print (sprintf(_("^1%s^1 was electrocuted by a tesla turret \n"), s1)); + break; + } + } + } } else if (type == DEATH_CUSTOM) { HUD_KillNotify_Push(s1, "", 0, DEATH_CUSTOM); if(alsoprint) @@ -2967,51 +1859,51 @@ void HUD_KillNotify(string s1, string s2, string s3, float type, float msg) // s } else if(type == DEATH_TOUCHEXPLODE) { HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); if(alsoprint) - print ("^1",s1, "^1 died in an accident\n"); + print (sprintf(_("^1%s^1 died in an accident\n"), s1)); } else if(type == DEATH_CHEAT) { HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); if(alsoprint) - print ("^1",s1, "^1 was unfairly eliminated\n"); + print (sprintf(_("^1%s^1 was unfairly eliminated\n"), s1)); } else if(type == DEATH_FIRE) { HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); if(alsoprint) { if(gentle) - print ("^1",s1, "^1 felt a little hot\n"); + print (sprintf(_("^1%s^1 felt a little hot\n"), s1)); else - print ("^1",s1, "^1 burnt to death\n"); + print (sprintf(_("^1%s^1 burnt to death\n"), s1)); } } else { HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); if(alsoprint) { if(gentle) - print ("^1",s1, "^1 needs a restart\n"); + print (sprintf(_("^1%s^1 needs a restart\n"), s1)); else - print ("^1",s1, "^1 died\n"); + print (sprintf(_("^1%s^1 died\n"), s1)); } } } else if(msg == MSG_KILL_ACTION_SPREE) { if(gentle) - print ("^1",s1,"^1 needs a restart after a ",s2," scoring spree\n"); + print (sprintf(_("^1%s^1 needs a restart after a %d scoring spree\n"), s1, stof(s2))); else - print ("^1",s1,"^1 died with a ",s2," kill spree\n"); + print (sprintf(_("^1%s^1 died with a %d kill spree\n"), s1, stof(s2))); } else if(msg == MSG_INFO) { if(type == INFO_GOTFLAG) { // here, s2 is the flag name HUD_KillNotify_Push(s1, s2, 0, INFO_GOTFLAG); - print(s1, "^7 got the ", s2, "\n"); + print(sprintf(_("%s^7 got the %s\n"), s1, s2)); } else if(type == INFO_LOSTFLAG) { HUD_KillNotify_Push(s1, s2, 0, INFO_LOSTFLAG); - print(s1, "^7 lost the ", s2, "\n"); + print(sprintf(_("%s^7 lost the %s\n"), s1, s2)); } else if(type == INFO_PICKUPFLAG) { HUD_KillNotify_Push(s1, s2, 0, INFO_GOTFLAG); - print(s1, "^7 picked up the ", s2, "\n"); + print(sprintf(_("%s^7 picked up the %s\n"), s1, s2)); } else if(type == INFO_RETURNFLAG) { HUD_KillNotify_Push(s1, s2, 0, INFO_RETURNFLAG); - print(s1, "^7 returned the ", s2, "\n"); + print(sprintf(_("%s^7 returned the %s\n"), s1, s2)); } else if(type == INFO_CAPTUREFLAG) { HUD_KillNotify_Push(s1, s2, 0, INFO_CAPTUREFLAG); - print(s1, "^7 captured the ", s2, s3, "\n"); + print(sprintf(_("%s^7 captured the %s%s\n"), s1, s2, s3)); } } else if(msg == MSG_RACE) { if(type == RACE_SERVER_RECORD) { @@ -3030,112 +1922,114 @@ void HUD_KillNotify(string s1, string s2, string s3, float type, float msg) // s if(type == KA_PICKUPBALL) { HUD_KillNotify_Push(s1, s2, 0, KA_PICKUPBALL); if(alsoprint) - print (s1, "^7 has picked up the ball!\n"); + print (sprintf(_("%s^7 has picked up the ball!\n"), s1)); } else if(type == KA_DROPBALL) { HUD_KillNotify_Push(s1, s2, 0, KA_DROPBALL); if(alsoprint) - print(s1, "^7 has dropped the ball!\n"); + print(sprintf(_("%s^7 has dropped the ball!\n"), s1)); } } } -#define DAMAGE_CENTERPRINT_SPACER NEWLINES - -void HUD_Centerprint(string s1, string s2, float type, float msg) +void HUD_KillCenterprint(string s1, string s2, float type, float msg) { float gentle; gentle = (autocvar_cl_gentle || autocvar_cl_gentle_messages); if(msg == MSG_SUICIDE) { if (type == DEATH_TEAMCHANGE) { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "You are now on: ", s1)); + centerprint_hud(sprintf(_("You are now on: %s"), s1)); } else if (type == DEATH_AUTOTEAMCHANGE) { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "You have been moved into a different team to improve team balance\nYou are now on: ", s1)); + centerprint_hud(sprintf(_("You have been moved into a different team to improve team balance\nYou are now on: %s"), s1)); } else if (type == DEATH_CAMP) { if(gentle) - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1Reconsider your tactics, camper!")); + centerprint_hud(_("^1Reconsider your tactics, camper!")); else - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1Die camper!")); + centerprint_hud(_("^1Die camper!")); } else if (type == DEATH_NOAMMO) { if(gentle) - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1You are reinserted into the game for running out of ammo...")); + centerprint_hud(_("^1You are reinserted into the game for running out of ammo...")); else - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1You were killed for running out of ammo...")); + centerprint_hud(_("^1You were killed for running out of ammo...")); } else if (type == DEATH_ROT) { if(gentle) - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1You need to preserve your health")); + centerprint_hud(_("^1You need to preserve your health")); else - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1You grew too old without taking your medicine")); + centerprint_hud(_("^1You grew too old without taking your medicine")); } else if (type == KILL_TEAM_RED || type == KILL_TEAM_BLUE) { if(gentle) - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1Don't go against team mates!")); + centerprint_hud(_("^1Don't go against team mates!")); else - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1Don't shoot your team mates!")); + centerprint_hud(_("^1Don't shoot your team mates!")); } else if (type == DEATH_QUIET) { // do nothing } else { // generic message if(gentle) - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1You need to be more careful!")); + centerprint_hud(_("^1You need to be more careful!")); else - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1You killed your own dumb self!")); + centerprint_hud(_("^1You killed your own dumb self!")); } } else if(msg == MSG_KILL) { if (type == KILL_TEAM_RED || type == KILL_TEAM_BLUE) { if(gentle) { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1Moron! You went against", s1, ",a team mate!")); + centerprint_hud(sprintf(_("^1Moron! You went against ^7%s^1, a team mate!"), s1)); } else { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1Moron! You fragged ", s1, ", a team mate!")); + centerprint_hud(sprintf(_("^1Moron! You fragged ^7%s^1, a team mate!"), s1)); } } else if (type == KILL_FIRST_BLOOD) { if(gentle) { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1First score")); + centerprint_hud(_("^1First score")); } else { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1First blood")); + centerprint_hud(_("^1First blood")); } } else if (type == KILL_FIRST_VICTIM) { if(gentle) { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1First casualty")); + centerprint_hud(_("^1First casualty")); } else { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1First victim")); + centerprint_hud(_("^1First victim")); } } else if (type == KILL_TYPEFRAG) { // s2 contains "advanced kill messages" such as ping, handicap... if(gentle) { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1You scored against ^7", s1, "^1 who was typing!", s2)); + centerprint_hud(strcat(sprintf(_("^1You scored against ^7%s^1 who was typing!"), s1), s2)); } else { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1You typefragged ^7", s1, s2)); + centerprint_hud(strcat(sprintf(_("^1You typefragged ^7%s"), s1), s2)); } } else if (type == KILL_TYPEFRAGGED) { if(gentle) { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1You were scored against by ^7", s1, "^1 while you were typing!", s2)); + centerprint_hud(strcat(sprintf(_("^1You were scored against by ^7%s^1 while you were typing!"), s1), s2)); } else { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1You were typefragged by ^7", s1, s2)); + centerprint_hud(strcat(sprintf(_("^1You were typefragged by ^7%s"), s1), s2)); } } else if (type == KILL_FRAG) { if(gentle) { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^4You scored against ^7", s1, s2)); + centerprint_hud(strcat(sprintf(_("^4You scored against ^7%s"), s1), s2)); } else { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^4You fragged ^7", s1, s2)); + centerprint_hud(strcat(sprintf(_("^4You fragged ^7%s"), s1), s2)); } } else { // generic message if(gentle) { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1You were scored against by ^7", s1, s2)); + centerprint_hud(strcat(sprintf(_("^1You were scored against by ^7%s"), s1), s2)); } else { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1You were fragged by ^7", s1, s2)); + centerprint_hud(strcat(sprintf(_("^1You were fragged by ^7%s"), s1), s2)); } } } else if(msg == MSG_KILL_ACTION) { // TODO: invent more centerprints here? - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1Watch your step!")); + centerprint_hud(_("^1Watch your step!")); } } void HUD_Notify (void) { - if(!autocvar_hud_panel_notify && !autocvar__hud_configure) - return; + if(!autocvar__hud_configure) + { + if(!autocvar_hud_panel_notify) return; + } + else + hud_configure_active_panel = HUD_PANEL_NOTIFY; - active_panel = HUD_PANEL_NOTIFY; HUD_Panel_UpdateCvars(notify); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -3152,7 +2046,8 @@ void HUD_Notify (void) height = mySize_y/entries; vector fontsize; - fontsize = '0.5 0.5 0' * height; + float fontheight = height * autocvar_hud_panel_notify_fontsize; + fontsize = '0.5 0.5 0' * fontheight; float a; float when; @@ -3167,7 +2062,7 @@ void HUD_Notify (void) float width_attacker; string attacker, victim; - float i, j, w, step, limit; + float i, j, w, type, step, limit; if(autocvar_hud_panel_notify_flip) //order items from the top down { i = 0; @@ -3189,8 +2084,8 @@ void HUD_Notify (void) a = i; else // inverse order a = entries - 1 - i; - attacker = textShortenToWidth(strcat("Player", ftos(a+1)), 0.48 * mySize_x - height, fontsize, stringwidth_colors); - victim = textShortenToWidth(strcat("Player", ftos(a+2)), 0.48 * mySize_x - height, fontsize, stringwidth_colors); + attacker = textShortenToWidth(sprintf(_("Player %d"), a+1), 0.48 * mySize_x - height, fontsize, stringwidth_colors); + victim = textShortenToWidth(sprintf(_("Player %d"), a+2), 0.48 * mySize_x - height, fontsize, stringwidth_colors); s = strcat("weapon", get_weaponinfo(WEP_FIRST + mod(floor(a*2.4), WEP_LAST)).netname); a = bound(0, (when - a) / 4, 1); goto hud_config_notifyprint; @@ -3216,63 +2111,63 @@ void HUD_Notify (void) s = ""; - w = -1; - w = DEATH_WEAPONOF(killnotify_deathtype[j]); + type = killnotify_deathtype[j]; + w = DEATH_WEAPONOF(type); // TODO: maybe print in team colors? // // Y [used by] X if(killnotify_actiontype[j] == 0) { - if(killnotify_deathtype[j] == DEATH_GENERIC) + if(type == DEATH_GENERIC) { s = "notify_death"; } - else if(killnotify_deathtype[j] == DEATH_NOAMMO) + else if(type == DEATH_NOAMMO) { s = "notify_outofammo"; } - else if(killnotify_deathtype[j] == DEATH_KILL) + else if(type == DEATH_KILL) { s = "notify_selfkill"; } - else if(killnotify_deathtype[j] == DEATH_CAMP) + else if(type == DEATH_CAMP) { s = "notify_camping"; } - else if(killnotify_deathtype[j] == KILL_TEAM_RED) + else if(type == KILL_TEAM_RED) { s = "notify_teamkill_red"; } - else if(killnotify_deathtype[j] == KILL_TEAM_BLUE) + else if(type == KILL_TEAM_BLUE) { s = "notify_teamkill_blue"; } - else if(killnotify_deathtype[j] == DEATH_DROWN) + else if(type == DEATH_DROWN) { s = "notify_water"; } - else if(killnotify_deathtype[j] == DEATH_SLIME) + else if(type == DEATH_SLIME) { s = "notify_slime"; } - else if(killnotify_deathtype[j] == DEATH_LAVA) + else if(type == DEATH_LAVA) { s = "notify_lava"; } - else if(killnotify_deathtype[j] == DEATH_FALL) + else if(type == DEATH_FALL) { s = "notify_fall"; } - else if(killnotify_deathtype[j] == DEATH_SHOOTING_STAR) + else if(type == DEATH_SHOOTING_STAR) { s = "notify_shootingstar"; } - else if(killnotify_deathtype[j] == DEATH_HURTTRIGGER || killnotify_deathtype[j] == DEATH_CUSTOM) + else if(type == DEATH_HURTTRIGGER || type == DEATH_CUSTOM) { s = "notify_death"; } - else if(killnotify_deathtype[j] == INFO_GOTFLAG) + else if(type == INFO_GOTFLAG) { if(killnotify_victims[j] == "^1RED^7 flag") { @@ -3283,7 +2178,7 @@ void HUD_Notify (void) s = "notify_blue_taken"; } } - else if(killnotify_deathtype[j] == INFO_RETURNFLAG) + else if(type == INFO_RETURNFLAG) { if(killnotify_victims[j] == "^1RED^7 flag") { @@ -3294,7 +2189,7 @@ void HUD_Notify (void) s = "notify_blue_returned"; } } - else if(killnotify_deathtype[j] == INFO_LOSTFLAG) + else if(type == INFO_LOSTFLAG) { if(killnotify_victims[j] == "^1RED^7 flag") { @@ -3305,7 +2200,7 @@ void HUD_Notify (void) s = "notify_blue_lost"; } } - else if(killnotify_deathtype[j] == INFO_CAPTUREFLAG) + else if(type == INFO_CAPTUREFLAG) { if(killnotify_victims[j] == "^1RED^7 flag") { @@ -3316,17 +2211,17 @@ void HUD_Notify (void) s = "notify_blue_captured"; } } - else if(killnotify_deathtype[j] == KA_DROPBALL) + else if(type == KA_DROPBALL) { s = "notify_balldropped"; } - else if(killnotify_deathtype[j] == KA_PICKUPBALL) + else if(type == KA_PICKUPBALL) { s = "notify_ballpickedup"; } attacker = textShortenToWidth(killnotify_attackers[j], 0.48 * mySize_x - height, fontsize, stringwidth_colors); - pos_attacker = pos + eX * (0.52 * mySize_x + height) + eY * (0.5 * fontsize_y + i * height); + pos_attacker = pos + eX * (0.52 * mySize_x + height) + eY * ((0.5 * fontsize_y + i * height) + (0.5 * (height - fontheight))); weap_pos = pos + eX * 0.5 * mySize_x - eX * height + eY * i * height; if(s != "") @@ -3338,72 +2233,72 @@ void HUD_Notify (void) // X [did action to] Y else { - if(killnotify_deathtype[j] & HITTYPE_SECONDARY && w == WEP_LASER) + if(type & HITTYPE_SECONDARY && w == WEP_LASER) { s = "notify_melee_laser"; } - else if(killnotify_deathtype[j] & HITTYPE_SECONDARY && w == WEP_SHOTGUN) + else if(type & HITTYPE_SECONDARY && w == WEP_SHOTGUN) { s = "notify_melee_shotgun"; } + else if(type & HITTYPE_HEADSHOT && (w == WEP_RIFLE || w == WEP_MINSTANEX)) // all headshot weapons go here + { + s = "notify_headshot"; + } else if(WEP_VALID(w)) { self = get_weaponinfo(w); s = strcat("weapon", self.netname); } - else if(killnotify_deathtype[j] == KILL_TEAM_RED) + else if(type == KILL_TEAM_RED) { s = "notify_teamkill_red"; } - else if(killnotify_deathtype[j] == KILL_TEAM_BLUE) + else if(type == KILL_TEAM_BLUE) { s = "notify_teamkill_red"; } - else if(killnotify_deathtype[j] == DEATH_TELEFRAG) + else if(type == DEATH_TELEFRAG) { s = "notify_telefrag"; } - else if(killnotify_deathtype[j] == DEATH_DROWN) + else if(type == DEATH_DROWN) { s = "notify_water"; } - else if(killnotify_deathtype[j] == DEATH_SLIME) + else if(type == DEATH_SLIME) { s = "notify_slime"; } - else if(killnotify_deathtype[j] == DEATH_LAVA) + else if(type == DEATH_LAVA) { s = "notify_lava"; } - else if(killnotify_deathtype[j] == DEATH_FALL) + else if(type == DEATH_FALL) { s = "notify_fall"; } - else if(killnotify_deathtype[j] == DEATH_SHOOTING_STAR) + else if(type == DEATH_SHOOTING_STAR) { s = "notify_shootingstar"; } - else if(killnotify_deathtype[j] == DEATH_HURTTRIGGER || killnotify_deathtype[j] == DEATH_CUSTOM) // DEATH_CUSTOM is also void, right? + else if(type == DEATH_HURTTRIGGER || type == DEATH_CUSTOM) // DEATH_CUSTOM is also void, right? { s = "notify_void"; } - else if(killnotify_deathtype[j] == DEATH_HEADSHOT) - { - s = "notify_headshot"; - } - else if(killnotify_deathtype[j] == RACE_SERVER_RECORD) + else if(type == RACE_SERVER_RECORD) { s = "race_newrecordserver"; } - else if(killnotify_deathtype[j] == RACE_NEW_RANK) + else if(type == RACE_NEW_RANK) { s = "race_newrankyellow"; } - else if(killnotify_deathtype[j] == RACE_NEW_TIME) + else if(type == RACE_NEW_TIME) { s = "race_newtime"; } - else if(killnotify_deathtype[j] == RACE_FAIL) + else if(type == RACE_FAIL) { s = "race_newfail"; } @@ -3412,8 +2307,8 @@ void HUD_Notify (void) victim = textShortenToWidth(killnotify_victims[j], 0.48 * mySize_x - height, fontsize, stringwidth_colors); :hud_config_notifyprint width_attacker = stringwidth(attacker, TRUE, fontsize); - pos_attacker = pos + eX * (0.48 * mySize_x - height - width_attacker) + eY * (0.5 * fontsize_y + i * height); - pos_victim = pos + eX * (0.52 * mySize_x + height) + eY * (0.5 * fontsize_y + i * height); + pos_attacker = pos + eX * (0.48 * mySize_x - height - width_attacker) + eY * ((0.5 * fontsize_y + i * height) + (0.5 * (height - fontheight))); + pos_victim = pos + eX * (0.52 * mySize_x + height) + eY * ((0.5 * fontsize_y + i * height) + (0.5 * (height - fontheight))); weap_pos = pos + eX * 0.5 * mySize_x - eX * height + eY * i * height; if(s != "") @@ -3435,20 +2330,20 @@ string seconds_tostring(float sec) minutes = floor(sec / 60); sec -= minutes * 60; - - string s; - s = ftos(100 + sec); - - return strcat(ftos(minutes), ":", substring(s, 1, 3)); + return sprintf("%d:%02d", minutes, sec); } void HUD_Timer(void) { - if(!autocvar_hud_panel_timer && !autocvar__hud_configure) - return; + if(!autocvar__hud_configure) + { + if(!autocvar_hud_panel_timer) return; + } + else + hud_configure_active_panel = HUD_PANEL_TIMER; - active_panel = HUD_PANEL_TIMER; HUD_Panel_UpdateCvars(timer); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -3490,20 +2385,43 @@ void HUD_Timer(void) timer = seconds_tostring(timeleft); } - drawfont = hud_bigfont; drawstring_aspect(pos, timer, mySize, timer_color, panel_fg_alpha, DRAWFLAG_NORMAL); - drawfont = hud_font; } // Radar (#6) // void HUD_Radar(void) { - if ((autocvar_hud_panel_radar == 0 || (autocvar_hud_panel_radar != 2 && !teamplay)) && !autocvar__hud_configure) - return; + if (!autocvar__hud_configure) + { + if (hud_panel_radar_maximized) + { + if (!hud_draw_maximized) return; + } + else + { + if (autocvar_hud_panel_radar == 0) return; + if (autocvar_hud_panel_radar != 2 && !teamplay) return; + } + } + else + hud_configure_active_panel = HUD_PANEL_RADAR; - active_panel = HUD_PANEL_RADAR; HUD_Panel_UpdateCvars(radar); + HUD_Panel_ApplyFadeAlpha(); + + if (hud_panel_radar_maximized && !autocvar__hud_configure) + { + panel_size = autocvar_hud_panel_radar_maximized_size; + panel_size_x = bound(0.2, panel_size_x, 1) * vid_conwidth; + panel_size_y = bound(0.2, panel_size_y, 1) * vid_conheight; + panel_pos_x = (vid_conwidth - panel_size_x) / 2; + panel_pos_y = (vid_conheight - panel_size_y) / 2; + + panel_bg = strcat(hud_skin_path, "/border_default"); // always use the default border when maximized + if(precache_pic(panel_bg) == "") { panel_bg = "gfx/hud/default/border_default"; } // fallback + } + vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -3515,9 +2433,8 @@ void HUD_Radar(void) mySize -= '2 2 0' * panel_bg_padding; } - local float color1, color2; // color already declared as a global in hud.qc - local vector rgb; - local entity tm; + float color2; + entity tm; float scale2d, normalsize, bigsize; float f; @@ -3575,8 +2492,8 @@ void HUD_Radar(void) c2 = rotate('1 0 0' * mi_min_x + '0 1 0' * mi_max_y, teamradar_angle * DEG2RAD); c3 = rotate('1 0 0' * mi_max_x + '0 1 0' * mi_min_y, teamradar_angle * DEG2RAD); span = '0 0 0'; - span_x = max4(c0_x, c1_x, c2_x, c3_x) - min4(c0_x, c1_x, c2_x, c3_x); - span_y = max4(c0_y, c1_y, c2_y, c3_y) - min4(c0_y, c1_y, c2_y, c3_y); + span_x = max(c0_x, c1_x, c2_x, c3_x) - min(c0_x, c1_x, c2_x, c3_x); + span_y = max(c0_y, c1_y, c2_y, c3_y) - min(c0_y, c1_y, c2_y, c3_y); // max-min distance must fit the radar in x=x, y=y bigsize = min( @@ -3596,9 +2513,6 @@ void HUD_Radar(void) f * mi_center + (1 - f) * view_origin); - color1 = GetPlayerColor(player_localentnum-1); - rgb = GetTeamRGB(color1); - drawsetcliparea( pos_x, pos_y, @@ -3625,13 +2539,142 @@ void HUD_Radar(void) // Score (#7) // -void HUD_Score(void) +void HUD_UpdatePlayerTeams(); +void HUD_Score_Rankings(vector pos, vector mySize, entity me, float team_count) { - if(!autocvar_hud_panel_score && !autocvar__hud_configure) + float score; + entity tm, pl; +#define SCOREPANEL_MAX_ENTRIES 6 +#define SCOREPANEL_ASPECTRATIO 2 + float entries = bound(1, floor(SCOREPANEL_MAX_ENTRIES * mySize_y/mySize_x * SCOREPANEL_ASPECTRATIO), SCOREPANEL_MAX_ENTRIES); + vector fontsize = '1 1 0' * (mySize_y/entries); + + vector rgb, score_color; + rgb = '1 1 1'; + score_color = '1 1 1'; + + float name_size = mySize_x*0.75; + float spacing_size = mySize_x*0.04; + const float highlight_alpha = 0.2; + float i, me_printed, first_pl; + string s; + i = 0; + first_pl = 0; + if (autocvar__hud_configure) + { + float players_per_team; + if (team_count) + { + // show team scores in the first line + float score_size = mySize_x / team_count; + players_per_team = max(2, ceil((entries - 1) / team_count)); + for(i=0; i<team_count; ++i) { + if (i == floor((entries - 2) / players_per_team) || (entries == 1 && i == 0)) + HUD_Panel_DrawHighlight(pos + eX * score_size * i, eX * score_size + eY * fontsize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + drawstring_aspect(pos + eX * score_size * i, ftos(175 - 23*i), eX * score_size + eY * fontsize_y, GetTeamRGB(ColorByTeam(i)) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL); + } + first_pl = 1; + pos_y += fontsize_y; + } + score = 10 + SCOREPANEL_MAX_ENTRIES * 3; + for (i=first_pl; i<entries; ++i) + { + //simulate my score is lower than all displayed players, + //so that I don't appear at all showing pure rankings. + //This is to better show the difference between the 2 ranking views + if (i == entries-1 && autocvar_hud_panel_score_rankings == 1) + { + rgb = '1 1 0'; + drawfill(pos, eX * mySize_x + eY * fontsize_y, rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); + s = GetPlayerName(pl.sv_entnum); + score = 7; + } + else + { + s = sprintf(_("Player %d"), i + 1 - first_pl); + score -= 3; + } + + if (team_count) + score_color = GetTeamRGB(ColorByTeam(floor((i - first_pl) / players_per_team))) * 0.8; + s = textShortenToWidth(s, name_size, fontsize, stringwidth_colors); + drawcolorcodedstring(pos + eX * (name_size - stringwidth(s, TRUE, fontsize)), s, fontsize, panel_fg_alpha, DRAWFLAG_NORMAL); + drawstring(pos + eX * (name_size + spacing_size), ftos(score), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL); + pos_y += fontsize_y; + } return; + } + + if (!scoreboard_fade_alpha) // the scoreboard too calls HUD_UpdatePlayerTeams + HUD_UpdatePlayerTeams(); + if (team_count) + { + // show team scores in the first line + float score_size = mySize_x / team_count; + for(tm = teams.sort_next; tm; tm = tm.sort_next) { + if(tm.team == COLOR_SPECTATOR) + continue; + if (tm.team == myteam) + drawfill(pos + eX * score_size * i, eX * score_size + eY * fontsize_y, '1 1 1', highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); + drawstring_aspect(pos + eX * score_size * i, ftos(tm.(teamscores[ts_primary])), eX * score_size + eY * fontsize_y, GetTeamRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL); + ++i; + } + first_pl = 1; + pos_y += fontsize_y; + tm = teams.sort_next; + } + i = first_pl; + + do + for (pl = players.sort_next; pl && i<entries; pl = pl.sort_next) + { + if ((team_count && pl.team != tm.team) || pl.team == COLOR_SPECTATOR) + continue; + + if (i == entries-1 && !me_printed && pl != me) + if (autocvar_hud_panel_score_rankings == 1 && spectatee_status != -1) + { + for (pl = me.sort_next; pl; pl = pl.sort_next) + if (pl.team != COLOR_SPECTATOR) + break; + + if (pl) + rgb = '1 1 0'; //not last but not among the leading players: yellow + else + rgb = '1 0 0'; //last: red + pl = me; + } + + if (pl == me) + { + if (i == first_pl) + rgb = '0 1 0'; //first: green + me_printed = 1; + drawfill(pos, eX * mySize_x + eY * fontsize_y, rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); + } + if (team_count) + score_color = GetTeamRGB(pl.team) * 0.8; + s = textShortenToWidth(GetPlayerName(pl.sv_entnum), name_size, fontsize, stringwidth_colors); + drawcolorcodedstring(pos + eX * (name_size - stringwidth(s, TRUE, fontsize)), s, fontsize, panel_fg_alpha, DRAWFLAG_NORMAL); + drawstring(pos + eX * (name_size + spacing_size), ftos(pl.(scores[ps_primary])), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL); + pos_y += fontsize_y; + ++i; + } + while (i<entries && team_count && (tm = tm.sort_next) && (tm.team != COLOR_SPECTATOR || (tm = tm.sort_next))); +} + +void HUD_Score(void) +{ + if(!autocvar__hud_configure) + { + if(!autocvar_hud_panel_score) return; + if(spectatee_status == -1 && (gametype == MAPINFO_TYPE_RACE || gametype == MAPINFO_TYPE_CTS)) return; + } + else + hud_configure_active_panel = HUD_PANEL_SCORE; - active_panel = HUD_PANEL_SCORE; HUD_Panel_UpdateCvars(score); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -3643,11 +2686,15 @@ void HUD_Score(void) mySize -= '2 2 0' * panel_bg_padding; } - float score, distribution, leader; + float score, distribution; string sign; vector distribution_color; entity tm, pl, me; +#ifdef COMPAT_XON050_ENGINE me = (spectatee_status > 0) ? playerslots[spectatee_status - 1] : playerslots[player_localentnum - 1]; +#else + me = playerslots[player_localentnum - 1]; +#endif if((scores_flags[ps_primary] & SFL_TIME) && !teamplay) { // race/cts record display on HUD string timer, distrtimer; @@ -3681,10 +2728,13 @@ void HUD_Score(void) // race record display if (distribution <= 0) HUD_Panel_DrawHighlight(pos, eX * 0.75 * mySize_x + eY * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); - drawfont = hud_bigfont; drawstring_aspect(pos, timer, eX * 0.75 * mySize_x + eY * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); - drawfont = hud_font; } else if (!teamplay) { // non-teamgames + if ((spectatee_status == -1 && !autocvar__hud_configure) || autocvar_hud_panel_score_rankings) + { + HUD_Score_Rankings(pos, mySize, me, 0); + return; + } // me vector := [team/connected frags id] pl = players.sort_next; if(pl == me) @@ -3701,54 +2751,99 @@ void HUD_Score(void) if(autocvar__hud_configure) score = 123; - if(distribution >= 5) { + if(distribution >= 5) distribution_color = eY; - leader = 1; - } else if(distribution >= 0) { + else if(distribution >= 0) distribution_color = '1 1 1'; - leader = 1; - } else if(distribution >= -5) + else if(distribution >= -5) distribution_color = '1 1 0'; else distribution_color = eX; - drawstring_aspect(pos + eX * 0.75 * mySize_x, ftos(distribution), eX * 0.25 * mySize_x + eY * (1/3) * mySize_y, distribution_color, panel_fg_alpha, DRAWFLAG_NORMAL); - if (leader) + string distribution_str; + distribution_str = ftos(distribution); + if (distribution >= 0) + { + if (distribution > 0) + distribution_str = strcat("+", distribution_str); HUD_Panel_DrawHighlight(pos, eX * 0.75 * mySize_x + eY * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); - drawfont = hud_bigfont; + } drawstring_aspect(pos, ftos(score), eX * 0.75 * mySize_x + eY * mySize_y, distribution_color, panel_fg_alpha, DRAWFLAG_NORMAL); - drawfont = hud_font; + drawstring_aspect(pos + eX * 0.75 * mySize_x, distribution_str, eX * 0.25 * mySize_x + eY * (1/3) * mySize_y, distribution_color, panel_fg_alpha, DRAWFLAG_NORMAL); } else { // teamgames + float scores_count, row, column, rows, columns; + local noref vector offset; // fteqcc sucks + vector score_pos, score_size; //for scores other than myteam + if (spectatee_status == -1 || autocvar_hud_panel_score_rankings) + { + for(tm = teams.sort_next; tm, tm.team != COLOR_SPECTATOR; tm = tm.sort_next) + ++scores_count; + if (autocvar_hud_panel_score_rankings) + { + HUD_Score_Rankings(pos, mySize, me, scores_count); + return; + } + rows = mySize_y/mySize_x; + rows = bound(1, floor((sqrt(4 * (3/1) * rows * scores_count + rows * rows) + rows + 0.5) / 2), scores_count); + // ^^^ ammo item aspect goes here + + columns = ceil(scores_count/rows); + + score_size = eX * mySize_x*(1/columns) + eY * mySize_y*(1/rows); + + float newSize; + if(score_size_x/score_size_y > 3) + { + newSize = 3 * score_size_y; + offset_x = score_size_x - newSize; + pos_x += offset_x/2; + score_size_x = newSize; + } + else + { + newSize = 1/3 * score_size_x; + offset_y = score_size_y - newSize; + pos_y += offset_y/2; + score_size_y = newSize; + } + } + else + score_size = eX * mySize_x*(1/4) + eY * mySize_y*(1/3); + float max_fragcount; max_fragcount = -99; - - float teamnum; for(tm = teams.sort_next; tm; tm = tm.sort_next) { - if(tm.team == COLOR_SPECTATOR || (!tm.team_size && !autocvar__hud_configure)) // no players? don't display + if(tm.team == COLOR_SPECTATOR) continue; score = tm.(teamscores[ts_primary]); if(autocvar__hud_configure) score = 123; - leader = 0; if (score > max_fragcount) max_fragcount = score; - if(tm.team == myteam) { + if (spectatee_status == -1) + { + score_pos = pos + eX * column * (score_size_x + offset_x) + eY * row * (score_size_y + offset_y); + if (max_fragcount == score) + HUD_Panel_DrawHighlight(score_pos, score_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + drawstring_aspect(score_pos, ftos(score), score_size, GetTeamRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL); + ++row; + if(row >= rows) + { + row = 0; + ++column; + } + } + else if(tm.team == myteam) { if (max_fragcount == score) - leader = 1; - if (leader) HUD_Panel_DrawHighlight(pos, eX * 0.75 * mySize_x + eY * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); - drawfont = hud_bigfont; drawstring_aspect(pos, ftos(score), eX * 0.75 * mySize_x + eY * mySize_y, GetTeamRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL); - drawfont = hud_font; } else { if (max_fragcount == score) - leader = 1; - if (leader) - HUD_Panel_DrawHighlight(pos + eX * 0.75 * mySize_x + eY * (1/3) * teamnum * mySize_y, eX * 0.25 * mySize_x + eY * (1/3) * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); - drawstring_aspect(pos + eX * 0.75 * mySize_x + eY * (1/3) * teamnum * mySize_y, ftos(score), eX * 0.25 * mySize_x + eY * (1/3) * mySize_y, GetTeamRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL); - teamnum += 1; + HUD_Panel_DrawHighlight(pos + eX * 0.75 * mySize_x + eY * (1/3) * rows * mySize_y, score_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + drawstring_aspect(pos + eX * 0.75 * mySize_x + eY * (1/3) * rows * mySize_y, ftos(score), score_size, GetTeamRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL); + ++rows; } } } @@ -3756,12 +2851,19 @@ void HUD_Score(void) // Race timer (#8) // -void HUD_RaceTimer (void) { - if(!autocvar_hud_panel_racetimer && !(gametype == GAME_RACE || gametype == GAME_CTS) && !autocvar__hud_configure) - return; +void HUD_RaceTimer (void) +{ + if(!autocvar__hud_configure) + { + if(!autocvar_hud_panel_racetimer) return; + if(!(gametype == MAPINFO_TYPE_RACE || gametype == MAPINFO_TYPE_CTS)) return; + if(spectatee_status == -1) return; + } + else + hud_configure_active_panel = HUD_PANEL_RACETIMER; - active_panel = HUD_PANEL_RACETIMER; HUD_Panel_UpdateCvars(racetimer); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -3791,7 +2893,6 @@ void HUD_RaceTimer (void) { } mySize = newSize; - drawfont = hud_bigfont; float a, t; string s, forcetime; @@ -3799,9 +2900,9 @@ void HUD_RaceTimer (void) { { s = "0:13:37"; drawstring(pos + eX * 0.5 * mySize_x - '0.5 0 0' * stringwidth(s, FALSE, '0.60 0.60 0' * mySize_y), s, '0.60 0.60 0' * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); - s = "^1Intermediate 1 (+15.42)"; + s = _("^1Intermediate 1 (+15.42)"); drawcolorcodedstring(pos + eX * 0.5 * mySize_x - '0.5 0 0' * stringwidth(s, TRUE, '1 1 0' * 0.20 * mySize_y) + eY * 0.60 * mySize_y, s, '1 1 0' * 0.20 * mySize_y, panel_fg_alpha, DRAWFLAG_NORMAL); - s = strcat("^1PENALTY: ", ftos_decimals(20 * 0.1, 1), " (missing a checkpoint)"); + s = sprintf(_("^1PENALTY: %.1f (%s)"), 2, "missing a checkpoint"); drawcolorcodedstring(pos + eX * 0.5 * mySize_x - '0.5 0 0' * stringwidth(s, TRUE, '1 1 0' * 0.20 * mySize_y) + eY * 0.80 * mySize_y, s, '1 1 0' * 0.20 * mySize_y, panel_fg_alpha, DRAWFLAG_NORMAL); } else if(race_checkpointtime) @@ -3843,7 +2944,7 @@ void HUD_RaceTimer (void) { a = bound(0, 2 - (time - race_penaltyeventtime), 1); if(a > 0) { - s = strcat("^1PENALTY: ", ftos_decimals(race_penaltytime * 0.1, 1), " (", race_penaltyreason, ")"); + s = sprintf(_("^1PENALTY: %.1f (%s)"), race_penaltytime * 0.1, race_penaltyreason); drawcolorcodedstring(pos + eX * 0.5 * mySize_x - '0.5 0 0' * stringwidth(s, TRUE, '1 1 0' * 0.2 * mySize_y) + eY * 0.8 * mySize_y, s, '1 1 0' * 0.2 * mySize_y, panel_fg_alpha * a, DRAWFLAG_NORMAL); } } @@ -3884,15 +2985,13 @@ void HUD_RaceTimer (void) { if(a > 0) { if(time < t) - s = strcat("^1PENALTY: ", ftos_decimals(t - time, 1), " (", race_penaltyreason, ")"); + s = sprintf(_("^1PENALTY: %.1f (%s)"), (t - time) * 0.1, race_penaltyreason); else - s = strcat("^2PENALTY: 0.0 (", race_penaltyreason, ")"); + s = sprintf(_("^2PENALTY: %.1f (%s)"), 0, race_penaltyreason); drawcolorcodedstring(pos + eX * 0.5 * mySize_x - '0.5 0 0' * stringwidth(s, TRUE, '1 1 0' * 0.2 * mySize_y) + eY * 0.6 * mySize_y, s, '1 1 0' * 0.2 * mySize_y, panel_fg_alpha * a, DRAWFLAG_NORMAL); } } } - - drawfont = hud_font; } // Vote window (#9) @@ -3909,19 +3008,26 @@ float vote_change; // "time" when vote_active changed void HUD_VoteWindow(void) { - uid2name_dialog = 0; - if(autocvar_cl_allow_uid2name == -1 && (gametype == GAME_CTS || gametype == GAME_RACE)) + if(autocvar_cl_allow_uid2name == -1 && (gametype == MAPINFO_TYPE_CTS || gametype == MAPINFO_TYPE_RACE || (serverflags & SERVERFLAG_PLAYERSTATS))) { vote_active = 1; - vote_called_vote = strzone(strcat("^2Name ^7instead of \"^1Unregistered player\"", " ^7in stats")); - uid2name_dialog = 1; + if (autocvar__hud_configure) + { + vote_yescount = 0; + vote_nocount = 0; + print(_("^1You must answer before entering hud configure mode\n")); + cvar_set("_hud_configure", "0"); + } + if(vote_called_vote) + strunzone(vote_called_vote); + vote_called_vote = strzone(_("^2Name ^7instead of \"^1Anonymous player^7\" in stats")); + uid2name_dialog = 1; } - if(!autocvar_hud_panel_vote && !autocvar__hud_configure) - return; - if(!autocvar__hud_configure) { + if(!autocvar_hud_panel_vote) return; + panel_fg_alpha = autocvar_hud_panel_fg_alpha; panel_bg_alpha_str = autocvar_hud_panel_vote_bg_alpha; @@ -3930,6 +3036,14 @@ void HUD_VoteWindow(void) } panel_bg_alpha = stof(panel_bg_alpha_str); } + else + { + hud_configure_active_panel = HUD_PANEL_VOTE; + + vote_yescount = 3; + vote_nocount = 2; + vote_needed = 4; + } string s; float a; @@ -3943,18 +3057,11 @@ void HUD_VoteWindow(void) else vote_alpha = bound(0, 1 - (time - vote_change) * 2, 1); - if(autocvar__hud_configure) - { - vote_yescount = 3; - vote_nocount = 2; - vote_needed = 4; - } - if(!vote_alpha) return; - active_panel = HUD_PANEL_VOTE; HUD_Panel_UpdateCvars(vote); + HUD_Panel_ApplyFadeAlpha(); if(uid2name_dialog) { @@ -3967,7 +3074,7 @@ void HUD_VoteWindow(void) pos = panel_pos; mySize = panel_size; - a = vote_alpha * bound(autocvar_hud_panel_vote_alreadyvoted_alpha, 1 - vote_highlighted, 1); + a = vote_alpha * (vote_highlighted ? autocvar_hud_panel_vote_alreadyvoted_alpha : 1); HUD_Panel_DrawBg(a); a = panel_fg_alpha * a; @@ -3995,19 +3102,19 @@ void HUD_VoteWindow(void) } mySize = newSize; - s = "A vote has been called for:"; + s = _("A vote has been called for:"); if(uid2name_dialog) - s = "Allow servers to store and display your name?"; + s = _("Allow servers to store and display your name?"); drawstring_aspect(pos, s, eX * mySize_x + eY * (2/8) * mySize_y, '1 1 1', a, DRAWFLAG_NORMAL); s = textShortenToWidth(vote_called_vote, mySize_x, '1 1 0' * mySize_y * (1/8), stringwidth_colors); if(autocvar__hud_configure) - s = "^1Configure the HUD"; + s = _("^1Configure the HUD"); drawcolorcodedstring_aspect(pos + eY * (2/8) * mySize_y, s, eX * mySize_x + eY * (1.75/8) * mySize_y, a, DRAWFLAG_NORMAL); // print the yes/no counts - s = strcat("Yes (", getcommandkey("vyes", "vyes"), "): ", ftos(vote_yescount)); + s = sprintf(_("Yes (%s): %d"), getcommandkey("vyes", "vyes"), vote_yescount); drawstring_aspect(pos + eY * (4/8) * mySize_y, s, eX * 0.5 * mySize_x + eY * (1.5/8) * mySize_y, '0 1 0', a, DRAWFLAG_NORMAL); - s = strcat("No (", getcommandkey("vno", "vno"), "): ", ftos(vote_nocount)); + s = sprintf(_("No (%s): %d"), getcommandkey("vno", "vno"), vote_nocount); drawstring_aspect(pos + eX * 0.5 * mySize_x + eY * (4/8) * mySize_y, s, eX * 0.5 * mySize_x + eY * (1.5/8) * mySize_y, '1 0 0', a, DRAWFLAG_NORMAL); // draw the progress bar backgrounds @@ -4018,7 +3125,7 @@ void HUD_VoteWindow(void) drawsetcliparea(pos_x, pos_y, mySize_x * 0.5, mySize_y); drawpic_skin(pos + eY * (5/8) * mySize_y, "voteprogress_voted", eX * mySize_x + eY * (3/8) * mySize_y, '1 1 1', a, DRAWFLAG_NORMAL); } - else if(vote_highlighted == 2) { + else if(vote_highlighted == -1) { drawsetcliparea(pos_x + 0.5 * mySize_x, pos_y, mySize_x * 0.5, mySize_y); drawpic_skin(pos + eY * (5/8) * mySize_y, "voteprogress_voted", eX * mySize_x + eY * (3/8) * mySize_y, '1 1 1', a, DRAWFLAG_NORMAL); } @@ -4037,10 +3144,6 @@ void HUD_VoteWindow(void) } drawresetcliparea(); - - if(!vote_active) { - vote_highlighted = 0; - } } // Mod icons panel (#10) @@ -4056,7 +3159,6 @@ void HUD_Mod_CA(vector pos, vector mySize) redalive = getstati(STAT_REDALIVE); bluealive = getstati(STAT_BLUEALIVE); - drawfont = hud_bigfont; vector redpos, bluepos; if(mySize_x > mySize_y) { @@ -4076,7 +3178,6 @@ void HUD_Mod_CA(vector pos, vector mySize) drawpic_aspect_skin(bluepos, "player_blue.tga", eX * mySize_x + eY * 0.3 * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); drawstring_aspect(bluepos + eY * 0.3 * mySize_y, ftos(bluealive), eX * mySize_x + eY * 0.2 * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); } - drawfont = hud_font; } // CTF HUD modicon section @@ -4099,7 +3200,7 @@ void HUD_Mod_CTF(vector pos, vector mySize) float redflag_statuschange_elapsedtime, blueflag_statuschange_elapsedtime; // time since the status changed float stat_items; - stat_items = getstati(STAT_ITEMS); + stat_items = getstati(STAT_ITEMS, 0, 24); redflag = (stat_items/IT_RED_FLAG_TAKEN) & 3; blueflag = (stat_items/IT_BLUE_FLAG_TAKEN) & 3; @@ -4322,16 +3423,16 @@ void HUD_Mod_KH(vector pos, vector mySize) switch(keyteam) { case COLOR_TEAM1: - drawpic_aspect_skin(pa, "kh_redarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL); // show 30% alpha key + drawpic_aspect_skin(pa, "kh_redarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL); // show 30% theAlpha key break; case COLOR_TEAM2: - drawpic_aspect_skin(pa, "kh_bluearrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL); // show 30% alpha key + drawpic_aspect_skin(pa, "kh_bluearrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL); // show 30% theAlpha key break; case COLOR_TEAM3: - drawpic_aspect_skin(pa, "kh_yellowarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL); // show 30% alpha key + drawpic_aspect_skin(pa, "kh_yellowarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL); // show 30% theAlpha key break; case COLOR_TEAM4: - drawpic_aspect_skin(pa, "kh_pinkarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL); // show 30% alpha key + drawpic_aspect_skin(pa, "kh_pinkarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL); // show 30% theAlpha key break; default: break; @@ -4339,16 +3440,16 @@ void HUD_Mod_KH(vector pos, vector mySize) switch(i) // YAY! switch(i) inside a for loop for i. DailyWTF, here we come! { case 0: - drawpic_aspect_skin(p, "kh_red", kh_size, '1 1 1', a, DRAWFLAG_NORMAL); // show 30% alpha key + drawpic_aspect_skin(p, "kh_red", kh_size, '1 1 1', a, DRAWFLAG_NORMAL); // show 30% theAlpha key break; case 1: - drawpic_aspect_skin(p, "kh_blue", kh_size, '1 1 1', a, DRAWFLAG_NORMAL); // show 30% alpha key + drawpic_aspect_skin(p, "kh_blue", kh_size, '1 1 1', a, DRAWFLAG_NORMAL); // show 30% theAlpha key break; case 2: - drawpic_aspect_skin(p, "kh_yellow", kh_size, '1 1 1', a, DRAWFLAG_NORMAL); // show 30% alpha key + drawpic_aspect_skin(p, "kh_yellow", kh_size, '1 1 1', a, DRAWFLAG_NORMAL); // show 30% theAlpha key break; case 3: - drawpic_aspect_skin(p, "kh_pink", kh_size, '1 1 1', a, DRAWFLAG_NORMAL); // show 30% alpha key + drawpic_aspect_skin(p, "kh_pink", kh_size, '1 1 1', a, DRAWFLAG_NORMAL); // show 30% theAlpha key break; } } @@ -4391,7 +3492,7 @@ void HUD_Mod_Keepaway(vector pos, vector mySize) float BLINK_FREQ = 5; float kaball_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); - float stat_items = getstati(STAT_ITEMS); + float stat_items = getstati(STAT_ITEMS, 0, 24); float kaball = (stat_items/IT_KEY1) & 1; if(kaball != kaball_prevstatus) @@ -4400,13 +3501,21 @@ void HUD_Mod_Keepaway(vector pos, vector mySize) kaball_prevstatus = kaball; } - // todo: Fix the sizing with the expanding image + vector kaball_pos, kaball_size; + + if(mySize_x > mySize_y) { + kaball_pos = pos + eX * 0.25 * mySize_x; + kaball_size = eX * 0.5 * mySize_x + eY * mySize_y; + } else { + kaball_pos = pos + eY * 0.25 * mySize_y; + kaball_size = eY * 0.5 * mySize_y + eX * mySize_x; + } float kaball_statuschange_elapsedtime = time - kaball_statuschange_time; float f = bound(0, kaball_statuschange_elapsedtime*2, 1); if(kaball_prevstatus && f < 1) - drawpic_aspect_skin_expanding(pos + eY * 0.25 * mySize_y, "keepawayball_carrying", eX * mySize_x + eY * mySize_y * 0.5, '1 1 1', panel_fg_alpha * kaball_alpha, DRAWFLAG_NORMAL, f); + drawpic_aspect_skin_expanding(kaball_pos, "keepawayball_carrying", kaball_size, '1 1 1', panel_fg_alpha * kaball_alpha, DRAWFLAG_NORMAL, f); if(kaball) drawpic_aspect_skin(pos, "keepawayball_carrying", eX * mySize_x + eY * mySize_y, '1 1 1', panel_fg_alpha * kaball_alpha * f, DRAWFLAG_NORMAL); @@ -4418,7 +3527,7 @@ void HUD_Mod_NexBall(vector pos, vector mySize) { float stat_items, nb_pb_starttime, dt, p; - stat_items = getstati(STAT_ITEMS); + stat_items = getstati(STAT_ITEMS, 0, 24); nb_pb_starttime = getstatf(STAT_NB_METERSTART); if (stat_items & IT_KEY1) @@ -4436,17 +3545,11 @@ void HUD_Mod_NexBall(vector pos, vector mySize) p = 2 - p; //Draw the filling - float vertical; + HUD_Panel_GetProgressBarColor(nexball); if(mySize_x > mySize_y) - { - vertical = 0; - } + HUD_Panel_DrawProgressBar(pos, mySize, "progressbar", p, 0, 0, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); else - { - vertical = 1; - } - HUD_Panel_GetProgressBarColor(nexball); - HUD_Panel_DrawProgressBar(pos, mySize, "statusbar", vertical, 0, p, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); + HUD_Panel_DrawProgressBar(pos, mySize, "progressbar", p, 1, 0, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); } if (stat_items & IT_KEY1) @@ -4466,7 +3569,7 @@ void HUD_Mod_Race(vector pos, vector mySize) { mod_active = 1; // race should never hide the mod icons panel entity me; - me = playerslots[player_localentnum - 1]; + me = playerslots[player_localnum]; float t, score; float f; // yet another function has this score = me.(scores[ps_primary]); @@ -4474,11 +3577,9 @@ void HUD_Mod_Race(vector pos, vector mySize) if not((scores_flags[ps_primary] & SFL_TIME) && !teamplay) // race/cts record display on HUD return; // no records in the actual race - drawfont = hud_bigfont; - // clientside personal record string rr; - if(gametype == GAME_CTS) + if(gametype == MAPINFO_TYPE_CTS) rr = CTS_RECORD; else rr = RACE_RECORD; @@ -4516,12 +3617,12 @@ void HUD_Mod_Race(vector pos, vector mySize) f = time - crecordtime_change_time; if (f > 1) { - drawstring_aspect(textPos, "Personal best", eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + drawstring_aspect(textPos, _("Personal best"), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); drawstring_aspect(textPos + eY * 0.25 * squareSize, TIME_ENCODED_TOSTRING(t), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); } else { - drawstring_aspect(textPos, "Personal best", eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + drawstring_aspect(textPos, _("Personal best"), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); drawstring_aspect(textPos + eY * 0.25 * squareSize, TIME_ENCODED_TOSTRING(t), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); - drawstring_aspect_expanding(pos, "Personal best", eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f); + drawstring_aspect_expanding(pos, _("Personal best"), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f); drawstring_aspect_expanding(pos + eY * 0.25 * squareSize, TIME_ENCODED_TOSTRING(t), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f); } @@ -4534,12 +3635,12 @@ void HUD_Mod_Race(vector pos, vector mySize) f = time - srecordtime_change_time; if (f > 1) { - drawstring_aspect(textPos + eY * 0.5 * squareSize, "Server best", eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + drawstring_aspect(textPos + eY * 0.5 * squareSize, _("Server best"), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); drawstring_aspect(textPos + eY * 0.75 * squareSize, TIME_ENCODED_TOSTRING(t), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); } else { - drawstring_aspect(textPos + eY * 0.5 * squareSize, "Server best", eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + drawstring_aspect(textPos + eY * 0.5 * squareSize, _("Server best"), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); drawstring_aspect(textPos + eY * 0.75 * squareSize, TIME_ENCODED_TOSTRING(t), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); - drawstring_aspect_expanding(textPos + eY * 0.5 * squareSize, "Server best", eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f); + drawstring_aspect_expanding(textPos + eY * 0.5 * squareSize, _("Server best"), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f); drawstring_aspect_expanding(textPos + eY * 0.75 * squareSize, TIME_ENCODED_TOSTRING(t), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f); } @@ -4576,7 +3677,7 @@ void HUD_Mod_Race(vector pos, vector mySize) drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL); drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); } else if(race_status == 2) { - if(race_status_name == GetPlayerName(player_localentnum -1) || !race_myrank || race_myrank < rank) + if(race_status_name == GetPlayerName(player_localnum) || !race_myrank || race_myrank < rank) drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newrankgreen", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); else drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newrankyellow", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); @@ -4598,7 +3699,103 @@ void HUD_Mod_Race(vector pos, vector mySize) strunzone(race_status_name_prev); race_status_name_prev = string_null; } - drawfont = hud_font; +} + +void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, float layout, float i) +{ + float stat, pps_ratio; + string pic; + vector color; + switch(i) + { + case 0: + stat = getstatf(STAT_DOM_PPS_RED); + pic = "dom_icon_red"; + color = '1 0 0'; + break; + case 1: + stat = getstatf(STAT_DOM_PPS_BLUE); + pic = "dom_icon_blue"; + color = '0 0 1'; + break; + case 2: + stat = getstatf(STAT_DOM_PPS_YELLOW); + pic = "dom_icon_yellow"; + color = '1 1 0'; + break; + case 3: + stat = getstatf(STAT_DOM_PPS_PINK); + pic = "dom_icon_pink"; + color = '1 0 1'; + } + pps_ratio = stat / getstatf(STAT_DOM_TOTAL_PPS); + + if(mySize_x/mySize_y > aspect_ratio) + { + i = aspect_ratio * mySize_y; + myPos_x = myPos_x + (mySize_x - i) / 2; + mySize_x = i; + } + else + { + i = 1/aspect_ratio * mySize_x; + myPos_y = myPos_y + (mySize_y - i) / 2; + mySize_y = i; + } + + if (layout) // show text too + { + //draw the text + color *= 0.5 + pps_ratio * (1 - 0.5); // half saturated color at min, full saturated at max + if (layout == 2) // average pps + drawstring_aspect(myPos + eX * mySize_y, ftos_decimals(stat, 2), eX * (2/3) * mySize_x + eY * mySize_y, color, panel_fg_alpha, DRAWFLAG_NORMAL); + else // percentage of average pps + drawstring_aspect(myPos + eX * mySize_y, strcat( ftos(floor(pps_ratio*100 + 0.5)), "%" ), eX * (2/3) * mySize_x + eY * mySize_y, color, panel_fg_alpha, DRAWFLAG_NORMAL); + } + + //draw the icon + drawpic_aspect_skin(myPos, pic, '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + if (stat > 0) + { + drawsetcliparea(myPos_x, myPos_y + mySize_y * (1 - pps_ratio), mySize_y, mySize_y * pps_ratio); + drawpic_aspect_skin(myPos, strcat(pic, "-highlighted"), '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + drawresetcliparea(); + } +} + +void HUD_Mod_Dom(vector myPos, vector mySize) +{ + mod_active = 1; // required in each mod function that always shows something + entity tm; + float teams_count; + for(tm = teams.sort_next; tm; tm = tm.sort_next) + if(tm.team != COLOR_SPECTATOR) + ++teams_count; + + float layout = autocvar_hud_panel_modicons_dom_layout; + float rows, columns, aspect_ratio; + rows = mySize_y/mySize_x; + aspect_ratio = (layout) ? 3 : 1; + rows = bound(1, floor((sqrt((4 * aspect_ratio * teams_count + rows) * rows) + rows + 0.5) / 2), teams_count); + columns = ceil(teams_count/rows); + + int i; + float row, column; + for(i=0; i<teams_count; ++i) + { + vector pos, itemSize; + pos = myPos + eX * column * mySize_x*(1/columns) + eY * row * mySize_y*(1/rows); + itemSize = eX * mySize_x*(1/columns) + eY * mySize_y*(1/rows); + + DrawDomItem(pos, itemSize, aspect_ratio, layout, i); + + ++row; + if(row >= rows) + { + row = 0; + ++column; + } + } } float mod_prev; // previous state of mod_active to check for a change @@ -4607,14 +3804,16 @@ float mod_change; // "time" when mod_active changed void HUD_ModIcons(void) { - if(!autocvar_hud_panel_modicons && !autocvar__hud_configure) - return; - - if (gametype != GAME_KEYHUNT && gametype != GAME_CTF && gametype != GAME_NEXBALL && gametype != GAME_CTS && gametype != GAME_RACE && gametype != GAME_CA && gametype != GAME_FREEZETAG && gametype != GAME_KEEPAWAY && !autocvar__hud_configure) - return; + if(!autocvar__hud_configure) + { + if(!autocvar_hud_panel_modicons) return; + if (gametype != MAPINFO_TYPE_CTF && gametype != MAPINFO_TYPE_KEYHUNT && gametype != MAPINFO_TYPE_NEXBALL && gametype != MAPINFO_TYPE_CTS && gametype != MAPINFO_TYPE_RACE && gametype != MAPINFO_TYPE_CA && gametype != MAPINFO_TYPE_FREEZETAG && gametype != MAPINFO_TYPE_KEEPAWAY && gametype != MAPINFO_TYPE_DOMINATION) return; + } + else + hud_configure_active_panel = HUD_PANEL_MODICONS; - active_panel = HUD_PANEL_MODICONS; HUD_Panel_UpdateCvars(modicons); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -4639,17 +3838,19 @@ void HUD_ModIcons(void) } // these MUST be ran in order to update mod_active - if(gametype == GAME_KEYHUNT) + if(gametype == MAPINFO_TYPE_KEYHUNT) HUD_Mod_KH(pos, mySize); - else if(gametype == GAME_CTF || autocvar__hud_configure) + else if(gametype == MAPINFO_TYPE_CTF || autocvar__hud_configure) HUD_Mod_CTF(pos, mySize); // forcealpha only needed for ctf icons, as only they are shown in config mode - else if(gametype == GAME_NEXBALL) + else if(gametype == MAPINFO_TYPE_NEXBALL) HUD_Mod_NexBall(pos, mySize); - else if(gametype == GAME_CTS || gametype == GAME_RACE) + else if(gametype == MAPINFO_TYPE_CTS || gametype == MAPINFO_TYPE_RACE) HUD_Mod_Race(pos, mySize); - else if(gametype == GAME_CA || gametype == GAME_FREEZETAG) + else if(gametype == MAPINFO_TYPE_CA || gametype == MAPINFO_TYPE_FREEZETAG) HUD_Mod_CA(pos, mySize); - else if(gametype == GAME_KEEPAWAY) + else if(gametype == MAPINFO_TYPE_DOMINATION) + HUD_Mod_Dom(pos, mySize); + else if(gametype == MAPINFO_TYPE_KEEPAWAY) HUD_Mod_Keepaway(pos, mySize); } @@ -4657,14 +3858,17 @@ void HUD_ModIcons(void) // void HUD_DrawPressedKeys(void) { - if(!autocvar_hud_panel_pressedkeys && !autocvar__hud_configure) - return; + if(!autocvar__hud_configure) + { + if(!autocvar_hud_panel_pressedkeys) return; + if(spectatee_status <= 0 && autocvar_hud_panel_pressedkeys < 2) return; + } + else + hud_configure_active_panel = HUD_PANEL_PRESSEDKEYS; - if(!(spectatee_status > 0 || autocvar_hud_panel_pressedkeys >= 2 || autocvar__hud_configure)) - return; - active_panel = HUD_PANEL_PRESSEDKEYS; HUD_Panel_UpdateCvars(pressedkeys); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -4701,28 +3905,37 @@ void HUD_DrawPressedKeys(void) vector keysize; keysize = eX * mySize_x * (1/3) + eY * mySize_y * 0.5; float pressedkeys; - pressedkeys = getstatf(STAT_PRESSED_KEYS); + drawpic_aspect_skin(pos, ((pressedkeys & KEY_CROUCH) ? "key_crouch_inv.tga" : "key_crouch.tga"), keysize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); - drawpic_aspect_skin(pos + eX * mySize_x * (1/3), ((pressedkeys & KEY_FORWARD) ? "key_forward_inv.tga" : "key_forward.tga"), keysize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); - drawpic_aspect_skin(pos + eX * mySize_x * (2/3), ((pressedkeys & KEY_JUMP) ? "key_jump_inv.tga" : "key_jump.tga"), keysize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); - drawpic_aspect_skin(pos + eY * 0.5 * mySize_y, ((pressedkeys & KEY_LEFT) ? "key_left_inv.tga" : "key_left.tga"), keysize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); - drawpic_aspect_skin(pos + eY * 0.5 * mySize_y + eX * mySize_x * (1/3), ((pressedkeys & KEY_BACKWARD) ? "key_backward_inv.tga" : "key_backward.tga"), keysize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); - drawpic_aspect_skin(pos + eY * 0.5 * mySize_y + eX * mySize_x * (2/3), ((pressedkeys & KEY_RIGHT) ? "key_right_inv.tga" : "key_right.tga"), keysize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + drawpic_aspect_skin(pos + eX * keysize_x, ((pressedkeys & KEY_FORWARD) ? "key_forward_inv.tga" : "key_forward.tga"), keysize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + drawpic_aspect_skin(pos + eX * keysize_x * 2, ((pressedkeys & KEY_JUMP) ? "key_jump_inv.tga" : "key_jump.tga"), keysize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + pos_y += keysize_y; + drawpic_aspect_skin(pos, ((pressedkeys & KEY_LEFT) ? "key_left_inv.tga" : "key_left.tga"), keysize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + drawpic_aspect_skin(pos + eX * keysize_x, ((pressedkeys & KEY_BACKWARD) ? "key_backward_inv.tga" : "key_backward.tga"), keysize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + drawpic_aspect_skin(pos + eX * keysize_x * 2, ((pressedkeys & KEY_RIGHT) ? "key_right_inv.tga" : "key_right.tga"), keysize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); } // Handle chat as a panel (#12) // void HUD_Chat(void) { - if(!autocvar_hud_panel_chat && !autocvar__hud_configure) + if(!autocvar__hud_configure) { - cvar_set("con_chatrect", "0"); - return; + if (!autocvar_hud_panel_chat) + { + if (!autocvar_con_chatrect) + cvar_set("con_chatrect", "0"); + return; + } + if(autocvar__con_chat_maximized) + if(!hud_draw_maximized) return; } + else + hud_configure_active_panel = HUD_PANEL_CHAT; - active_panel = HUD_PANEL_CHAT; HUD_Panel_UpdateCvars(chat); + HUD_Panel_ApplyFadeAlpha(); if(autocvar__con_chat_maximized && !autocvar__hud_configure) // draw at full screen height if maximized { @@ -4737,7 +3950,7 @@ void HUD_Chat(void) } } } - panel_bg_alpha = max(0.75, panel_bg_alpha); // force an alpha of at least 0.75 + panel_bg_alpha = max(0.75, panel_bg_alpha); // force an theAlpha of at least 0.75 } vector pos, mySize; @@ -4752,7 +3965,8 @@ void HUD_Chat(void) mySize -= '2 2 0' * panel_bg_padding; } - cvar_set("con_chatrect", "1"); + if (!autocvar_con_chatrect) + cvar_set("con_chatrect", "1"); cvar_set("con_chatrect_x", ftos(pos_x/vid_conwidth)); cvar_set("con_chatrect_y", ftos(pos_y/vid_conheight)); @@ -4762,9 +3976,9 @@ void HUD_Chat(void) if(autocvar__hud_configure) { - float chatsize; - chatsize = autocvar_con_chatsize; - cvar_set("con_chatrect_x", "9001"); // over 9000, we'll fake it instead for more control over alpha and such + vector chatsize; + chatsize = '1 1 0' * autocvar_con_chatsize; + cvar_set("con_chatrect_x", "9001"); // over 9000, we'll fake it instead for more control over theAlpha and such float i, a; for(i = 0; i < autocvar_con_chat; ++i) { @@ -4772,7 +3986,8 @@ void HUD_Chat(void) a = panel_fg_alpha; else a = panel_fg_alpha * floor(((i + 1) * 7 + autocvar_con_chattime)/45); - drawcolorcodedstring(pos + eY * i * chatsize, textShortenToWidth("^3Player^7: This is the chat area.", mySize_x, '1 1 0' * chatsize, stringwidth_colors), '1 1 0' * chatsize, a, DRAWFLAG_NORMAL); + drawcolorcodedstring(pos, textShortenToWidth(_("^3Player^7: This is the chat area."), mySize_x, chatsize, stringwidth_colors), chatsize, a, DRAWFLAG_NORMAL); + pos_y += chatsize_y; } } } @@ -4788,11 +4003,15 @@ float frametimeavg1; // 1 frame ago float frametimeavg2; // 2 frames ago void HUD_EngineInfo(void) { - if(!autocvar_hud_panel_engineinfo && !autocvar__hud_configure) - return; + if(!autocvar__hud_configure) + { + if(!autocvar_hud_panel_engineinfo) return; + } + else + hud_configure_active_panel = HUD_PANEL_ENGINEINFO; - active_panel = HUD_PANEL_ENGINEINFO; HUD_Panel_UpdateCvars(engineinfo); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -4835,9 +4054,7 @@ void HUD_EngineInfo(void) vector color; color = HUD_Get_Num_Color (prevfps, 100); - drawfont = hud_bigfont; - drawstring_aspect(pos, strcat("FPS: ", ftos_decimals(prevfps, autocvar_hud_panel_engineinfo_framecounter_decimals)), mySize, color, panel_fg_alpha, DRAWFLAG_NORMAL); - drawfont = hud_font; + drawstring_aspect(pos, sprintf(_("FPS: %.*f"), autocvar_hud_panel_engineinfo_framecounter_decimals, prevfps), mySize, color, panel_fg_alpha, DRAWFLAG_NORMAL); } // Info messages panel (#14) @@ -4849,11 +4066,15 @@ void HUD_EngineInfo(void) o_y += fontsize_y; void HUD_InfoMessages(void) { - if(!autocvar_hud_panel_infomessages && !autocvar__hud_configure) - return; + if(!autocvar__hud_configure) + { + if(!autocvar_hud_panel_infomessages) return; + } + else + hud_configure_active_panel = HUD_PANEL_INFOMESSAGES; - active_panel = HUD_PANEL_INFOMESSAGES; HUD_Panel_UpdateCvars(infomessages); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -4891,52 +4112,54 @@ void HUD_InfoMessages(void) fontsize = '0.20 0.20 0' * mySize_y; float a; - if(spectatee_status != 0) - a = 1; - else - a = panel_fg_alpha; + a = panel_fg_alpha; string s; if(!autocvar__hud_configure) { if(spectatee_status && !intermission) { + a = 1; if(spectatee_status == -1) - s = "^1Observing"; + s = _("^1Observing"); else - s = strcat("^1Spectating: ^7", GetPlayerName(spectatee_status - 1)); +#ifdef COMPAT_XON050_ENGINE + s = sprintf(_("^1Spectating: ^7%s"), GetPlayerName(spectatee_status - 1)); +#else + s = sprintf(_("^1Spectating: ^7%s"), GetPlayerName(player_localentnum - 1)); +#endif drawInfoMessage(s) if(spectatee_status == -1) - s = strcat("^1Press ^3", getcommandkey("primary fire", "+fire"), "^1 to spectate"); + s = sprintf(_("^1Press ^3%s^1 to spectate"), getcommandkey("primary fire", "+fire")); else - s = strcat("^1Press ^3", getcommandkey("primary fire", "+fire"), "^1 for another player"); + s = sprintf(_("^1Press ^3%s^1 for another player"), getcommandkey("primary fire", "+fire")); drawInfoMessage(s) if(spectatee_status == -1) - s = strcat("^1Use ^3", getcommandkey("next weapon", "weapnext"), "^1 or ^3", getcommandkey("previous weapon", "weapprev"), "^1 to change the speed"); + s = sprintf(_("^1Use ^3%s^1 or ^3%s^1 to change the speed"), getcommandkey("next weapon", "weapnext"), getcommandkey("previous weapon", "weapprev")); else - s = strcat("^1Press ^3", getcommandkey("secondary fire", "+fire2"), "^1 to observe"); + s = sprintf(_("^1Press ^3%s^1 to observe"), getcommandkey("secondary fire", "+fire2")); drawInfoMessage(s) - s = strcat("^1Press ^3", getcommandkey("server info", "+show_info"), "^1 for gamemode info"); + s = sprintf(_("^1Press ^3%s^1 for gamemode info"), getcommandkey("server info", "+show_info")); drawInfoMessage(s) - if(gametype == GAME_ARENA) - s = "^1Wait for your turn to join"; - else if(gametype == GAME_LMS) + if(gametype == MAPINFO_TYPE_ARENA) + s = _("^1Wait for your turn to join"); + else if(gametype == MAPINFO_TYPE_LMS) { entity sk; - sk = playerslots[player_localentnum - 1]; + sk = playerslots[player_localnum]; if(sk.(scores[ps_primary]) >= 666) - s = "^1Match has already begun"; + s = _("^1Match has already begun"); else if(sk.(scores[ps_primary]) > 0) - s = "^1You have no more lives left"; + s = _("^1You have no more lives left"); else - s = strcat("^1Press ^3", getcommandkey("jump", "+jump"), "^1 to join"); + s = sprintf(_("^1Press ^3%s^1 to join"), getcommandkey("jump", "+jump")); } else - s = strcat("^1Press ^3", getcommandkey("jump", "+jump"), "^1 to join"); + s = sprintf(_("^1Press ^3%s^1 to join"), getcommandkey("jump", "+jump")); drawInfoMessage(s) //show restart countdown: @@ -4944,14 +4167,14 @@ void HUD_InfoMessages(void) float countdown; //we need to ceil, otherwise the countdown would be off by .5 when using round() countdown = ceil(getstatf(STAT_GAMESTARTTIME) - time); - s = strcat("^1Game starts in ^3", ftos(countdown), "^1 seconds"); + s = sprintf(_("^1Game starts in ^3%d^1 seconds"), countdown); drawcolorcodedstring(o, s, fontsize, a, DRAWFLAG_NORMAL); o_y += fontsize_y; } } if(warmup_stage && !intermission) { - s = "^2Currently in ^1warmup^2 stage!"; + s = _("^2Currently in ^1warmup^2 stage!"); drawInfoMessage(s) } @@ -4966,26 +4189,26 @@ void HUD_InfoMessages(void) if(ready_waiting_for_me) { if(warmup_stage) - s = strcat(blinkcolor, "Press ^3", getcommandkey("ready", "ready"), blinkcolor, " to end warmup"); + s = sprintf(_("%sPress ^3%s%s to end warmup"), blinkcolor, getcommandkey("ready", "ready"), blinkcolor); else - s = strcat(blinkcolor, "Press ^3", getcommandkey("ready", "ready"), blinkcolor, " once you are ready"); + s = sprintf(_("%sPress ^3%s%s once you are ready"), blinkcolor, getcommandkey("ready", "ready"), blinkcolor); } else { if(warmup_stage) - s = strcat("^2Waiting for others to ready up to end warmup..."); + s = _("^2Waiting for others to ready up to end warmup..."); else - s = strcat("^2Waiting for others to ready up..."); + s = _("^2Waiting for others to ready up..."); } drawInfoMessage(s) } else if(warmup_stage && !intermission && !spectatee_status) { - s = strcat("^2Press ^3", getcommandkey("ready", "ready"), "^2 to end warmup"); + s = sprintf(_("^2Press ^3%s^2 to end warmup"), getcommandkey("ready", "ready")); drawInfoMessage(s) } - if(teamplay && !intermission && !spectatee_status && gametype != GAME_CA && teamnagger) + if(teamplay && !intermission && !spectatee_status && gametype != MAPINFO_TYPE_CA && teamnagger) { float ts_min, ts_max; tm = teams.sort_next; @@ -5002,12 +4225,12 @@ void HUD_InfoMessages(void) } if ((ts_max - ts_min) > 1) { - s = strcat(blinkcolor, "Teamnumbers are unbalanced!"); + s = strcat(blinkcolor, _("Teamnumbers are unbalanced!")); tm = GetTeam(myteam, false); if (tm) if (tm.team != COLOR_SPECTATOR) if (tm.team_size == ts_max) - s = strcat(s, " Press ^3", getcommandkey("team menu", "menu_showteamselect"), blinkcolor, " to adjust"); + s = strcat(s, sprintf(_(" Press ^3%s%s to adjust"), getcommandkey("team menu", "menu_showteamselect"), blinkcolor)); drawInfoMessage(s) } } @@ -5015,125 +4238,557 @@ void HUD_InfoMessages(void) } else { - s = "^7Press ^3ESC ^7to show HUD options."; + s = _("^7Press ^3ESC ^7to show HUD options."); drawInfoMessage(s) - s = "^3Doubleclick ^7a panel for panel-specific options."; + s = _("^3Doubleclick ^7a panel for panel-specific options."); drawInfoMessage(s) - s = "^3CTRL ^7to disable collision testing, ^3SHIFT ^7and"; + s = _("^3CTRL ^7to disable collision testing, ^3SHIFT ^7and"); drawInfoMessage(s) - s = "^3ALT ^7+ ^3ARROW KEYS ^7for fine adjustments."; + s = _("^3ALT ^7+ ^3ARROW KEYS ^7for fine adjustments."); drawInfoMessage(s) } } -/* -================== -Main HUD system -================== -*/ - -void HUD_ShowSpeed(void) +// Physics panel (#15) +// +vector acc_prevspeed; +float acc_prevtime, acc_avg, top_speed, top_speed_time; +void HUD_Physics(void) { - vector numsize; - float pos, conversion_factor; - string speed, zspeed, unit; + if(!autocvar__hud_configure) + { + if(!autocvar_hud_panel_physics) return; + if(spectatee_status == -1 && (autocvar_hud_panel_physics == 1 || autocvar_hud_panel_physics == 3)) return; + if(autocvar_hud_panel_physics == 3 && !(gametype == MAPINFO_TYPE_RACE || gametype == MAPINFO_TYPE_CTS)) return; + } + else + hud_configure_active_panel = HUD_PANEL_PHYSICS; + + HUD_Panel_UpdateCvars(physics); + HUD_Panel_ApplyFadeAlpha(); + + HUD_Panel_DrawBg(1); + if(panel_bg_padding) + { + panel_pos += '1 1 0' * panel_bg_padding; + panel_size -= '2 2 0' * panel_bg_padding; + } - switch(autocvar_cl_showspeed_unit) + //compute speed + float speed, conversion_factor; + string unit; + + switch(autocvar_hud_panel_physics_speed_unit) { default: - case 0: - unit = ""; - conversion_factor = 1.0; - break; case 1: - unit = " qu/s"; + unit = _(" qu/s"); conversion_factor = 1.0; break; case 2: - unit = " m/s"; + unit = _(" m/s"); conversion_factor = 0.0254; break; case 3: - unit = " km/h"; + unit = _(" km/h"); conversion_factor = 0.0254 * 3.6; break; case 4: - unit = " mph"; + unit = _(" mph"); conversion_factor = 0.0254 * 3.6 * 0.6213711922; break; case 5: - unit = " knots"; + unit = _(" knots"); conversion_factor = 0.0254 * 1.943844492; // 1 m/s = 1.943844492 knots, because 1 knot = 1.852 km/h break; } - speed = strcat(ftos(floor( vlen(pmove_vel - pmove_vel_z * '0 0 1') * conversion_factor + 0.5 )), unit); + float max_speed = floor( autocvar_hud_panel_physics_speed_max * conversion_factor + 0.5 ); + if (autocvar__hud_configure) + speed = floor( max_speed * 0.65 + 0.5 ); + else if(autocvar_hud_panel_physics_speed_vertical) + speed = floor( vlen(pmove_vel) * conversion_factor + 0.5 ); + else + speed = floor( vlen(pmove_vel - pmove_vel_z * '0 0 1') * conversion_factor + 0.5 ); + + //compute acceleration + float acceleration, f; + if (autocvar__hud_configure) + acceleration = autocvar_hud_panel_physics_acceleration_max * 0.3; + else + { + // 1 m/s = 0.0254 qu/s; 1 g = 9.80665 m/s^2 + f = time - acc_prevtime; + if(autocvar_hud_panel_physics_acceleration_vertical) + acceleration = (vlen(pmove_vel) - vlen(acc_prevspeed)); + else + acceleration = (vlen(pmove_vel - '0 0 1' * pmove_vel_z) - vlen(acc_prevspeed - '0 0 1' * acc_prevspeed_z)); + + acceleration = acceleration * (1 / max(0.0001, f)) * (0.0254 / 9.80665); + + acc_prevspeed = pmove_vel; + acc_prevtime = time; + + f = bound(0, f * 10, 1); + acc_avg = acc_avg * (1 - f) + acceleration * f; + } + + //compute layout + float panel_ar = panel_size_x/panel_size_y; + vector speed_offset, acceleration_offset; + if (panel_ar >= 5) + { + panel_size_x *= 0.5; + if (autocvar_hud_panel_physics_flip) + speed_offset_x = panel_size_x; + else + acceleration_offset_x = panel_size_x; + } + else + { + panel_size_y *= 0.5; + if (autocvar_hud_panel_physics_flip) + speed_offset_y = panel_size_y; + else + acceleration_offset_y = panel_size_y; + } + float speed_baralign, acceleration_baralign; + if (autocvar_hud_panel_physics_baralign == 1) + acceleration_baralign = speed_baralign = 1; + else if(autocvar_hud_panel_physics_baralign == 4) + acceleration_baralign = speed_baralign = 2; + else if (autocvar_hud_panel_physics_flip) + { + acceleration_baralign = (autocvar_hud_panel_physics_baralign == 2); + speed_baralign = (autocvar_hud_panel_physics_baralign == 3); + } + else + { + speed_baralign = (autocvar_hud_panel_physics_baralign == 2); + acceleration_baralign = (autocvar_hud_panel_physics_baralign == 3); + } + if (autocvar_hud_panel_physics_acceleration_mode == 0) + acceleration_baralign = 3; //override hud_panel_physics_baralign value for acceleration + + //draw speed + if(speed) + if(autocvar_hud_panel_physics_progressbar == 1 || autocvar_hud_panel_physics_progressbar == 2) + { + HUD_Panel_GetProgressBarColor(speed); + HUD_Panel_DrawProgressBar(panel_pos + speed_offset, panel_size, "progressbar", speed/max_speed, 0, speed_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); + } + vector tmp_offset, tmp_size; + if (autocvar_hud_panel_physics_text == 1 || autocvar_hud_panel_physics_text == 2) + { + tmp_size_x = panel_size_x * 0.75; + tmp_size_y = panel_size_y; + if (speed_baralign) + tmp_offset_x = panel_size_x - tmp_size_x; + //else + //tmp_offset_x = 0; + drawstring_aspect(panel_pos + speed_offset + tmp_offset, ftos(speed), tmp_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + + //draw speed unit + if (speed_baralign) + tmp_offset_x = 0; + else + tmp_offset_x = tmp_size_x; + if (autocvar_hud_panel_physics_speed_unit_show) + { + //tmp_offset_y = 0; + tmp_size_x = panel_size_x * (1 - 0.75); + tmp_size_y = panel_size_y * 0.4; + drawstring_aspect(panel_pos + speed_offset + tmp_offset, unit, tmp_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + } + } + + //compute and draw top speed + if (autocvar_hud_panel_physics_topspeed) + if (autocvar_hud_panel_physics_text == 1 || autocvar_hud_panel_physics_text == 2) + { + if (autocvar__hud_configure) + { + top_speed = floor( max_speed * 0.75 + 0.5 ); + f = 1; + } + else + { + if (speed >= top_speed) + { + top_speed = speed; + top_speed_time = time; + } + if (top_speed != 0) + { + f = max(1, autocvar_hud_panel_physics_topspeed_time); + // divide by f to make it start from 1 + f = cos( ((time - top_speed_time) / f) * PI/2 ); + } + else //hide top speed 0, it would be stupid + f = 0; + } + if (f > 0) + { + //top speed progressbar peak + if(speed < top_speed) + if(autocvar_hud_panel_physics_progressbar == 1 || autocvar_hud_panel_physics_progressbar == 2) + { + float peak_offset_x; + vector peak_size; + if (speed_baralign == 0) + peak_offset_x = min(top_speed, max_speed)/max_speed * panel_size_x; + else if (speed_baralign == 1) + peak_offset_x = (1 - min(top_speed, max_speed)/max_speed) * panel_size_x; + else if (speed_baralign == 2) + peak_offset_x = min(top_speed, max_speed)/max_speed * panel_size_x * 0.5; + //if speed is not 0 the speed progressbar already fetched the color + if (speed == 0) + HUD_Panel_GetProgressBarColor(speed); + peak_size_x = floor(panel_size_x * 0.01 + 1.5); + peak_size_y = panel_size_y; + if (speed_baralign == 2) // draw two peaks, on both sides + { + drawfill(panel_pos + speed_offset + eX * (0.5 * panel_size_x + peak_offset_x - peak_size_x), peak_size, progressbar_color, f * autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); + drawfill(panel_pos + speed_offset + eX * (0.5 * panel_size_x - peak_offset_x + peak_size_x), peak_size, progressbar_color, f * autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); + } + else + drawfill(panel_pos + speed_offset + eX * (peak_offset_x - peak_size_x), peak_size, progressbar_color, f * autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); + } + + //top speed + tmp_offset_y = panel_size_y * 0.4; + tmp_size_x = panel_size_x * (1 - 0.75); + tmp_size_y = panel_size_y - tmp_offset_y; + drawstring_aspect(panel_pos + speed_offset + tmp_offset, ftos(top_speed), tmp_size, '1 0 0', f * panel_fg_alpha, DRAWFLAG_NORMAL); + } + else + top_speed = 0; + } + + //draw acceleration + if(acceleration) + if(autocvar_hud_panel_physics_progressbar == 1 || autocvar_hud_panel_physics_progressbar == 3) + { + if (acceleration < 0) + HUD_Panel_GetProgressBarColor(acceleration_neg); + else + HUD_Panel_GetProgressBarColor(acceleration); + HUD_Panel_DrawProgressBar(panel_pos + acceleration_offset, panel_size, "accelbar", acceleration/autocvar_hud_panel_physics_acceleration_max, 0, acceleration_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); + } + if (autocvar_hud_panel_physics_text == 1 || autocvar_hud_panel_physics_text == 3) + drawstring_aspect(panel_pos + acceleration_offset, strcat(ftos_decimals(acceleration, 2), "g"), panel_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); +} + +// CenterPrint (#16) +// +#define CENTERPRINT_MAX_MSGS 10 +#define CENTERPRINT_MAX_ENTRIES 50 +#define CENTERPRINT_SPACING 0.7 +float cpm_index; +string centerprint_messages[CENTERPRINT_MAX_MSGS]; +float centerprint_msgID[CENTERPRINT_MAX_MSGS]; +float centerprint_time[CENTERPRINT_MAX_MSGS]; +float centerprint_expire_time[CENTERPRINT_MAX_MSGS]; +float centerprint_countdown_num[CENTERPRINT_MAX_MSGS]; +float centerprint_showing; + +void centerprint_generic(float new_id, string strMessage, float duration, float countdown_num) +{ + float i, j; + + if(strMessage == "" && new_id == 0) + return; + + // strip trailing newlines + j = strlen(strMessage) - 1; + while(substring(strMessage, j, 1) == "\n" && j >= 0) + --j; + if (j < strlen(strMessage) - 1) + strMessage = substring(strMessage, 0, j + 1); + + if(strMessage == "" && new_id == 0) + return; + + // strip leading newlines + j = 0; + while(substring(strMessage, j, 1) == "\n" && j < strlen(strMessage)) + ++j; + if (j > 0) + strMessage = substring(strMessage, j, strlen(strMessage) - j); - numsize_x = numsize_y = autocvar_cl_showspeed_size; - pos = (vid_conheight - numsize_y) * autocvar_cl_showspeed_position; + if(strMessage == "" && new_id == 0) + return; - drawfont = hud_bigfont; - drawstringcenter(eX + pos * eY, speed, numsize, '1 1 1', autocvar_hud_panel_fg_alpha * hud_fade_alpha, DRAWFLAG_NORMAL); + if (!centerprint_showing) + centerprint_showing = TRUE; - if (autocvar_cl_showspeed_z == 1) { - zspeed = strcat(ftos(fabs(floor( pmove_vel_z * conversion_factor + 0.5 ))), unit); - drawstringcenter(eX + pos * eY + numsize_y * eY, zspeed, numsize * 0.5, '1 1 1', autocvar_hud_panel_fg_alpha * hud_fade_alpha, DRAWFLAG_NORMAL); + for (i=0, j=cpm_index; i<CENTERPRINT_MAX_MSGS; ++i, ++j) + { + if (j == CENTERPRINT_MAX_MSGS) + j = 0; + if (new_id && new_id == centerprint_msgID[j]) + { + if (strMessage == "" && centerprint_messages[j] != "" && centerprint_countdown_num[j] == 0) + { + // fade out the current msg (duration and countdown_num are ignored) + centerprint_time[j] = min(5, autocvar_hud_panel_centerprint_fade_out); + if (centerprint_expire_time[j] > time + min(5, autocvar_hud_panel_centerprint_fade_out) || centerprint_expire_time[j] < time) + centerprint_expire_time[j] = time + min(5, autocvar_hud_panel_centerprint_fade_out); + return; + } + break; // found a msg with the same id, at position j + } } - drawfont = hud_font; + if (i == CENTERPRINT_MAX_MSGS) + { + // a msg with the same id was not found, add the msg at the next position + --cpm_index; + if (cpm_index == -1) + cpm_index = CENTERPRINT_MAX_MSGS - 1; + j = cpm_index; + } + if(centerprint_messages[j]) + strunzone(centerprint_messages[j]); + centerprint_messages[j] = strzone(strMessage); + centerprint_msgID[j] = new_id; + if (duration < 0) + centerprint_time[j] = -1; + else + { + if(duration == 0) + duration = max(1, autocvar_hud_panel_centerprint_time); + centerprint_time[j] = duration; + centerprint_expire_time[j] = time + duration; + } + centerprint_countdown_num[j] = countdown_num; } -vector acc_prevspeed; -float acc_prevtime; -float acc_avg; +void centerprint_hud(string strMessage) +{ + centerprint_generic(0, strMessage, autocvar_hud_panel_centerprint_time, 0); +} -void HUD_ShowAcceleration(void) +void reset_centerprint_messages(void) +{ + float i; + for (i=0; i<CENTERPRINT_MAX_MSGS; ++i) + { + centerprint_expire_time[i] = 0; + centerprint_time[i] = 1; + centerprint_msgID[i] = 0; + if(centerprint_messages[i]) + strunzone(centerprint_messages[i]); + centerprint_messages[i] = string_null; + } +} +float hud_configure_cp_generation_time; +void HUD_CenterPrint (void) { - float acceleration, sz, scale, alpha, f; - vector pos, top, rgb; - top_x = vid_conwidth/2; - top_y = 0; - - f = time - acc_prevtime; - if(autocvar_cl_showacceleration_z) - acceleration = (vlen(pmove_vel) - vlen(acc_prevspeed)) * (1 / f); + if(!autocvar__hud_configure) + { + if(!autocvar_hud_panel_centerprint) return; + + if (hud_configure_prev && hud_configure_prev != -1) + reset_centerprint_messages(); + } else - acceleration = (vlen(pmove_vel - '0 0 1' * pmove_vel_z) - vlen(acc_prevspeed - '0 0 1' * acc_prevspeed_z)) * (1 / f); - acc_prevspeed = pmove_vel; - acc_prevtime = time; - - f = bound(0, f * 10, 1); - acc_avg = acc_avg * (1 - f) + acceleration * f; - acceleration = acc_avg / getstatf(STAT_MOVEVARS_MAXSPEED); - if (acceleration == 0) + { + hud_configure_active_panel = HUD_PANEL_CENTERPRINT; + + if (!hud_configure_prev) + reset_centerprint_messages(); + if (time > hud_configure_cp_generation_time) + { + float r; + r = random(); + if (r > 0.9) + centerprint_generic(floor(r*1000), strcat(sprintf("^3Countdown message at time %s", seconds_tostring(time)), ", seconds left: %d"), 1, 10); + else if (r > 0.8) + centerprint_generic(0, sprintf("^1Multiline message at time %s that\n^1lasts longer than normal", seconds_tostring(time)), 20, 0); + else + centerprint_hud(sprintf("Message at time %s", seconds_tostring(time))); + hud_configure_cp_generation_time = time + 1 + random()*4; + } + } + + HUD_Panel_UpdateCvars(centerprint); + + // this panel doesn't fade when showing the scoreboard + if(autocvar__menu_alpha) + HUD_Panel_ApplyFadeAlpha(); + + if(scoreboard_fade_alpha) + { + // move the panel below the scoreboard + if (scoreboard_bottom >= 0.96 * vid_conheight) + return; + vector target_pos; + + target_pos = eY * scoreboard_bottom + eX * 0.5 * (vid_conwidth - panel_size_x); + + if(target_pos_y > panel_pos_y) + { + panel_pos = panel_pos + (target_pos - panel_pos) * sqrt(scoreboard_fade_alpha); + panel_size_y = min(panel_size_y, vid_conheight - scoreboard_bottom); + } + } + + HUD_Panel_DrawBg(1); + + if (!centerprint_showing) return; - pos = top - sz/2 * eY + (autocvar_cl_showacceleration_position * vid_conheight) * eY; + if(panel_bg_padding) + { + panel_pos += '1 1 0' * panel_bg_padding; + panel_size -= '2 2 0' * panel_bg_padding; + } + + float entries, height; + vector fontsize; + // entries = bound(1, floor(CENTERPRINT_MAX_ENTRIES * 4 * panel_size_y/panel_size_x), CENTERPRINT_MAX_ENTRIES); + // height = panel_size_y/entries; + // fontsize = '1 1 0' * height; + height = vid_conheight/50 * autocvar_hud_panel_centerprint_fontscale; + fontsize = '1 1 0' * height; + entries = bound(1, floor(panel_size_y/height), CENTERPRINT_MAX_ENTRIES); + + float i, j, k, n; + float a, sz, align, current_msg_pos_y, msg_size; + vector pos; + string ts; + + n = -1; // if no msg will be displayed, n stays -1 - sz = autocvar_cl_showacceleration_size; - scale = autocvar_cl_showacceleration_scale; - alpha = autocvar_cl_showacceleration_alpha; - if (autocvar_cl_showacceleration_color_custom) - rgb = stov(autocvar_cl_showacceleration_color); - else { - if (acceleration < 0) - rgb = '1 .5 .5' - '0 .5 .5' * bound(0, -acceleration * 0.2, 1); + pos = panel_pos; + if (autocvar_hud_panel_centerprint_flip) + pos_y += panel_size_y; + align = bound(0, autocvar_hud_panel_centerprint_align, 1); + for (i=0, j=cpm_index; i<CENTERPRINT_MAX_MSGS; ++i, ++j) + { + if (j == CENTERPRINT_MAX_MSGS) + j = 0; + if (centerprint_expire_time[j] <= time) + { + if (centerprint_countdown_num[j] && centerprint_time[j] > 0) + { + centerprint_countdown_num[j] = centerprint_countdown_num[j] - 1; + if (centerprint_countdown_num[j] == 0) + continue; + centerprint_expire_time[j] = centerprint_expire_time[j] + centerprint_time[j]; + } + else + continue; + } + + // fade the centerprint_hud in/out + if (centerprint_time[j] < 0 || centerprint_expire_time[j] - autocvar_hud_panel_centerprint_fade_out > time) + a = bound(0, (time - (centerprint_expire_time[j] - centerprint_time[j])) / max(0.0001, autocvar_hud_panel_centerprint_fade_in), 1); + else if (centerprint_expire_time[j] > time) + a = (centerprint_expire_time[j] - time) / max(0.0001, autocvar_hud_panel_centerprint_fade_out); + + // set the size from fading in/out before subsequent fading + sz = autocvar_hud_panel_centerprint_fade_minfontsize + a * (1 - autocvar_hud_panel_centerprint_fade_minfontsize); + + // also fade it based on positioning + if(autocvar_hud_panel_centerprint_fade_subsequent) + { + a = a * bound(autocvar_hud_panel_centerprint_fade_subsequent_passone_minalpha, (1 - (i / max(1, autocvar_hud_panel_centerprint_fade_subsequent_passone))), 1); // pass one: all messages after the first have half theAlpha + a = a * bound(autocvar_hud_panel_centerprint_fade_subsequent_passtwo_minalpha, (1 - (i / max(1, autocvar_hud_panel_centerprint_fade_subsequent_passtwo))), 1); // pass two: after that, gradually lower theAlpha even more for each message + } + + // finally set the size based on the new theAlpha from subsequent fading + sz = sz * (autocvar_hud_panel_centerprint_fade_subsequent_minfontsize + a * (1 - autocvar_hud_panel_centerprint_fade_subsequent_minfontsize)); + drawfontscale = sz * '1 1 0'; + + if (centerprint_countdown_num[j]) + n = tokenizebyseparator(sprintf(centerprint_messages[j], centerprint_countdown_num[j]), "\n"); else - rgb = '.5 1 .5' - '.5 0 .5' * bound(0, +acceleration * 0.2, 1); - } + n = tokenizebyseparator(centerprint_messages[j], "\n"); - if (acceleration > 0) - HUD_Panel_DrawProgressBar(pos, eX * (vid_conwidth - pos_x) + eY * sz, "statusbar", 0, 0, acceleration * scale, rgb, alpha * autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); - else - HUD_Panel_DrawProgressBar(eY * pos_y, eX * pos_x + eY * sz, "statusbar", 0, 1, -acceleration * scale, rgb, alpha * autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL); + if (autocvar_hud_panel_centerprint_flip) + { + // check if the message can be entirely shown + for(k = 0; k < n; ++k) + { + getWrappedLine_remaining = argv(k); + while(getWrappedLine_remaining) + { + ts = getWrappedLine(panel_size_x * sz, fontsize, stringwidth_colors); + if (ts != "") + pos_y -= fontsize_y; + else + pos_y -= fontsize_y * CENTERPRINT_SPACING/2; + } + } + current_msg_pos_y = pos_y; // save starting pos (first line) of the current message + } + + msg_size = pos_y; + for(k = 0; k < n; ++k) + { + getWrappedLine_remaining = argv(k); + while(getWrappedLine_remaining) + { + ts = getWrappedLine(panel_size_x * sz, fontsize, stringwidth_colors); + if (ts != "") + { + if (align) + pos_x = panel_pos_x + (panel_size_x - stringwidth(ts, TRUE, fontsize)) * align; + drawcolorcodedstring(pos + eY * 0.5 * (1 - sz) * fontsize_y, ts, fontsize, a * panel_fg_alpha, DRAWFLAG_NORMAL); + pos_y += fontsize_y; + } + else + pos_y += fontsize_y * CENTERPRINT_SPACING/2; + } + } + msg_size = pos_y - msg_size; + if (autocvar_hud_panel_centerprint_flip) + { + pos_y = current_msg_pos_y - CENTERPRINT_SPACING * fontsize_y; + if (a < 1 && centerprint_msgID[j] == 0) // messages with id can be replaced just after they are faded out, so never move over them the next messages + pos_y += (msg_size + CENTERPRINT_SPACING * fontsize_y) * (1 - sqrt(sz)); + + if (pos_y < panel_pos_y) // check if the next message can be shown + { + drawfontscale = '1 1 0'; + return; + } + } + else + { + pos_y += CENTERPRINT_SPACING * fontsize_y; + if (a < 1 && centerprint_msgID[j] == 0) // messages with id can be replaced just after they are faded out, so never move over them the next messages + pos_y -= (msg_size + CENTERPRINT_SPACING * fontsize_y) * (1 - sqrt(sz)); + + if(pos_y > panel_pos_y + panel_size_y - fontsize_y) // check if the next message can be shown + { + drawfontscale = '1 1 0'; + return; + } + } + } + drawfontscale = '1 1 0'; + if (n == -1) + { + centerprint_showing = FALSE; + reset_centerprint_messages(); + } } +/* +================== +Main HUD system +================== +*/ + void HUD_Reset (void) { // reset gametype specific icons - if(gametype == GAME_KEYHUNT) + if(gametype == MAPINFO_TYPE_KEYHUNT) HUD_Mod_KH_Reset(); - else if(gametype == GAME_CTF) + else if(gametype == MAPINFO_TYPE_CTF) HUD_Mod_CTF_Reset(); } @@ -5169,12 +4824,16 @@ switch (id) {\ HUD_EngineInfo(); break;\ case (HUD_PANEL_INFOMESSAGES):\ HUD_InfoMessages(); break;\ + case (HUD_PANEL_PHYSICS):\ + HUD_Physics(); break;\ + case (HUD_PANEL_CENTERPRINT):\ + HUD_CenterPrint(); break;\ } ENDS_WITH_CURLY_BRACE void HUD_Main (void) { float i; - // global hud alpha fade + // global hud theAlpha fade if(menu_enabled == 1) hud_fade_alpha = 1; else @@ -5184,11 +4843,28 @@ void HUD_Main (void) hud_fade_alpha = (1 - scoreboard_fade_alpha); if(intermission == 2) // no hud during mapvote + { + if (autocvar__hud_configure) //force exit from hud config + { + if (menu_enabled) + { + menu_enabled = 0; + localcmd("togglemenu\n"); + } + cvar_set("_hud_configure", "0"); + } hud_fade_alpha = 0; + } else if(autocvar__menu_alpha == 0 && scoreboard_fade_alpha == 0) hud_fade_alpha = 1; - hud_fontsize = HUD_GetFontsize("hud_fontsize"); + // panels that we want to be active together with the scoreboard + // they must call HUD_Panel_ApplyFadeAlpha(); only when showing the menu + if(scoreboard_fade_alpha == 1) + { + HUD_CenterPrint(); + return; + } if(!autocvar__hud_configure && !hud_fade_alpha) return; @@ -5204,19 +4880,23 @@ void HUD_Main (void) // HUD configure visible grid if(autocvar__hud_configure && autocvar_hud_configure_grid && autocvar_hud_configure_grid_alpha) { + hud_configure_gridSize_x = bound(0.005, cvar("hud_configure_grid_xsize"), 0.2); + hud_configure_gridSize_y = bound(0.005, cvar("hud_configure_grid_ysize"), 0.2); + hud_configure_realGridSize_x = hud_configure_gridSize_x * vid_conwidth; + hud_configure_realGridSize_y = hud_configure_gridSize_y * vid_conheight; // x-axis - for(i = 0; i < 1/bound(0.005, autocvar_hud_configure_grid_xsize, 0.2); ++i) - { - drawfill(eX * i * vid_conwidth * bound(0.005, autocvar_hud_configure_grid_xsize, 0.2), eX + eY * vid_conheight, '0.5 0.5 0.5', autocvar_hud_configure_grid_alpha, DRAWFLAG_NORMAL); - } + for(i = 0; i < 1/hud_configure_gridSize_x; ++i) + drawfill(eX * i * hud_configure_realGridSize_x, eX + eY * vid_conheight, '0.5 0.5 0.5', autocvar_hud_configure_grid_alpha, DRAWFLAG_NORMAL); // y-axis - for(i = 0; i < 1/bound(0.005, autocvar_hud_configure_grid_ysize, 0.2); ++i) - { - drawfill(eY * i * vid_conheight * bound(0.005, autocvar_hud_configure_grid_ysize, 0.2), eY + eX * vid_conwidth, '0.5 0.5 0.5', autocvar_hud_configure_grid_alpha, DRAWFLAG_NORMAL); - } + for(i = 0; i < 1/hud_configure_gridSize_y; ++i) + drawfill(eY * i * hud_configure_realGridSize_y, eY + eX * vid_conwidth, '0.5 0.5 0.5', autocvar_hud_configure_grid_alpha, DRAWFLAG_NORMAL); } +#ifdef COMPAT_XON050_ENGINE current_player = (spectatee_status > 0) ? spectatee_status : player_localentnum; +#else + current_player = player_localentnum; +#endif // draw the dock if(autocvar_hud_dock != "" && autocvar_hud_dock != "0") @@ -5225,7 +4905,7 @@ void HUD_Main (void) vector color; float hud_dock_color_team = autocvar_hud_dock_color_team; if((teamplay) && hud_dock_color_team) { - f = stof(getplayerkey(current_player - 1, "colors")); + f = stof(getplayerkeyvalue(current_player - 1, "colors")); color = colormapPaletteColor(mod(f, 16), 1) * hud_dock_color_team; } else if(autocvar_hud_configure_teamcolorforced && autocvar__hud_configure && hud_dock_color_team) { @@ -5235,11 +4915,11 @@ void HUD_Main (void) { string hud_dock_color = autocvar_hud_dock_color; if(hud_dock_color == "shirt") { - f = stof(getplayerkey(current_player - 1, "colors")); + f = stof(getplayerkeyvalue(current_player - 1, "colors")); color = colormapPaletteColor(floor(f / 16), 0); } else if(hud_dock_color == "pants") { - f = stof(getplayerkey(current_player - 1, "colors")); + f = stof(getplayerkeyvalue(current_player - 1, "colors")); color = colormapPaletteColor(mod(f, 16), 1); } else @@ -5259,36 +4939,74 @@ void HUD_Main (void) // cache the panel order into the panel_order array if(autocvar__hud_panelorder != hud_panelorder_prev) { + for(i = 0; i < HUD_PANEL_NUM; ++i) + panel_order[i] = -1; + string s; + float p_num, warning; + float argc = tokenize_console(autocvar__hud_panelorder); + if (argc > HUD_PANEL_NUM) + warning = true; + //first detect wrong/missing panel numbers + for(i = 0; i < HUD_PANEL_NUM; ++i) { + p_num = stof(argv(i)); + if (p_num >= 0 && p_num < HUD_PANEL_NUM) { //correct panel number? + if (panel_order[p_num] == -1) //found for the first time? + s = strcat(s, ftos(p_num), " "); + panel_order[p_num] = 1; //mark as found + } + else + warning = true; + } + for(i = 0; i < HUD_PANEL_NUM; ++i) { + if (panel_order[i] == -1) { + warning = true; + s = strcat(s, ftos(i), " "); //add missing panel number + } + } + if (warning) + print(_("Automatically fixed wrong/missing panel numbers in _hud_panelorder\n")); + + cvar_set("_hud_panelorder", s); if(hud_panelorder_prev) strunzone(hud_panelorder_prev); - hud_panelorder_prev = strzone(autocvar__hud_panelorder); - tokenize_console(autocvar__hud_panelorder); + hud_panelorder_prev = strzone(s); + + //now properly set panel_order + tokenize_console(s); for(i = 0; i < HUD_PANEL_NUM; ++i) { panel_order[i] = stof(argv(i)); } } + + hud_draw_maximized = 0; // draw panels in order specified by panel_order array - for(i = HUD_PANEL_NUM - 1; i >= 0; --i) { - if(i != HUD_PANEL_CHAT || !autocvar__con_chat_maximized) // don't draw maximized chat panel twice! - HUD_DrawPanel(panel_order[i]); - } + for(i = HUD_PANEL_NUM - 1; i >= 0; --i) + HUD_DrawPanel(panel_order[i]); - // draw chat panel on top if it is maximized + hud_draw_maximized = 1; // panels that may be maximized must check this var + // draw maximized panels on top + if(hud_panel_radar_maximized) + HUD_Radar(); if(autocvar__con_chat_maximized) - HUD_Chat(); // HUD_DrawPanel(HUD_PANEL_CHAT); - - // TODO hud_'ify these - if (autocvar_cl_showspeed) - HUD_ShowSpeed(); - if (autocvar_cl_showacceleration) - HUD_ShowAcceleration(); + HUD_Chat(); - if (autocvar__hud_configure && spectatee_status && hud_configure_prev == -1) // try to join if we are in hud_configure mode, but still spectating, and in the first frame (in order to get rid of motd when launching a server via the menu "HUD Setup" button) - localcmd("cmd selectteam auto; cmd join\n"); + if(autocvar__hud_configure) + { + if(tab_panel != -1) + { + HUD_Panel_UpdatePosSizeForId(tab_panel) + drawfill(panel_pos - '1 1 0' * panel_bg_border, panel_size + '2 2 0' * panel_bg_border, '1 1 1', .2, DRAWFLAG_NORMAL); + } + if(highlightedPanel != -1) + { + HUD_Panel_UpdatePosSizeForId(highlightedPanel); + HUD_Panel_HlBorder(panel_bg_border + 1.5 * hlBorderSize, '0 0.5 1', 0.25 * (1 - autocvar__menu_alpha)); + } + } hud_configure_prev = autocvar__hud_configure; - if (!autocvar__hud_configure) // hud config mode disabled, enable normal alpha stuff again + if (!autocvar__hud_configure) // hud config mode disabled, enable normal theAlpha stuff again if (menu_enabled) menu_enabled = 0; } diff --git a/qcsrc/client/hud.qh b/qcsrc/client/hud.qh index 21e3746b56..16ccd0c79c 100644 --- a/qcsrc/client/hud.qh +++ b/qcsrc/client/hud.qh @@ -1,16 +1,14 @@ -float log(float f); - -vector centerprint_start; - float panel_order[HUD_PANEL_NUM]; string hud_panelorder_prev; +float hud_draw_maximized; +float hud_panel_radar_maximized; + vector mousepos; vector panel_click_distance; // mouse cursor distance from the top left corner of the panel (saved only upon a click) vector panel_click_resizeorigin; // coordinates for opposite point when resizing float resizeCorner; // 1 = topleft, 2 = topright, 3 = bottomleft, 4 = bottomright var float highlightedPanel = -1; -var float highlightedPanel_prev = -1; float highlightedAction; // 0 = nothing, 1 = move, 2 = resize const float BORDER_MULTIPLIER = 0.25; @@ -31,7 +29,8 @@ float complain_weapon_time; float ps_primary, ps_secondary; float ts_primary, ts_secondary; -float last_weapon; +float last_switchweapon; +float last_activeweapon; float weapontime; float weaponprevtime; @@ -39,6 +38,8 @@ float teamnagger; float hud_configure_checkcollisions; float hud_configure_prev; +noref vector hud_configure_gridSize; // fteqcc sucks +noref vector hud_configure_realGridSize; // fteqcc sucks float hudShiftState; const float S_SHIFT = 1; @@ -61,7 +62,7 @@ var vector panel_size_backup; var float highlightedPanel_copied = -1; //this is good only to know if there is something copied var vector panel_size_copied; -var float active_panel; // this panel has recently referred the UpdateCvars macro +var float hud_configure_active_panel; // this panel has recently referred the UpdateCvars macro var string panel_name; var float panel_enabled; var vector panel_pos; @@ -92,12 +93,15 @@ float current_player; progressbar_color = stov(cvar_string("hud_progressbar_" #item "_color")) #define HUD_Panel_GetProgressBarColorForString(item) \ switch(item) {\ - case "strength": HUD_Panel_GetProgressBarColor(strength); break;\ - case "shield": HUD_Panel_GetProgressBarColor(shield); break;\ case "health": HUD_Panel_GetProgressBarColor(health); break;\ case "armor": HUD_Panel_GetProgressBarColor(armor); break;\ + case "strength": HUD_Panel_GetProgressBarColor(strength); break;\ + case "shield": HUD_Panel_GetProgressBarColor(shield); break;\ case "fuel": HUD_Panel_GetProgressBarColor(fuel); break;\ case "nexball": HUD_Panel_GetProgressBarColor(nexball); break;\ + case "speed": HUD_Panel_GetProgressBarColor(speed); break;\ + case "acceleration": HUD_Panel_GetProgressBarColor(acceleration); break;\ + case "acceleration_neg": HUD_Panel_GetProgressBarColor(acceleration_neg); break;\ } ENDS_WITH_CURLY_BRACE // Get value for panel_bg: if "" fetch default, else use panel_bg_str @@ -127,7 +131,7 @@ if(!autocvar__hud_configure && panel_bg_str == "0") {\ // Get value for panel_bg_color: if "" fetch default, else use panel_bg_color. Convert pants, shirt or teamcolor into a vector. #define HUD_Panel_GetColor()\ if((teamplay) && panel_bg_color_team) {\ - panel_bg_color = colormapPaletteColor(mod(stof(getplayerkey(current_player - 1, "colors")), 16), 1) * panel_bg_color_team;\ + panel_bg_color = colormapPaletteColor(mod(stof(getplayerkeyvalue(current_player - 1, "colors")), 16), 1) * panel_bg_color_team;\ } else if (autocvar_hud_configure_teamcolorforced && autocvar__hud_configure && panel_bg_color_team) {\ panel_bg_color = '1 0 0' * panel_bg_color_team;\ } else {\ @@ -135,9 +139,9 @@ if((teamplay) && panel_bg_color_team) {\ panel_bg_color = autocvar_hud_panel_bg_color;\ } else {\ if(panel_bg_color_str == "shirt") {\ - panel_bg_color = colormapPaletteColor(floor(stof(getplayerkey(current_player - 1, "colors")) / 16), 0);\ + panel_bg_color = colormapPaletteColor(floor(stof(getplayerkeyvalue(current_player - 1, "colors")) / 16), 0);\ } else if(panel_bg_color_str == "pants") {\ - panel_bg_color = colormapPaletteColor(mod(stof(getplayerkey(current_player - 1, "colors")), 16), 1);\ + panel_bg_color = colormapPaletteColor(mod(stof(getplayerkeyvalue(current_player - 1, "colors")), 16), 1);\ } else {\ panel_bg_color = stov(panel_bg_color_str);\ }\ @@ -152,6 +156,14 @@ if(panel_bg_color_team_str == "") {\ panel_bg_color_team = stof(panel_bg_color_team_str);\ } +// the check doesn't allow to fade this panel when showing the panel-specific menu dialog +#define HUD_Panel_ApplyFadeAlpha()\ +if(!(menu_enabled == 2 && highlightedPanel == hud_configure_active_panel))\ +{\ + panel_bg_alpha *= hud_fade_alpha;\ + panel_fg_alpha *= hud_fade_alpha;\ +} ENDS_WITH_CURLY_BRACE + // Get value for panel_bg_alpha: if "" fetch default, else use panel_bg_alpha. Also do various menu dialog fadeout/in checks, and minalpha checks // comment on line 3 of macro: // do not set a minalpha cap when showing the config dialog for this panel #define HUD_Panel_GetBgAlpha()\ @@ -159,25 +171,21 @@ if(panel_bg_alpha_str == "") {\ panel_bg_alpha_str = ftos(autocvar_hud_panel_bg_alpha);\ }\ panel_bg_alpha = stof(panel_bg_alpha_str);\ -if(autocvar__hud_configure && menu_enabled == 2 && highlightedPanel == active_panel) {\ - panel_bg_alpha = (1 - autocvar__menu_alpha) * max(autocvar_hud_configure_bg_minalpha, panel_bg_alpha) + autocvar__menu_alpha * panel_bg_alpha;\ -} else if(autocvar__hud_configure) {\ - panel_bg_alpha = max(autocvar_hud_configure_bg_minalpha, panel_bg_alpha);\ -} if(autocvar__hud_configure && !panel_enabled) {\ - panel_bg_alpha = 0.25;\ -} if(!(menu_enabled == 2 && highlightedPanel == active_panel)) {\ - panel_bg_alpha *= hud_fade_alpha;\ +if(autocvar__hud_configure) {\ + if(!panel_enabled)\ + panel_bg_alpha = 0.25;\ + else if(menu_enabled == 2 && highlightedPanel == hud_configure_active_panel)\ + panel_bg_alpha = (1 - autocvar__menu_alpha) * max(cvar("hud_configure_bg_minalpha"), panel_bg_alpha) + autocvar__menu_alpha * panel_bg_alpha;\ + else\ + panel_bg_alpha = max(cvar("hud_configure_bg_minalpha"), panel_bg_alpha);\ } // Get value for panel_fg_alpha. Also do various minalpha checks // comment on line 2 of macro: // ALWAYS show disabled panels at 0.25 alpha when in config mode -// comment on line 4 of macro: // don't fade this panel when showing the panel-specific menu dialog #define HUD_Panel_GetFgAlpha()\ panel_fg_alpha = autocvar_hud_panel_fg_alpha;\ if(autocvar__hud_configure && !panel_enabled)\ panel_fg_alpha = 0.25;\ -if(!(menu_enabled == 2 && highlightedPanel == active_panel))\ - panel_fg_alpha *= hud_fade_alpha; // Get border. See comments above, it's similar. #define HUD_Panel_GetBorder()\ @@ -205,13 +213,15 @@ if(panel_bg_padding_str == "") {\ panel_bg_padding = min(min(panel_size_x, panel_size_y)/2 - 5, panel_bg_padding); // Point to the macros above (stupid max macro length) -#define HUD_Panel_StringVars()\ +#define HUD_Panel_GetStringVars()\ HUD_Panel_GetBg()\ -HUD_Panel_GetColorTeam()\ -HUD_Panel_GetColor()\ -HUD_Panel_GetBgAlpha()\ +if (panel_bg != "0") {\ + HUD_Panel_GetColorTeam()\ + HUD_Panel_GetColor()\ + HUD_Panel_GetBgAlpha()\ + HUD_Panel_GetBorder()\ +}\ HUD_Panel_GetFgAlpha()\ -HUD_Panel_GetBorder()\ HUD_Panel_GetScaledVectors()\ HUD_Panel_GetPadding() @@ -225,7 +235,9 @@ else\ panel_pos = (1 - autocvar__menu_alpha) * panel_pos + (autocvar__menu_alpha) * menu_enable_panelpos; // return smoothly faded size of given panel when a dialog is active -var vector menu_enable_maxsize; FTEQCC_YOU_SUCK_THIS_IS_NOT_UNREFERENCED(menu_enable_maxsize); +//var vector menu_enable_maxsize; +var float menu_enable_maxsize_x; +var float menu_enable_maxsize_y; var vector menu_enable_size; #define HUD_Panel_GetMenuSize()\ menu_enable_maxsize_x = 0.3 * vid_conwidth;\ @@ -260,13 +272,23 @@ panel_bg_color_team_str = cvar_string("hud_panel_" #name "_bg_color_team"); \ panel_bg_alpha_str = cvar_string("hud_panel_" #name "_bg_alpha"); \ panel_bg_border_str = cvar_string("hud_panel_" #name "_bg_border"); \ panel_bg_padding_str = cvar_string("hud_panel_" #name "_bg_padding"); \ -HUD_Panel_StringVars()\ -if(menu_enabled == 2 && active_panel == highlightedPanel) {\ +HUD_Panel_GetStringVars()\ +if(menu_enabled == 2 && hud_configure_active_panel == highlightedPanel) {\ HUD_Panel_GetMenuSize()\ HUD_Panel_GetMenuPos()\ } ENDS_WITH_CURLY_BRACE +// FTEQCC I HATE YOU WHY DO YOU MAKE ME DO THIS??? :( +// max macro length is 1024 characters, I must split it up :( + // Update all common cvars of given panel id +#define HUD_Panel_UpdateCvarsForId_Part2(id) \ +switch(id) { \ + case HUD_PANEL_INFOMESSAGES: HUD_Panel_UpdateCvars(infomessages) break; \ + case HUD_PANEL_PHYSICS: HUD_Panel_UpdateCvars(physics); break;\ + case HUD_PANEL_CENTERPRINT: HUD_Panel_UpdateCvars(centerprint); break;\ +} + #define HUD_Panel_UpdateCvarsForId(id) \ switch(id) { \ case HUD_PANEL_WEAPONS: HUD_Panel_UpdateCvars(weapons) break; \ @@ -283,14 +305,14 @@ switch(id) { \ case HUD_PANEL_PRESSEDKEYS: HUD_Panel_UpdateCvars(pressedkeys) break; \ case HUD_PANEL_CHAT: HUD_Panel_UpdateCvars(chat) break; \ case HUD_PANEL_ENGINEINFO: HUD_Panel_UpdateCvars(engineinfo) break; \ - case HUD_PANEL_INFOMESSAGES: HUD_Panel_UpdateCvars(infomessages) break; \ + default: HUD_Panel_UpdateCvarsForId_Part2(id)\ } #define HUD_Panel_UpdatePosSize(name) \ panel_pos = stov(cvar_string("hud_panel_" #name "_pos")); \ panel_size = stov(cvar_string("hud_panel_" #name "_size")); \ HUD_Panel_GetScaledVectors()\ -if(menu_enabled == 2 && active_panel == highlightedPanel) {\ +if(menu_enabled == 2 && hud_configure_active_panel == highlightedPanel) {\ HUD_Panel_GetMenuSize()\ HUD_Panel_GetMenuPos()\ }\ @@ -298,6 +320,13 @@ panel_bg_border_str = cvar_string("hud_panel_" #name "_bg_border"); \ HUD_Panel_GetBorder() // Update pos and size of given panel id +#define HUD_Panel_UpdatePosSizeForId_Part2(id) \ +switch(id) { \ + case HUD_PANEL_INFOMESSAGES: HUD_Panel_UpdatePosSize(infomessages) break;\ + case HUD_PANEL_PHYSICS: HUD_Panel_UpdatePosSize(physics); break;\ + case HUD_PANEL_CENTERPRINT: HUD_Panel_UpdatePosSize(centerprint); break;\ +} + #define HUD_Panel_UpdatePosSizeForId(id) \ switch(id) { \ case HUD_PANEL_WEAPONS: HUD_Panel_UpdatePosSize(weapons) break;\ @@ -314,5 +343,5 @@ switch(id) { \ case HUD_PANEL_PRESSEDKEYS: HUD_Panel_UpdatePosSize(pressedkeys) break;\ case HUD_PANEL_CHAT: HUD_Panel_UpdatePosSize(chat) break;\ case HUD_PANEL_ENGINEINFO: HUD_Panel_UpdatePosSize(engineinfo) break;\ - case HUD_PANEL_INFOMESSAGES: HUD_Panel_UpdatePosSize(infomessages)\ + default: HUD_Panel_UpdatePosSizeForId_Part2(id)\ } diff --git a/qcsrc/client/hud_config.qc b/qcsrc/client/hud_config.qc new file mode 100644 index 0000000000..3ad600e41c --- /dev/null +++ b/qcsrc/client/hud_config.qc @@ -0,0 +1,1172 @@ +#define HUD_Write(s) fputs(fh, s) +// q: quoted, n: not quoted +#define HUD_Write_Cvar_n(cvar) HUD_Write(strcat("seta ", cvar, " ", cvar_string(cvar), "\n")) +#define HUD_Write_Cvar_q(cvar) HUD_Write(strcat("seta ", cvar, " \"", cvar_string(cvar), "\"\n")) +#define HUD_Write_PanelCvar_n(cvar_suf) HUD_Write_Cvar_n(strcat("hud_panel_", panel_name, cvar_suf)) +#define HUD_Write_PanelCvar_q(cvar_suf) HUD_Write_Cvar_q(strcat("hud_panel_", panel_name, cvar_suf)) +// Save the config +void HUD_Panel_ExportCfg(string cfgname) +{ + float fh; + string filename = strcat("hud_", autocvar_hud_skin, "_", cfgname, ".cfg"); + fh = fopen(filename, FILE_WRITE); + if(fh >= 0) + { + HUD_Write_Cvar_q("hud_skin"); + HUD_Write_Cvar_q("hud_panel_bg"); + HUD_Write_Cvar_q("hud_panel_bg_color"); + HUD_Write_Cvar_q("hud_panel_bg_color_team"); + HUD_Write_Cvar_q("hud_panel_bg_alpha"); + HUD_Write_Cvar_q("hud_panel_bg_border"); + HUD_Write_Cvar_q("hud_panel_bg_padding"); + HUD_Write_Cvar_q("hud_panel_fg_alpha"); + HUD_Write("\n"); + + HUD_Write_Cvar_q("hud_dock"); + HUD_Write_Cvar_q("hud_dock_color"); + HUD_Write_Cvar_q("hud_dock_color_team"); + HUD_Write_Cvar_q("hud_dock_alpha"); + HUD_Write("\n"); + + HUD_Write_Cvar_q("hud_progressbar_alpha"); + HUD_Write_Cvar_q("hud_progressbar_strength_color"); + HUD_Write_Cvar_q("hud_progressbar_shield_color"); + HUD_Write_Cvar_q("hud_progressbar_health_color"); + HUD_Write_Cvar_q("hud_progressbar_armor_color"); + HUD_Write_Cvar_q("hud_progressbar_fuel_color"); + HUD_Write_Cvar_q("hud_progressbar_nexball_color"); + HUD_Write_Cvar_q("hud_progressbar_speed_color"); + HUD_Write_Cvar_q("hud_progressbar_acceleration_color"); + HUD_Write_Cvar_q("hud_progressbar_acceleration_neg_color"); + HUD_Write("\n"); + + HUD_Write_Cvar_q("_hud_panelorder"); + HUD_Write("\n"); + + HUD_Write_Cvar_q("hud_configure_grid"); + HUD_Write_Cvar_q("hud_configure_grid_xsize"); + HUD_Write_Cvar_q("hud_configure_grid_ysize"); + HUD_Write("\n"); + + // common cvars for all panels + float i; + for (i = 0; i < HUD_PANEL_NUM; ++i) + { + HUD_Panel_GetName(i); + + HUD_Write_PanelCvar_n(""); + HUD_Write_PanelCvar_q("_pos"); + HUD_Write_PanelCvar_q("_size"); + HUD_Write_PanelCvar_q("_bg"); + HUD_Write_PanelCvar_q("_bg_color"); + HUD_Write_PanelCvar_q("_bg_color_team"); + HUD_Write_PanelCvar_q("_bg_alpha"); + HUD_Write_PanelCvar_q("_bg_border"); + HUD_Write_PanelCvar_q("_bg_padding"); + switch(i) { + case HUD_PANEL_WEAPONS: + HUD_Write_PanelCvar_q("_accuracy"); + HUD_Write_PanelCvar_q("_label"); + HUD_Write_PanelCvar_q("_complainbubble"); + HUD_Write_PanelCvar_q("_complainbubble_padding"); + HUD_Write_PanelCvar_q("_complainbubble_time"); + HUD_Write_PanelCvar_q("_complainbubble_fadetime"); + HUD_Write_PanelCvar_q("_complainbubble_color_outofammo"); + HUD_Write_PanelCvar_q("_complainbubble_color_donthave"); + HUD_Write_PanelCvar_q("_complainbubble_color_unavailable"); + HUD_Write_PanelCvar_q("_ammo"); + HUD_Write_PanelCvar_q("_ammo_color"); + HUD_Write_PanelCvar_q("_ammo_alpha"); + HUD_Write_PanelCvar_q("_aspect"); + HUD_Write_PanelCvar_q("_timeout"); + HUD_Write_PanelCvar_q("_timeout_effect"); + HUD_Write_PanelCvar_q("_onlyowned"); + break; + case HUD_PANEL_AMMO: + HUD_Write_PanelCvar_q("_onlycurrent"); + HUD_Write_PanelCvar_q("_iconalign"); + HUD_Write_PanelCvar_q("_progressbar"); + HUD_Write_PanelCvar_q("_progressbar_name"); + HUD_Write_PanelCvar_q("_progressbar_xoffset"); + HUD_Write_PanelCvar_q("_text"); + break; + case HUD_PANEL_POWERUPS: + HUD_Write_PanelCvar_q("_flip"); + HUD_Write_PanelCvar_q("_iconalign"); + HUD_Write_PanelCvar_q("_baralign"); + HUD_Write_PanelCvar_q("_progressbar"); + HUD_Write_PanelCvar_q("_progressbar_strength"); + HUD_Write_PanelCvar_q("_progressbar_shield"); + HUD_Write_PanelCvar_q("_text"); + break; + case HUD_PANEL_HEALTHARMOR: + HUD_Write_PanelCvar_q("_flip"); + HUD_Write_PanelCvar_q("_iconalign"); + HUD_Write_PanelCvar_q("_baralign"); + HUD_Write_PanelCvar_q("_progressbar"); + HUD_Write_PanelCvar_q("_progressbar_health"); + HUD_Write_PanelCvar_q("_progressbar_armor"); + HUD_Write_PanelCvar_q("_progressbar_gfx"); + HUD_Write_PanelCvar_q("_progressbar_gfx_smooth"); + HUD_Write_PanelCvar_q("_text"); + break; + case HUD_PANEL_NOTIFY: + HUD_Write_PanelCvar_q("_flip"); + HUD_Write_PanelCvar_q("_fontsize"); + HUD_Write_PanelCvar_q("_print"); + HUD_Write_PanelCvar_q("_time"); + HUD_Write_PanelCvar_q("_fadetime"); + break; + case HUD_PANEL_TIMER: + HUD_Write_PanelCvar_q("_increment"); + break; + case HUD_PANEL_RADAR: + HUD_Write_PanelCvar_q("_foreground_alpha"); + HUD_Write_PanelCvar_q("_rotation"); + HUD_Write_PanelCvar_q("_zoommode"); + HUD_Write_PanelCvar_q("_scale"); + HUD_Write_PanelCvar_q("_maximized_scale"); + HUD_Write_PanelCvar_q("_maximized_size"); + break; + case HUD_PANEL_SCORE: + HUD_Write_PanelCvar_q("_rankings"); + break; + case HUD_PANEL_VOTE: + HUD_Write_PanelCvar_q("_alreadyvoted_alpha"); + break; + case HUD_PANEL_MODICONS: + HUD_Write_PanelCvar_q("_dom_layout"); + break; + case HUD_PANEL_PRESSEDKEYS: + HUD_Write_PanelCvar_q("_aspect"); + break; + case HUD_PANEL_ENGINEINFO: + HUD_Write_PanelCvar_q("_framecounter_time"); + HUD_Write_PanelCvar_q("_framecounter_decimals"); + break; + case HUD_PANEL_INFOMESSAGES: + HUD_Write_PanelCvar_q("_flip"); + break; + case HUD_PANEL_PHYSICS: + HUD_Write_PanelCvar_q("_speed_unit"); + HUD_Write_PanelCvar_q("_speed_unit_show"); + HUD_Write_PanelCvar_q("_speed_max"); + HUD_Write_PanelCvar_q("_speed_vertical"); + HUD_Write_PanelCvar_q("_topspeed"); + HUD_Write_PanelCvar_q("_topspeed_time"); + HUD_Write_PanelCvar_q("_acceleration_max"); + HUD_Write_PanelCvar_q("_acceleration_vertical"); + HUD_Write_PanelCvar_q("_flip"); + HUD_Write_PanelCvar_q("_baralign"); + HUD_Write_PanelCvar_q("_progressbar"); + HUD_Write_PanelCvar_q("_acceleration_mode"); + HUD_Write_PanelCvar_q("_text"); + break; + case HUD_PANEL_CENTERPRINT: + HUD_Write_PanelCvar_q("_align"); + HUD_Write_PanelCvar_q("_flip"); + HUD_Write_PanelCvar_q("_fontscale"); + HUD_Write_PanelCvar_q("_time"); + HUD_Write_PanelCvar_q("_fade_in"); + HUD_Write_PanelCvar_q("_fade_out"); + HUD_Write_PanelCvar_q("_fade_subsequent"); + HUD_Write_PanelCvar_q("_fade_subsequent_passone"); + HUD_Write_PanelCvar_q("_fade_subsequent_passone_minalpha"); + HUD_Write_PanelCvar_q("_fade_subsequent_passtwo"); + HUD_Write_PanelCvar_q("_fade_subsequent_passtwo_minalpha"); + HUD_Write_PanelCvar_q("_fade_subsequent_minfontsize"); + HUD_Write_PanelCvar_q("_fade_minfontsize"); + break; + } + HUD_Write("\n"); + } + HUD_Write("menu_sync\n"); // force the menu to reread the cvars, so that the dialogs are updated + + print(sprintf(_("^2Successfully exported to %s! (Note: It's saved in data/data/)\n"), filename)); + fclose(fh); + } + else + print(sprintf(_("^1Couldn't write to %s\n"), filename)); +} + +// check if move will result in panel being moved into another panel. If so, return snapped vector, otherwise return the given vector +vector HUD_Panel_CheckMove(vector myPos, vector mySize) +{ + float i; + float myCenter_x, myCenter_y, targCenter_x, targCenter_y; + vector myTarget; + myTarget = myPos; + + for (i = 0; i < HUD_PANEL_NUM; ++i) { + if(i == highlightedPanel || !panel_enabled) + continue; + + HUD_Panel_UpdatePosSizeForId(i); + + panel_pos -= '1 1 0' * panel_bg_border; + panel_size += '2 2 0' * panel_bg_border; + + if(myPos_y + mySize_y < panel_pos_y) + continue; + if(myPos_y > panel_pos_y + panel_size_y) + continue; + + if(myPos_x + mySize_x < panel_pos_x) + continue; + if(myPos_x > panel_pos_x + panel_size_x) + continue; + + // OK, there IS a collision. + + myCenter_x = myPos_x + 0.5 * mySize_x; + myCenter_y = myPos_y + 0.5 * mySize_y; + + targCenter_x = panel_pos_x + 0.5 * panel_size_x; + targCenter_y = panel_pos_y + 0.5 * panel_size_y; + + if(myCenter_x < targCenter_x && myCenter_y < targCenter_y) // top left (of the target panel) + { + if(myPos_x + mySize_x - panel_pos_x < myPos_y + mySize_y - panel_pos_y) // push it to the side + myTarget_x = panel_pos_x - mySize_x; + else // push it upwards + myTarget_y = panel_pos_y - mySize_y; + } + else if(myCenter_x > targCenter_x && myCenter_y < targCenter_y) // top right + { + if(panel_pos_x + panel_size_x - myPos_x < myPos_y + mySize_y - panel_pos_y) // push it to the side + myTarget_x = panel_pos_x + panel_size_x; + else // push it upwards + myTarget_y = panel_pos_y - mySize_y; + } + else if(myCenter_x < targCenter_x && myCenter_y > targCenter_y) // bottom left + { + if(myPos_x + mySize_x - panel_pos_x < panel_pos_y + panel_size_y - myPos_y) // push it to the side + myTarget_x = panel_pos_x - mySize_x; + else // push it downwards + myTarget_y = panel_pos_y + panel_size_y; + } + else if(myCenter_x > targCenter_x && myCenter_y > targCenter_y) // bottom right + { + if(panel_pos_x + panel_size_x - myPos_x < panel_pos_y + panel_size_y - myPos_y) // push it to the side + myTarget_x = panel_pos_x + panel_size_x; + else // push it downwards + myTarget_y = panel_pos_y + panel_size_y; + } + //if(cvar("hud_configure_checkcollisions_debug")) + //drawfill(panel_pos, panel_size, '1 1 0', .3, DRAWFLAG_NORMAL); + } + + return myTarget; +} + +void HUD_Panel_SetPos(vector pos) +{ + HUD_Panel_UpdatePosSizeForId(highlightedPanel); + vector mySize; + mySize = panel_size; + + //if(cvar("hud_configure_checkcollisions_debug")) + //drawfill(pos, mySize, '1 1 1', .2, DRAWFLAG_NORMAL); + + if(autocvar_hud_configure_grid) + { + pos_x = floor((pos_x/vid_conwidth)/hud_configure_gridSize_x + 0.5) * hud_configure_realGridSize_x; + pos_y = floor((pos_y/vid_conheight)/hud_configure_gridSize_y + 0.5) * hud_configure_realGridSize_y; + } + + if(hud_configure_checkcollisions) + pos = HUD_Panel_CheckMove(pos, mySize); + + pos_x = bound(0, pos_x, vid_conwidth - mySize_x); + pos_y = bound(0, pos_y, vid_conheight - mySize_y); + + string s; + s = strcat(ftos(pos_x/vid_conwidth), " ", ftos(pos_y/vid_conheight)); + + HUD_Panel_GetName(highlightedPanel); + cvar_set(strcat("hud_panel_", panel_name, "_pos"), s); +} + +// check if resize will result in panel being moved into another panel. If so, return snapped vector, otherwise return the given vector +vector HUD_Panel_CheckResize(vector mySize, vector resizeorigin) { + float i; + + vector targEndPos; + + float dist_x, dist_y; + float ratio; + ratio = mySize_x/mySize_y; + + for (i = 0; i < HUD_PANEL_NUM; ++i) { + if(i == highlightedPanel || !panel_enabled) + continue; + + HUD_Panel_UpdatePosSizeForId(i); + + panel_pos -= '1 1 0' * panel_bg_border; + panel_size += '2 2 0' * panel_bg_border; + + targEndPos = panel_pos + panel_size; + + // resizeorigin is WITHIN target panel, just abort any collision testing against that particular panel to produce expected behaviour! + if(resizeorigin_x > panel_pos_x && resizeorigin_x < targEndPos_x && resizeorigin_y > panel_pos_y && resizeorigin_y < targEndPos_y) + continue; + + if (resizeCorner == 1) + { + // check if this panel is on our way + if (resizeorigin_x <= panel_pos_x) + continue; + if (resizeorigin_y <= panel_pos_y) + continue; + if (targEndPos_x <= resizeorigin_x - mySize_x) + continue; + if (targEndPos_y <= resizeorigin_y - mySize_y) + continue; + + // there is a collision: + // detect which side of the panel we are facing is actually limiting the resizing + // (which side the resize direction finds for first) and reduce the size up to there + // + // dist is the distance between resizeorigin and the "analogous" point of the panel + // in this case between resizeorigin (bottom-right point) and the bottom-right point of the panel + dist_x = resizeorigin_x - targEndPos_x; + dist_y = resizeorigin_y - targEndPos_y; + if (dist_y <= 0 || dist_x / dist_y > ratio) + mySize_x = min(mySize_x, dist_x); + else + mySize_y = min(mySize_y, dist_y); + } + else if (resizeCorner == 2) + { + if (resizeorigin_x >= targEndPos_x) + continue; + if (resizeorigin_y <= panel_pos_y) + continue; + if (panel_pos_x >= resizeorigin_x + mySize_x) + continue; + if (targEndPos_y <= resizeorigin_y - mySize_y) + continue; + + dist_x = panel_pos_x - resizeorigin_x; + dist_y = resizeorigin_y - targEndPos_y; + if (dist_y <= 0 || dist_x / dist_y > ratio) + mySize_x = min(mySize_x, dist_x); + else + mySize_y = min(mySize_y, dist_y); + } + else if (resizeCorner == 3) + { + if (resizeorigin_x <= panel_pos_x) + continue; + if (resizeorigin_y >= targEndPos_y) + continue; + if (targEndPos_x <= resizeorigin_x - mySize_x) + continue; + if (panel_pos_y >= resizeorigin_y + mySize_y) + continue; + + dist_x = resizeorigin_x - targEndPos_x; + dist_y = panel_pos_y - resizeorigin_y; + if (dist_y <= 0 || dist_x / dist_y > ratio) + mySize_x = min(mySize_x, dist_x); + else + mySize_y = min(mySize_y, dist_y); + } + else if (resizeCorner == 4) + { + if (resizeorigin_x >= targEndPos_x) + continue; + if (resizeorigin_y >= targEndPos_y) + continue; + if (panel_pos_x >= resizeorigin_x + mySize_x) + continue; + if (panel_pos_y >= resizeorigin_y + mySize_y) + continue; + + dist_x = panel_pos_x - resizeorigin_x; + dist_y = panel_pos_y - resizeorigin_y; + if (dist_y <= 0 || dist_x / dist_y > ratio) + mySize_x = min(mySize_x, dist_x); + else + mySize_y = min(mySize_y, dist_y); + } + //if(cvar("hud_configure_checkcollisions_debug")) + //drawfill(panel_pos, panel_size, '1 1 0', .3, DRAWFLAG_NORMAL); + } + + return mySize; +} + +void HUD_Panel_SetPosSize(vector mySize) +{ + HUD_Panel_UpdatePosSizeForId(highlightedPanel); + vector resizeorigin; + resizeorigin = panel_click_resizeorigin; + local noref vector myPos; // fteqcc sucks + + // minimum panel size cap + mySize_x = max(0.025 * vid_conwidth, mySize_x); + mySize_y = max(0.025 * vid_conheight, mySize_y); + + if(highlightedPanel == HUD_PANEL_CHAT) // some panels have their own restrictions, like the chat panel (which actually only moves the engine chat print around). Looks bad if it's too small. + { + mySize_x = max(17 * autocvar_con_chatsize, mySize_x); + mySize_y = max(2 * autocvar_con_chatsize + 2 * panel_bg_padding, mySize_y); + } + + // collision testing| + // -----------------+ + + // we need to know pos at this stage, but it might still change later if we hit a screen edge/other panel (?) + if(resizeCorner == 1) { + myPos_x = resizeorigin_x - mySize_x; + myPos_y = resizeorigin_y - mySize_y; + } else if(resizeCorner == 2) { + myPos_x = resizeorigin_x; + myPos_y = resizeorigin_y - mySize_y; + } else if(resizeCorner == 3) { + myPos_x = resizeorigin_x - mySize_x; + myPos_y = resizeorigin_y; + } else { // resizeCorner == 4 + myPos_x = resizeorigin_x; + myPos_y = resizeorigin_y; + } + + // left/top screen edges + if(myPos_x < 0) + mySize_x = mySize_x + myPos_x; + if(myPos_y < 0) + mySize_y = mySize_y + myPos_y; + + // bottom/right screen edges + if(myPos_x + mySize_x > vid_conwidth) + mySize_x = vid_conwidth - myPos_x; + if(myPos_y + mySize_y > vid_conheight) + mySize_y = vid_conheight - myPos_y; + + //if(cvar("hud_configure_checkcollisions_debug")) + //drawfill(myPos, mySize, '1 1 1', .2, DRAWFLAG_NORMAL); + + // before checkresize, otherwise panel can be snapped partially inside another panel or panel aspect ratio can be broken + if(autocvar_hud_configure_grid) + { + mySize_x = floor((mySize_x/vid_conwidth)/hud_configure_gridSize_x + 0.5) * hud_configure_realGridSize_x; + mySize_y = floor((mySize_y/vid_conheight)/hud_configure_gridSize_y + 0.5) * hud_configure_realGridSize_y; + } + + if(hud_configure_checkcollisions) + mySize = HUD_Panel_CheckResize(mySize, resizeorigin); + + // minimum panel size cap, do this once more so we NEVER EVER EVER have a panel smaller than this, JUST IN CASE above code still makes the panel eg negative (impossible to resize back without changing cvars manually then) + mySize_x = max(0.025 * vid_conwidth, mySize_x); + mySize_y = max(0.025 * vid_conheight, mySize_y); + + // do another pos check, as size might have changed by now + if(resizeCorner == 1) { + myPos_x = resizeorigin_x - mySize_x; + myPos_y = resizeorigin_y - mySize_y; + } else if(resizeCorner == 2) { + myPos_x = resizeorigin_x; + myPos_y = resizeorigin_y - mySize_y; + } else if(resizeCorner == 3) { + myPos_x = resizeorigin_x - mySize_x; + myPos_y = resizeorigin_y; + } else { // resizeCorner == 4 + myPos_x = resizeorigin_x; + myPos_y = resizeorigin_y; + } + + //if(cvar("hud_configure_checkcollisions_debug")) + //drawfill(myPos, mySize, '0 1 0', .3, DRAWFLAG_NORMAL); + + HUD_Panel_GetName(highlightedPanel); + string s; + s = strcat(ftos(mySize_x/vid_conwidth), " ", ftos(mySize_y/vid_conheight)); + cvar_set(strcat("hud_panel_", panel_name, "_size"), s); + + s = strcat(ftos(myPos_x/vid_conwidth), " ", ftos(myPos_y/vid_conheight)); + cvar_set(strcat("hud_panel_", panel_name, "_pos"), s); +} + +float pressed_key_time; +vector highlightedPanel_initial_pos, highlightedPanel_initial_size; +void HUD_Panel_Arrow_Action(float nPrimary) +{ + if (highlightedPanel == -1) + return; + + hud_configure_checkcollisions = (!(hudShiftState & S_CTRL) && autocvar_hud_configure_checkcollisions); + + float step; + if(autocvar_hud_configure_grid) + { + if (nPrimary == K_UPARROW || nPrimary == K_DOWNARROW) + { + if (hudShiftState & S_SHIFT) + step = hud_configure_realGridSize_y; + else + step = 2 * hud_configure_realGridSize_y; + } + else + { + if (hudShiftState & S_SHIFT) + step = hud_configure_realGridSize_x; + else + step = 2 * hud_configure_realGridSize_x; + } + } + else + { + if (nPrimary == K_UPARROW || nPrimary == K_DOWNARROW) + step = vid_conheight; + else + step = vid_conwidth; + if (hudShiftState & S_SHIFT) + step = (step / 256); // more precision + else + step = (step / 64) * (1 + 2 * (time - pressed_key_time)); + } + + HUD_Panel_UpdatePosSizeForId(highlightedPanel); + + highlightedPanel_initial_pos = panel_pos; + highlightedPanel_initial_size = panel_size; + + if (hudShiftState & S_ALT) // resize + { + highlightedAction = 1; + if(nPrimary == K_UPARROW) + resizeCorner = 1; + else if(nPrimary == K_RIGHTARROW) + resizeCorner = 2; + else if(nPrimary == K_LEFTARROW) + resizeCorner = 3; + else // if(nPrimary == K_DOWNARROW) + resizeCorner = 4; + + // ctrl+arrow reduces the size, instead of increasing it + // Note that ctrl disables collisions check too, but it's fine + // since we don't collide with anything reducing the size + if (hudShiftState & S_CTRL) { + step = -step; + resizeCorner = 5 - resizeCorner; + } + + vector mySize; + mySize = panel_size; + panel_click_resizeorigin = panel_pos; + if(resizeCorner == 1) { + panel_click_resizeorigin += mySize; + mySize_y += step; + } else if(resizeCorner == 2) { + panel_click_resizeorigin_y += mySize_y; + mySize_x += step; + } else if(resizeCorner == 3) { + panel_click_resizeorigin_x += mySize_x; + mySize_x += step; + } else { // resizeCorner == 4 + mySize_y += step; + } + HUD_Panel_SetPosSize(mySize); + } + else // move + { + highlightedAction = 2; + vector pos; + pos = panel_pos; + if(nPrimary == K_UPARROW) + pos_y -= step; + else if(nPrimary == K_DOWNARROW) + pos_y += step; + else if(nPrimary == K_LEFTARROW) + pos_x -= step; + else // if(nPrimary == K_RIGHTARROW) + pos_x += step; + + HUD_Panel_SetPos(pos); + } + + HUD_Panel_UpdatePosSizeForId(highlightedPanel); + + if (highlightedPanel_initial_pos != panel_pos || highlightedPanel_initial_size != panel_size) + { + // backup! + panel_pos_backup = highlightedPanel_initial_pos; + panel_size_backup = highlightedPanel_initial_size; + highlightedPanel_backup = highlightedPanel; + } +} + +const float S_MOUSE1 = 1; +const float S_MOUSE2 = 2; +const float S_MOUSE3 = 4; +float mouseClicked; +float prevMouseClicked; // previous state +float prevMouseClickedTime; // time during previous left mouse click, to check for doubleclicks +vector prevMouseClickedPos; // pos during previous left mouse click, to check for doubleclicks + +void HUD_Panel_EnableMenu(); +float tab_panels[HUD_PANEL_NUM]; +float tab_panel, tab_backward; +vector tab_panel_pos; +void HUD_Panel_FirstInDrawQ(float id); +void reset_tab_panels() +{ + int i; + for(i = 0; i < HUD_PANEL_NUM; ++i) + tab_panels[i] = -1; +} +float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary) +{ + string s; + + // we only care for keyboard events + if(bInputType != 0 && bInputType != 1) + return false; + + if(!autocvar__hud_configure) + return false; + + // allow console bind to work + string con_keys; + float keys; + con_keys = findkeysforcommand("toggleconsole", 0); + keys = tokenize(con_keys); // findkeysforcommand returns data for this + + float hit_con_bind, i; + for (i = 0; i < keys; ++i) + { + if(nPrimary == stof(argv(i))) + hit_con_bind = 1; + } + + if(bInputType == 0) { + if(nPrimary == K_ALT) hudShiftState |= S_ALT; + if(nPrimary == K_CTRL) hudShiftState |= S_CTRL; + if(nPrimary == K_SHIFT) hudShiftState |= S_SHIFT; + } + else if(bInputType == 1) { + if(nPrimary == K_ALT) hudShiftState -= (hudShiftState & S_ALT); + if(nPrimary == K_CTRL) hudShiftState -= (hudShiftState & S_CTRL); + if(nPrimary == K_SHIFT) hudShiftState -= (hudShiftState & S_SHIFT); + } + + if(nPrimary == K_CTRL) + { + if (bInputType == 1) //ctrl has been released + { + if (tab_panel != -1) + { + //switch to selected panel + highlightedPanel = tab_panel; + highlightedAction = 0; + HUD_Panel_FirstInDrawQ(highlightedPanel); + } + tab_panel = -1; + reset_tab_panels(); + } + } + + if(nPrimary == K_MOUSE1) + { + if(bInputType == 0) // key pressed + mouseClicked |= S_MOUSE1; + else if(bInputType == 1) // key released + mouseClicked -= (mouseClicked & S_MOUSE1); + } + else if(nPrimary == K_MOUSE2) + { + if(bInputType == 0) // key pressed + mouseClicked |= S_MOUSE2; + else if(bInputType == 1) // key released + mouseClicked -= (mouseClicked & S_MOUSE2); + } + else if(nPrimary == K_ESCAPE) + { + if (bInputType == 1) + return true; + menu_enabled = 1; + menu_enabled_time = time; + localcmd("menu_showhudexit\n"); + } + else if(nPrimary == K_BACKSPACE && hudShiftState & S_CTRL) + { + if (bInputType == 1) + return true; + if (!menu_enabled) + cvar_set("_hud_configure", "0"); + } + else if(nPrimary == K_TAB && hudShiftState & S_CTRL) // select and highlight another panel + { + if (bInputType == 1 || mouseClicked) + return true; + + //FIXME: if a panel is highlighted, has the same pos_x and lays in the same level + //of other panels then next consecutive ctrl-tab will select the highlighted panel too + //(it should only after every other panel of the hud) + //It's a minor bug anyway, we can live with it + + float starting_panel; + float old_tab_panel = tab_panel; + if (tab_panel == -1) //first press of TAB + { + if (highlightedPanel != -1) + HUD_Panel_UpdatePosSizeForId(highlightedPanel) + else + panel_pos = '0 0 0'; + starting_panel = highlightedPanel; //can be -1, it means no starting panel + tab_panel_pos = panel_pos; //to compute level + } + else + { + if ( ((!tab_backward) && (hudShiftState & S_SHIFT)) || (tab_backward && !(hudShiftState & S_SHIFT)) ) //tab direction changed? + reset_tab_panels(); + starting_panel = tab_panel; + } + tab_backward = (hudShiftState & S_SHIFT); + + float k, level, start_pos_x; + vector candidate_pos; + const float LEVELS_NUM = 4; + float level_height = vid_conheight / LEVELS_NUM; +:find_tab_panel + level = floor(tab_panel_pos_y / level_height) * level_height; //starting level + candidate_pos_x = (!tab_backward) ? vid_conwidth : 0; + start_pos_x = tab_panel_pos_x; + tab_panel = -1; + k=0; + while(++k) + { + for(i = 0; i < HUD_PANEL_NUM; ++i) + { + if (i == tab_panels[i] || i == starting_panel) + continue; + HUD_Panel_UpdatePosSizeForId(i) + if (panel_pos_y >= level && (panel_pos_y - level) < level_height) + if ( ( !tab_backward && panel_pos_x >= start_pos_x && (panel_pos_x < candidate_pos_x || (panel_pos_x == candidate_pos_x && panel_pos_y <= candidate_pos_y)) ) + || ( tab_backward && panel_pos_x <= start_pos_x && (panel_pos_x > candidate_pos_x || (panel_pos_x == candidate_pos_x && panel_pos_y >= candidate_pos_y)) ) ) + { + tab_panel = i; + tab_panel_pos = candidate_pos = panel_pos; + } + } + if (tab_panel != -1) + break; + if (k == LEVELS_NUM) //tab_panel not found + { + reset_tab_panels(); + if (old_tab_panel == -2) //this prevents an infinite loop (should not happen normally) + { + tab_panel = -1; + return true; + } + starting_panel = old_tab_panel; + old_tab_panel = -2; + goto find_tab_panel; //u must find tab_panel! + } + if (!tab_backward) + { + level = mod(level + level_height, vid_conheight); + start_pos_x = 0; + candidate_pos_x = vid_conwidth; + } + else + { + level = mod(level - level_height, vid_conheight); + start_pos_x = vid_conwidth; + candidate_pos_x = 0; + } + } + + tab_panels[tab_panel] = tab_panel; + } + else if(nPrimary == K_SPACE && hudShiftState & S_CTRL) // enable/disable highlighted panel or dock + { + if (bInputType == 1 || mouseClicked) + return true; + + if (highlightedPanel != -1) + { + HUD_Panel_GetName(highlightedPanel); + cvar_set(strcat("hud_panel_", panel_name), ftos(!(panel_enabled))); + } + else + cvar_set(strcat("hud_dock"), (autocvar_hud_dock == "") ? "dock" : ""); + } + else if(nPrimary == 'c' && hudShiftState & S_CTRL) // copy highlighted panel size + { + if (bInputType == 1 || mouseClicked) + return true; + + if (highlightedPanel != -1) + { + HUD_Panel_UpdatePosSizeForId(highlightedPanel); + panel_size_copied = panel_size; + highlightedPanel_copied = highlightedPanel; + } + } + else if(nPrimary == 'v' && hudShiftState & S_CTRL) // past copied size on the highlighted panel + { + if (bInputType == 1 || mouseClicked) + return true; + + if (highlightedPanel_copied == -1 || highlightedPanel == -1) + return true; + + HUD_Panel_UpdatePosSizeForId(highlightedPanel); + + // reduce size if it'd go beyond screen boundaries + vector tmp_size = panel_size_copied; + if (panel_pos_x + panel_size_copied_x > vid_conwidth) + tmp_size_x = vid_conwidth - panel_pos_x; + if (panel_pos_y + panel_size_copied_y > vid_conheight) + tmp_size_y = vid_conheight - panel_pos_y; + + if (panel_size == tmp_size) + return true; + + // backup first! + panel_pos_backup = panel_pos; + panel_size_backup = panel_size; + highlightedPanel_backup = highlightedPanel; + + s = strcat(ftos(tmp_size_x/vid_conwidth), " ", ftos(tmp_size_y/vid_conheight)); + HUD_Panel_GetName(highlightedPanel); + cvar_set(strcat("hud_panel_", panel_name, "_size"), s); + } + else if(nPrimary == 'z' && hudShiftState & S_CTRL) // undo last action + { + if (bInputType == 1 || mouseClicked) + return true; + //restore previous values + if (highlightedPanel_backup != -1) + { + HUD_Panel_GetName(highlightedPanel_backup); + s = strcat(ftos(panel_pos_backup_x/vid_conwidth), " ", ftos(panel_pos_backup_y/vid_conheight)); + cvar_set(strcat("hud_panel_", panel_name, "_pos"), s); + s = strcat(ftos(panel_size_backup_x/vid_conwidth), " ", ftos(panel_size_backup_y/vid_conheight)); + cvar_set(strcat("hud_panel_", panel_name, "_size"), s); + highlightedPanel_backup = -1; + } + } + else if(nPrimary == K_UPARROW || nPrimary == K_DOWNARROW || nPrimary == K_LEFTARROW || nPrimary == K_RIGHTARROW) + { + if (bInputType == 1) + { + pressed_key_time = 0; + return true; + } + else if (pressed_key_time == 0) + pressed_key_time = time; + + if (!mouseClicked) + HUD_Panel_Arrow_Action(nPrimary); //move or resize panel + } + else if(nPrimary == K_ENTER || nPrimary == K_SPACE || nPrimary == K_KP_ENTER) + { + if (bInputType == 1) + return true; + if (highlightedPanel != -1) + HUD_Panel_EnableMenu(); + } + else if(hit_con_bind) + return false; + + return true; +} + +float HUD_Panel_Check_Mouse_Pos(float allow_move) +{ + float i, j, border; + + while(j < HUD_PANEL_NUM) + { + i = panel_order[j]; + j += 1; + + HUD_Panel_UpdatePosSizeForId(i); + + border = max(8, panel_bg_border); // FORCED border so a small border size doesn't mean you can't resize + + // move + if(allow_move && mousepos_x >= panel_pos_x && mousepos_y >= panel_pos_y && mousepos_x <= panel_pos_x + panel_size_x && mousepos_y <= panel_pos_y + panel_size_y) + { + return 1; + } + // resize from topleft border + else if(mousepos_x >= panel_pos_x - border && mousepos_y >= panel_pos_y - border && mousepos_x <= panel_pos_x + 0.5 * panel_size_x && mousepos_y <= panel_pos_y + 0.5 * panel_size_y) + { + return 2; + } + // resize from topright border + else if(mousepos_x >= panel_pos_x + 0.5 * panel_size_x && mousepos_y >= panel_pos_y - border && mousepos_x <= panel_pos_x + panel_size_x + border && mousepos_y <= panel_pos_y + 0.5 * panel_size_y) + { + return 3; + } + // resize from bottomleft border + else if(mousepos_x >= panel_pos_x - border && mousepos_y >= panel_pos_y + 0.5 * panel_size_y && mousepos_x <= panel_pos_x + 0.5 * panel_size_x && mousepos_y <= panel_pos_y + panel_size_y + border) + { + return 3; + } + // resize from bottomright border + else if(mousepos_x >= panel_pos_x + 0.5 * panel_size_x && mousepos_y >= panel_pos_y + 0.5 * panel_size_y && mousepos_x <= panel_pos_x + panel_size_x + border && mousepos_y <= panel_pos_y + panel_size_y + border) + { + return 2; + } + } + return 0; +} + +// move a panel to the beginning of the panel order array (which means it gets drawn last, on top of everything else) +void HUD_Panel_FirstInDrawQ(float id) +{ + float i; + var float place = -1; + // find out where in the array our current id is, save into place + for(i = 0; i < HUD_PANEL_NUM; ++i) + { + if(panel_order[i] == id) + { + place = i; + break; + } + } + // place last if we didn't find a place for it yet (probably new panel, or screwed up cvar) + if(place == -1) + place = HUD_PANEL_NUM - 1; + + // move all ids up by one step in the array until "place" + for(i = place; i > 0; --i) + { + panel_order[i] = panel_order[i-1]; + } + // now save the new top id + panel_order[0] = id; + + // let's save them into the cvar by some strcat trickery + string s; + for(i = 0; i < HUD_PANEL_NUM; ++i) + { + s = strcat(s, ftos(panel_order[i]), " "); + } + cvar_set("_hud_panelorder", s); + if(hud_panelorder_prev) + strunzone(hud_panelorder_prev); + hud_panelorder_prev = strzone(autocvar__hud_panelorder); // prevent HUD_Main from doing useless update, we already updated here +} + +void HUD_Panel_Highlight(float allow_move) +{ + float i, j, border; + + while(j < HUD_PANEL_NUM) + { + i = panel_order[j]; + j += 1; + + HUD_Panel_UpdatePosSizeForId(i); + + border = max(8, panel_bg_border); // FORCED border so a small border size doesn't mean you can't resize + + // move + if(allow_move && mousepos_x >= panel_pos_x && mousepos_y >= panel_pos_y && mousepos_x <= panel_pos_x + panel_size_x && mousepos_y <= panel_pos_y + panel_size_y) + { + highlightedPanel = i; + HUD_Panel_FirstInDrawQ(i); + highlightedAction = 1; + panel_click_distance = mousepos - panel_pos; + return; + } + // resize from topleft border + else if(mousepos_x >= panel_pos_x - border && mousepos_y >= panel_pos_y - border && mousepos_x <= panel_pos_x + 0.5 * panel_size_x && mousepos_y <= panel_pos_y + 0.5 * panel_size_y) + { + highlightedPanel = i; + HUD_Panel_FirstInDrawQ(i); + highlightedAction = 2; + resizeCorner = 1; + panel_click_distance = mousepos - panel_pos; + panel_click_resizeorigin = panel_pos + panel_size; + return; + } + // resize from topright border + else if(mousepos_x >= panel_pos_x + 0.5 * panel_size_x && mousepos_y >= panel_pos_y - border && mousepos_x <= panel_pos_x + panel_size_x + border && mousepos_y <= panel_pos_y + 0.5 * panel_size_y) + { + highlightedPanel = i; + HUD_Panel_FirstInDrawQ(i); + highlightedAction = 2; + resizeCorner = 2; + panel_click_distance_x = panel_size_x - mousepos_x + panel_pos_x; + panel_click_distance_y = mousepos_y - panel_pos_y; + panel_click_resizeorigin = panel_pos + eY * panel_size_y; + return; + } + // resize from bottomleft border + else if(mousepos_x >= panel_pos_x - border && mousepos_y >= panel_pos_y + 0.5 * panel_size_y && mousepos_x <= panel_pos_x + 0.5 * panel_size_x && mousepos_y <= panel_pos_y + panel_size_y + border) + { + highlightedPanel = i; + HUD_Panel_FirstInDrawQ(i); + highlightedAction = 2; + resizeCorner = 3; + panel_click_distance_x = mousepos_x - panel_pos_x; + panel_click_distance_y = panel_size_y - mousepos_y + panel_pos_y; + panel_click_resizeorigin = panel_pos + eX * panel_size_x; + return; + } + // resize from bottomright border + else if(mousepos_x >= panel_pos_x + 0.5 * panel_size_x && mousepos_y >= panel_pos_y + 0.5 * panel_size_y && mousepos_x <= panel_pos_x + panel_size_x + border && mousepos_y <= panel_pos_y + panel_size_y + border) + { + highlightedPanel = i; + HUD_Panel_FirstInDrawQ(i); + highlightedAction = 2; + resizeCorner = 4; + panel_click_distance = panel_size - mousepos + panel_pos; + panel_click_resizeorigin = panel_pos; + return; + } + } + highlightedPanel = -1; + highlightedAction = 0; +} + +void HUD_Panel_EnableMenu() +{ + menu_enabled = 2; + menu_enabled_time = time; + HUD_Panel_GetName(highlightedPanel); + localcmd("menu_showhudoptions ", panel_name, "\n"); +} +float mouse_over_panel; +void HUD_Panel_Mouse() +{ + // TODO: needs better check... is there any float that contains the current state of the menu? _menu_alpha isn't apparently updated the frame the menu gets enabled + if (autocvar__menu_alpha == 0 && time - menu_enabled_time > 0.5) + menu_enabled = 0; + + /* + print("menu_enabled: ", ftos(menu_enabled), "\n"); + print("Highlighted: ", ftos(highlightedPanel), "\n"); + print("Menu theAlpha: ", ftos(autocvar__menu_alpha), "\n"); + */ + + // instantly hide the editor cursor if we open the HUDExit dialog + // as hud_fade_alpha doesn't decrease to 0 in this case + // TODO: find a way to fade the cursor out even in this case + if(menu_enabled == 1 || (menu_enabled == 2 && !hud_fade_alpha)) + return; + + mousepos = mousepos + getmousepos() * autocvar_menu_mouse_speed; + + mousepos_x = bound(0, mousepos_x, vid_conwidth); + mousepos_y = bound(0, mousepos_y, vid_conheight); + + if(mouseClicked) + { + if(prevMouseClicked == 0) + { + if (tab_panel != -1) + { + //stop ctrl-tab selection + tab_panel = -1; + reset_tab_panels(); + } + HUD_Panel_Highlight(mouseClicked & S_MOUSE1); // sets highlightedPanel, highlightedAction, panel_click_distance, panel_click_resizeorigin + // and calls HUD_Panel_UpdatePosSizeForId() for the highlighted panel + if (highlightedPanel != -1) + { + highlightedPanel_initial_pos = panel_pos; + highlightedPanel_initial_size = panel_size; + } + // doubleclick check + if ((mouseClicked & S_MOUSE1) && time - prevMouseClickedTime < 0.4 && highlightedPanel != -1 && prevMouseClickedPos == mousepos) + { + mouseClicked = 0; // to prevent spam, I guess. + HUD_Panel_EnableMenu(); + } + else + { + if (mouseClicked & S_MOUSE1) + { + prevMouseClickedTime = time; + prevMouseClickedPos = mousepos; + } + mouse_over_panel = HUD_Panel_Check_Mouse_Pos(mouseClicked & S_MOUSE1); + } + } + else + HUD_Panel_UpdatePosSizeForId(highlightedPanel); + + if (highlightedPanel != -1) + { + drawfill(panel_pos - '1 1 0' * panel_bg_border, panel_size + '2 2 0' * panel_bg_border, '1 1 1', .1, DRAWFLAG_NORMAL); + if (highlightedPanel_initial_pos != panel_pos || highlightedPanel_initial_size != panel_size) + { + hud_configure_checkcollisions = (!(hudShiftState & S_CTRL) && autocvar_hud_configure_checkcollisions); + // backup! + panel_pos_backup = highlightedPanel_initial_pos; + panel_size_backup = highlightedPanel_initial_size; + highlightedPanel_backup = highlightedPanel; + } + else + // in case the clicked panel is inside another panel and we aren't + // moving it, avoid the immediate "fix" of its position/size + // (often unwanted and hateful) by disabling collisions check + hud_configure_checkcollisions = false; + } + + if(highlightedAction == 1) + HUD_Panel_SetPos(mousepos - panel_click_distance); + else if(highlightedAction == 2) + { + vector mySize; + if(resizeCorner == 1) { + mySize_x = panel_click_resizeorigin_x - (mousepos_x - panel_click_distance_x); + mySize_y = panel_click_resizeorigin_y - (mousepos_y - panel_click_distance_y); + } else if(resizeCorner == 2) { + mySize_x = mousepos_x + panel_click_distance_x - panel_click_resizeorigin_x; + mySize_y = panel_click_distance_y + panel_click_resizeorigin_y - mousepos_y; + } else if(resizeCorner == 3) { + mySize_x = panel_click_resizeorigin_x + panel_click_distance_x - mousepos_x; + mySize_y = mousepos_y + panel_click_distance_y - panel_click_resizeorigin_y; + } else { // resizeCorner == 4 + mySize_x = mousepos_x - (panel_click_resizeorigin_x - panel_click_distance_x); + mySize_y = mousepos_y - (panel_click_resizeorigin_y - panel_click_distance_y); + } + HUD_Panel_SetPosSize(mySize); + } + } + else + { + if(menu_enabled == 2) + mouse_over_panel = 0; + else + mouse_over_panel = HUD_Panel_Check_Mouse_Pos(TRUE); + if (mouse_over_panel && tab_panel == -1) + drawfill(panel_pos - '1 1 0' * panel_bg_border, panel_size + '2 2 0' * panel_bg_border, '1 1 1', .1, DRAWFLAG_NORMAL); + } + // draw cursor after performing move/resize to have the panel pos/size updated before mouse_over_panel + const vector cursorsize = '32 32 0'; + + if(!mouse_over_panel) + drawpic(mousepos, strcat("gfx/menu/", autocvar_menu_skin, "/cursor.tga"), cursorsize, '1 1 1', hud_fade_alpha, DRAWFLAG_NORMAL); + else if(mouse_over_panel == 1) + drawpic(mousepos - cursorsize * 0.5, strcat("gfx/menu/", autocvar_menu_skin, "/cursor_move.tga"), cursorsize, '1 1 1', hud_fade_alpha, DRAWFLAG_NORMAL); + else if(mouse_over_panel == 2) + drawpic(mousepos - cursorsize * 0.5, strcat("gfx/menu/", autocvar_menu_skin, "/cursor_resize.tga"), cursorsize, '1 1 1', hud_fade_alpha, DRAWFLAG_NORMAL); + else + drawpic(mousepos - cursorsize * 0.5, strcat("gfx/menu/", autocvar_menu_skin, "/cursor_resize2.tga"), cursorsize, '1 1 1', hud_fade_alpha, DRAWFLAG_NORMAL); + + prevMouseClicked = mouseClicked; +} + +const float hlBorderSize = 4; +const string hlBorder = "gfx/hud/default/border_highlighted"; +const string hlBorder2 = "gfx/hud/default/border_highlighted2"; +void HUD_Panel_HlBorder(float myBorder, vector color, float theAlpha) +{ + drawfill(panel_pos - '1 1 0' * myBorder, panel_size + '2 2 0' * myBorder, '0 0.5 1', .5 * theAlpha, DRAWFLAG_NORMAL); + drawpic_tiled(panel_pos - '1 1 0' * myBorder, hlBorder, '8 1 0' * hlBorderSize, eX * (panel_size_x + 2 * myBorder) + eY * hlBorderSize, color, theAlpha, DRAWFLAG_NORMAL); + drawpic_tiled(panel_pos - '1 1 0' * myBorder + eY * (panel_size_y + 2 * myBorder - hlBorderSize), hlBorder, '8 1 0' * hlBorderSize, eX * (panel_size_x + 2 * myBorder) + eY * hlBorderSize, color, theAlpha, DRAWFLAG_NORMAL); + drawpic_tiled(panel_pos - '1 1 0' * myBorder + eY * hlBorderSize, hlBorder2, '1 8 0' * hlBorderSize, eY * (panel_size_y + 2 * myBorder - 2 * hlBorderSize) + eX * hlBorderSize, color, theAlpha, DRAWFLAG_NORMAL); + drawpic_tiled(panel_pos - '1 1 0' * myBorder + eY * hlBorderSize + eX * (panel_size_x + 2 * myBorder - hlBorderSize), hlBorder2, '1 8 0' * hlBorderSize, eY * (panel_size_y + 2 * myBorder - 2 * hlBorderSize) + eX * hlBorderSize, color, theAlpha, DRAWFLAG_NORMAL); +} diff --git a/qcsrc/client/interpolate.qc b/qcsrc/client/interpolate.qc deleted file mode 100644 index f96d3d7f96..0000000000 --- a/qcsrc/client/interpolate.qc +++ /dev/null @@ -1,102 +0,0 @@ -// FIXME make this generic code, to be used for other entities too? -.vector iorigin1, iorigin2; -.vector ivelocity1, ivelocity2; -.vector iforward1, iforward2; -.vector iup1, iup2; -.float itime1, itime2; -void InterpolateOrigin_Reset() -{ - self.iflags &~= IFLAG_INTERNALMASK; - self.itime1 = self.itime2 = 0; -} -void InterpolateOrigin_Note() -{ - float dt; - float f0; - - dt = time - self.itime2; - - f0 = self.iflags; - if(self.iflags & IFLAG_PREVALID) - self.iflags |= IFLAG_VALID; - else - self.iflags |= IFLAG_PREVALID; - - self.iorigin1 = self.iorigin2; - self.iorigin2 = self.origin; - - if(self.iflags & IFLAG_AUTOANGLES) - if(self.iorigin2 != self.iorigin1) - self.angles = vectoangles(self.iorigin2 - self.iorigin1); - - if(self.iflags & IFLAG_ANGLES) - { - fixedmakevectors(self.angles); - if(f0 & IFLAG_VALID) - { - self.iforward1 = self.iforward2; - self.iup1 = self.iup2; - } - else - { - self.iforward1 = v_forward; - self.iup1 = v_up; - } - self.iforward2 = v_forward; - self.iup2 = v_up; - } - - if(self.iflags & IFLAG_VELOCITY) - { - self.ivelocity1 = self.ivelocity2; - self.ivelocity2 = self.velocity; - } - - if(vlen(self.iorigin2 - self.iorigin1) > 1000) - { - self.itime1 = self.itime2 = time; // don't lerp - } - - if((self.iflags & IFLAG_VELOCITY) && (vlen(self.ivelocity2 - self.ivelocity1) > 1000)) - { - self.itime1 = self.itime2 = time; // don't lerp - } - - if(dt < 0.2) - { - self.itime1 = serverprevtime; - self.itime2 = time; - } - else - { - // don't lerp - self.itime1 = self.itime2 = time; - } -} -void InterpolateOrigin_Do() -{ - vector forward, up; - if(self.itime1 && self.itime2 && self.itime1 != self.itime2) - { - float f; - f = bound(0, (time - self.itime1) / (self.itime2 - self.itime1), 1); - self.origin = (1 - f) * self.iorigin1 + f * self.iorigin2; - if(self.iflags & IFLAG_ANGLES) - { - forward = (1 - f) * self.iforward1 + f * self.iforward2; - up = (1 - f) * self.iup1 + f * self.iup2; - self.angles = fixedvectoangles2(forward, up); - } - if(self.iflags & IFLAG_VELOCITY) - self.velocity = (1 - f) * self.ivelocity1 + f * self.ivelocity2; - } -} -void InterpolateOrigin_Undo() -{ - self.origin = self.iorigin2; - if(self.iflags & IFLAG_ANGLES) - self.angles = fixedvectoangles2(self.iforward2, self.iup2); - if(self.iflags & IFLAG_VELOCITY) - self.velocity = self.ivelocity2; -} - diff --git a/qcsrc/client/interpolate.qh b/qcsrc/client/interpolate.qh deleted file mode 100644 index a0488038cd..0000000000 --- a/qcsrc/client/interpolate.qh +++ /dev/null @@ -1,19 +0,0 @@ -.float iflags; -#define IFLAG_VELOCITY 1 -#define IFLAG_ANGLES 2 -#define IFLAG_AUTOANGLES 4 -#define IFLAG_VALID 8 -#define IFLAG_PREVALID 16 -#define IFLAG_INTERNALMASK (IFLAG_VALID | IFLAG_PREVALID) - -// call this BEFORE reading an entity update -void InterpolateOrigin_Undo(); - -// call this AFTER receiving an entity update -void InterpolateOrigin_Note(); - -// call this when the entity got teleported, before InterpolateOrigin_Note -void InterpolateOrigin_Reset(); - -// call this BEFORE drawing -void InterpolateOrigin_Do(); diff --git a/qcsrc/client/laser.qc b/qcsrc/client/laser.qc index 0880ddc4b2..a91e13b019 100644 --- a/qcsrc/client/laser.qc +++ b/qcsrc/client/laser.qc @@ -62,7 +62,7 @@ void Draw_Laser() if(self.cnt >= 0) pointparticles(self.cnt, trace_endpos, trace_plane_normal, drawframetime * 1000); if(self.colormod != '0 0 0' && self.modelscale != 0) - R_AddDynamicLight(trace_endpos + trace_plane_normal * 1, self.modelscale, self.colormod * 5); + adddynamiclight(trace_endpos + trace_plane_normal * 1, self.modelscale, self.colormod * 5); } } diff --git a/qcsrc/client/main.qh b/qcsrc/client/main.qh index 625a4ba7be..43e7b64995 100644 --- a/qcsrc/client/main.qh +++ b/qcsrc/client/main.qh @@ -17,12 +17,6 @@ float menu_visible; var void() menu_show; var float(float bInputType, float nPrimary, float nSecondary) menu_action; -// -------------------------------------------------------------------------- -// CTF - -void() ctf_menu_show; -string ctf_temp_1; - // -------------------------------------------------------------------------- // Onslaught @@ -80,15 +74,12 @@ float hud_size[MAX_HUD_FIELDS + 1]; string hud_title[MAX_HUD_FIELDS + 1]; float hud_num_fields; -float hud_font; -float hud_bigfont; - string scores_label[MAX_SCORE]; float scores_flags[MAX_SCORE]; string teamscores_label[MAX_SCORE]; float teamscores_flags[MAX_SCORE]; -.float scores[MAX_SCORE]; FTEQCC_YOU_SUCK_THIS_IS_NOT_UNREFERENCED(scores); -.float teamscores[MAX_TEAMSCORE]; FTEQCC_YOU_SUCK_THIS_IS_NOT_UNREFERENCED(teamscores); +.float scores[MAX_SCORE]; +.float teamscores[MAX_TEAMSCORE]; #define IS_INCREASING(x) ( (x)&SFL_LOWER_IS_BETTER ) #define IS_DECREASING(x) ( !((x)&SFL_LOWER_IS_BETTER) ) @@ -116,16 +107,15 @@ vector view_origin, view_angles, view_forward, view_right, view_up; float button_zoom; float spectatorbutton_zoom; float button_attack2; + float activeweapon; +float switchingweapon; +float switchweapon; float current_viewzoom; float zoomin_effect; -float ignore_plus_zoom; -float ignore_minus_zoom; float warmup_stage; string getcommandkey(string text, string command); -float hud_showbinds; -float hud_showbinds_limit; string vote_called_vote; float ready_waiting; @@ -133,10 +123,6 @@ float ready_waiting_for_me; float vote_waiting; float vote_waiting_for_me; -float previous_game_starttime; -entity restartAnnouncer; //a temporary entity which will play the countdown sounds 3, 2, 1 for the client -void restartAnnouncer_Think(); - float current_zoomfraction; float cs_project_is_b0rked; @@ -147,7 +133,8 @@ float chase_active_backup; float camera_roll; vector camera_direction; -void centerprint(string strMessage); +void centerprint_hud(string strMessage); +void centerprint_generic(float new_id, string strMessage, float duration, float countdown_num); #define ALPHA_MIN_VISIBLE 0.003 @@ -165,3 +152,10 @@ float g_balance_grenadelauncher_bouncefactor; float g_balance_grenadelauncher_bouncestop; float g_balance_electro_secondary_bouncefactor; float g_balance_electro_secondary_bouncestop; +float g_trueaim_minrange; + +entity entcs_receiver[255]; // 255 is the engine limit on maxclients + +float hud; +float view_quality; +float framecount; diff --git a/qcsrc/client/mapvoting.qc b/qcsrc/client/mapvoting.qc index 8ff4817b0f..4cb8dad05f 100644 --- a/qcsrc/client/mapvoting.qc +++ b/qcsrc/client/mapvoting.qc @@ -12,6 +12,8 @@ float mv_ownvote; float mv_detail; float mv_timeout; float mv_maps_mask; +float mv_top2_time; +float mv_top2_alpha; vector mv_mousepos; float mv_selection; @@ -19,13 +21,13 @@ float mv_selection; string MapVote_FormatMapItem(float id, string map, float count, float maxwidth, vector fontsize) { string pre, post; - pre = strcat(ftos(id+1), ". "); + pre = sprintf("%d. ", id+1); if(mv_detail) { if(count == 1) - post = strcat(" (1 vote)"); - else - post = strcat(" (", ftos(count), " votes)"); + post = _(" (1 vote)"); + else if(count >= 0) + post = sprintf(_(" (%d votes)"), count); } else post = ""; @@ -34,8 +36,10 @@ string MapVote_FormatMapItem(float id, string map, float count, float maxwidth, return strcat(pre, map, post); } -vector MapVote_RGB(float id) +vector MapVote_RGB(float id, float count) { + if(count < 0) + return '1 1 1'; if(id == mv_ownvote) return '0 1 0'; else if (id == mv_selection) @@ -53,20 +57,25 @@ void MapVote_DrawMapItem(vector pos, float isize, float tsize, string map, strin isize -= hud_fontsize_y; // respect the text when calculating the image size - rgb = MapVote_RGB(id); + rgb = MapVote_RGB(id, count); img_size_y = isize; img_size_x = isize / 0.75; // 4:3 x can be stretched easily, height is defined in isize - drawfont = hud_font; pos_y = pos_y + img_size_y; label = MapVote_FormatMapItem(id, map, count, tsize, hud_fontsize); text_size = stringwidth(label, false, hud_fontsize); - + + float theAlpha; + if (count < 0 && mv_top2_alpha) + theAlpha = mv_top2_alpha; + else + theAlpha = 1; + pos_x -= text_size*0.5; - drawstring(pos, label, hud_fontsize, rgb, 1, DRAWFLAG_NORMAL); + drawstring(pos, label, hud_fontsize, rgb, theAlpha, DRAWFLAG_NORMAL); pos_x = pos_x + text_size*0.5 - img_size_x*0.5; pos_y = pos_y - img_size_y; @@ -75,19 +84,22 @@ void MapVote_DrawMapItem(vector pos, float isize, float tsize, string map, strin img_size -= (autocvar_scoreboard_border_thickness * 2) * '1 1 0'; if(pic == "") { - drawfill(pos, img_size, '.5 .5 .5', .7, DRAWFLAG_NORMAL); + drawfill(pos, img_size, '.5 .5 .5', .7 * theAlpha, DRAWFLAG_NORMAL); } else { - drawpic(pos, pic, img_size, '1 1 1', 1, DRAWFLAG_NORMAL); + if(drawgetimagesize(pic) == '0 0 0') + drawpic(pos, draw_UseSkinFor("nopreview_map"), img_size, '1 1 1', theAlpha, DRAWFLAG_NORMAL); + else + drawpic(pos, pic, img_size, '1 1 1', theAlpha, DRAWFLAG_NORMAL); } if(id == mv_ownvote) - drawborderlines(autocvar_scoreboard_border_thickness, pos, img_size, rgb, 1, DRAWFLAG_NORMAL); + drawborderlines(autocvar_scoreboard_border_thickness, pos, img_size, rgb, theAlpha, DRAWFLAG_NORMAL); else - drawborderlines(autocvar_scoreboard_border_thickness, pos, img_size, '0 0 0', 1, DRAWFLAG_NORMAL); + drawborderlines(autocvar_scoreboard_border_thickness, pos, img_size, '0 0 0', theAlpha, DRAWFLAG_NORMAL); - if(id == mv_selection) + if(id == mv_selection && count >= 0) drawfill(pos, img_size, '1 1 1', 0.1, DRAWFLAG_NORMAL); } @@ -97,12 +109,11 @@ void MapVote_DrawAbstain(vector pos, float isize, float tsize, float count, floa float text_size; string label; - rgb = MapVote_RGB(id); + rgb = MapVote_RGB(id, count); - drawfont = hud_font; pos_y = pos_y + hud_fontsize_y; - label = MapVote_FormatMapItem(id, "Don't care", count, tsize, hud_fontsize); + label = MapVote_FormatMapItem(id, _("Don't care"), count, tsize, hud_fontsize); text_size = stringwidth(label, false, hud_fontsize); @@ -162,7 +173,7 @@ void MapVote_Draw() if(!mv_active) return; - + mv_mousepos = mv_mousepos + getmousepos(); mv_mousepos_x = bound(0, mv_mousepos_x, vid_conwidth); @@ -178,31 +189,28 @@ void MapVote_Draw() if(i >= 0 || ymax < (vid_conheight*0.5)) ymax = vid_conheight - ymin; - drawfont = hud_bigfont; hud_fontsize = HUD_GetFontsize("hud_fontsize"); pos_y = ymin; pos_z = 0; - //pos_x = center - stringwidth("Vote for a map", false) * 0.5 * 24; - pos_x = center - stringwidth("Vote for a map", false, '12 0 0'); - drawstring(pos, "Vote for a map", '24 24 0', '1 1 1', 1, DRAWFLAG_NORMAL); + + map = _("Vote for a map"); + pos_x = center - stringwidth(map, false, '12 0 0'); + drawstring(pos, map, '24 24 0', '1 1 1', 1, DRAWFLAG_NORMAL); pos_y += 26; i = ceil(max(0, mv_timeout - time)); - map = strcat(ftos(i), " seconds left"); - //pos_x = center - stringwidth(map, false) * 0.5 * 16; + map = sprintf(_("%d seconds left"), i); pos_x = center - stringwidth(map, false, '8 0 0'); drawstring(pos, map, '16 16 0', '0 1 0', 1, DRAWFLAG_NORMAL); pos_y += 22; pos_x = xmin; - drawfont = hud_font; - // base for multi-column stuff... ymin = pos_y; if(mv_abstain) mv_num_maps -= 1; - + if(mv_num_maps > 3) { columns = 3; @@ -222,11 +230,12 @@ void MapVote_Draw() pos_y += (dist_y - isize) / 2; ymax -= isize; + if (mv_top2_time) + mv_top2_alpha = max(0.2, 1 - (time - mv_top2_time)*(time - mv_top2_time)); + for(i = 0; i < mv_num_maps; ++i) { tmp = mv_votes[i]; // FTEQCC bug: too many array accesses in the function call screw it up - if(tmp < 0) - continue; map = mv_maps[i]; if(mv_preview[i]) MapVote_DrawMapItem(pos + MapVote_GridVec(dist, i, columns), isize, tsize, map, mv_pics[i], tmp, i); @@ -236,7 +245,7 @@ void MapVote_Draw() if(mv_abstain) ++mv_num_maps; - + if(mv_abstain && i < mv_num_maps) { tmp = mv_votes[i]; pos_y = ymax + isize - hud_fontsize_y; @@ -254,7 +263,7 @@ void Cmd_MapVote_MapDownload(float argc) if(argc != 2 || !mv_pk3list) { - print("mv_mapdownload: ^3You're not supposed to use this command on your own!\n"); + print(_("mv_mapdownload: ^3You're not supposed to use this command on your own!\n")); return; } @@ -264,20 +273,17 @@ void Cmd_MapVote_MapDownload(float argc) break; if(!pak || pak.sv_entnum != id) { - print("^1Error:^7 Couldn't find pak index.\n"); + print(_("^1Error:^7 Couldn't find pak index.\n")); return; } - //print(strcat("^3Adding: ", ftos(id), " - ", pak.message, " - ")); - if(PreviewExists(pak.message)) { mv_preview[id] = true; - //print("^2Found...\n"); return; } else { - print("Requesting preview...\n"); - localcmd(strcat("\ncmd mv_getpic ", ftos(id), "\n")); + print(_("Requesting preview...\n")); + localcmd(strcat("\ncmd mv_getpicture ", ftos(id), "\n")); } } @@ -355,8 +361,8 @@ void MapVote_Init() else mv_maps_mask = ReadShort(); - // Assume mv_pk3list is NULL, there should only be 1 mapvote per round - mv_pk3list = NULL; // I'm still paranoid! + // Assume mv_pk3list is world, there should only be 1 mapvote per round + mv_pk3list = world; // I'm still paranoid! for(i = 0, power = 1; i < mv_num_maps; ++i, power *= 2) { @@ -375,7 +381,6 @@ void MapVote_Init() mv_preview[i] = false; - //print(strcat("RECV: ", map, " in ", pk3, "\n")); MapVote_CheckPic(map, pk3, i); } else @@ -409,6 +414,19 @@ float MapVote_InputEvent(float bInputType, float nPrimary, float nSecondary) localcmd(strcat("\nimpulse ", ftos(imp), "\n")); return true; } + switch(nPrimary) + { + case K_KP_1: localcmd("\nimpulse 1\n"); return true; + case K_KP_2: localcmd("\nimpulse 2\n"); return true; + case K_KP_3: localcmd("\nimpulse 3\n"); return true; + case K_KP_4: localcmd("\nimpulse 4\n"); return true; + case K_KP_5: localcmd("\nimpulse 5\n"); return true; + case K_KP_6: localcmd("\nimpulse 6\n"); return true; + case K_KP_7: localcmd("\nimpulse 7\n"); return true; + case K_KP_8: localcmd("\nimpulse 8\n"); return true; + case K_KP_9: localcmd("\nimpulse 9\n"); return true; + case K_KP_0: localcmd("\nimpulse 10\n"); return true; + } if (nPrimary == K_MOUSE1) if (mv_selection >= 0) @@ -434,12 +452,14 @@ void MapVote_UpdateMask() if(oldmask & mv_maps_mask != oldmask) if(oldmask & mv_maps_mask == mv_maps_mask) - sound(world, CHAN_AUTO, "misc_invshot.wav", VOL_BASE, ATTN_NONE); + sound(world, CH_INFO, "misc_invshot.wav", VOL_BASE, ATTN_NONE); // remove votes that no longer apply for(i = 0, power = 1; i < mv_num_maps; ++i, power *= 2) if not(mv_maps_mask & power) mv_votes[i] = -1; + + mv_top2_time = time; } void MapVote_UpdateVotes() diff --git a/qcsrc/client/miscfunctions.qc b/qcsrc/client/miscfunctions.qc index 57e25810f7..2bc20e9510 100644 --- a/qcsrc/client/miscfunctions.qc +++ b/qcsrc/client/miscfunctions.qc @@ -3,190 +3,6 @@ var float(string text, float handleColors, vector fontSize) stringwidth; entity players; entity teams; -void serverAnnouncer() -{ - // check for pending announcement, play it and remove it - if(announce_snd != "") - { - sound(world, CHAN_AUTO, strcat("announcer/", autocvar_cl_announcer, "/", announce_snd, ".wav"), VOL_BASEVOICE, ATTN_NONE); - strunzone(announce_snd); - announce_snd = ""; - } -} - -void restartAnnouncer_Think() { - float countdown_rounded, countdown; - countdown = getstatf(STAT_GAMESTARTTIME) - time; - countdown_rounded = floor(0.5 + countdown); - if(countdown <= 0) { - if (!spectatee_status) //do cprint only for players - centerprint("^1Begin!"); - - sound(world, CHAN_AUTO, strcat("announcer/", autocvar_cl_announcer, "/begin.wav"), VOL_BASEVOICE, ATTN_NONE); - //reset maptime announcers now as well - announcer_5min = announcer_1min = FALSE; - - remove(self); - return; - } - else { - if (!spectatee_status) //do cprint only for players - centerprint(strcat("^1Game starts in ", ftos(countdown_rounded), " seconds")); - - if(countdown_rounded <= 3 && countdown_rounded >= 1) { - sound(world, CHAN_AUTO, strcat("announcer/", autocvar_cl_announcer, "/", ftos(countdown_rounded), ".wav"), VOL_BASEVOICE, ATTN_NONE); - } - - self.nextthink = getstatf(STAT_GAMESTARTTIME) - (countdown - 1); - } -} - -/** - * Plays the 1minute or 5 minutes (of maptime) remaining sound, if client wants it - */ -void maptimeAnnouncer() { - float timelimit; - timelimit = getstatf(STAT_TIMELIMIT); - float timeleft; - timeleft = max(0, timelimit * 60 + getstatf(STAT_GAMESTARTTIME) - time); - - float warmuplimit; - float warmuptimeleft; - if(warmup_stage) { - warmuplimit = autocvar_g_warmup_limit; - if(warmuplimit > 0) { - warmuptimeleft = max(0, warmuplimit + getstatf(STAT_GAMESTARTTIME) - time); - } - } - - //5 minute check - if (autocvar_cl_sound_maptime_warning >= 2) { - //make sure that after connect (and e.g. 4 minutes left) we will not get a wrong sound - if(announcer_5min) - { - if(((!warmup_stage || warmuplimit == 0) && timeleft > 300) || (warmup_stage && warmuplimit > 0 && warmuptimeleft > 300)) - announcer_5min = FALSE; - } - else if (((!warmup_stage || warmuplimit == 0) && timelimit > 0 && timeleft < 300 && timeleft > 299) || (warmup_stage && warmuplimit > 0 && warmuptimeleft < 300 && warmuptimeleft > 299)) - //if we're in warmup mode, check whether there's a warmup timelimit - if not (warmuplimit == -1 && warmup_stage) { - announcer_5min = TRUE; - //dprint("i will play the sound, I promise!\n"); - sound(world, CHAN_AUTO, strcat("announcer/", autocvar_cl_announcer, "/5minutesremain.wav"), VOL_BASEVOICE, ATTN_NONE); - } - } - - //1 minute check - if (autocvar_cl_sound_maptime_warning == 1 || autocvar_cl_sound_maptime_warning == 3) { - if (announcer_1min) - { - if(((!warmup_stage || warmuplimit == 0) && timeleft > 60) || (warmup_stage && warmuplimit > 0 && warmuptimeleft > 60)) - announcer_1min = FALSE; - } - else if (((!warmup_stage || warmuplimit == 0) && timelimit > 0 && timeleft < 60) || (warmup_stage && warmuplimit > 0 && warmuptimeleft < 60)) - //if we're in warmup mode, check whether there's a warmup timelimit - if not (warmuplimit == -1 && warmup_stage) { - announcer_1min = TRUE; - sound(world, CHAN_AUTO, strcat("announcer/", autocvar_cl_announcer, "/1minuteremains.wav"), VOL_BASEVOICE, ATTN_NONE); - } - } -} - -/** - * Announce carried items (e.g. flags in CTF). - */ -float redflag_prev; -float blueflag_prev; -void carrierAnnouncer() { - float stat_items, redflag, blueflag; - float pickup; - string item; - - if not(autocvar_cl_notify_carried_items) - return; - - stat_items = getstati(STAT_ITEMS); - - redflag = (stat_items/IT_RED_FLAG_TAKEN) & 3; - blueflag = (stat_items/IT_BLUE_FLAG_TAKEN) & 3; - - if (redflag == 3 && redflag != redflag_prev) { - item = "^1RED^7 flag"; - pickup = (redflag_prev == 2); - } - - if (blueflag == 3 && blueflag != blueflag_prev) { - item = "^4BLUE^7 flag"; - pickup = (blueflag_prev == 2); - } - - if (item) - { - if (pickup) { - if (autocvar_cl_notify_carried_items & 2) - centerprint(strcat("You picked up the ", item, "!")); - } - else { - if (autocvar_cl_notify_carried_items & 1) - centerprint(strcat("You got the ", item, "!")); - } - } - - blueflag_prev = blueflag; - redflag_prev = redflag; -} - -/** - * Add all future announcer sounds precaches here. - * TODO: announcer queues - */ -void Announcer_Precache () { - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/1minuteremains.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/5minutesremain.wav")); - - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/electrobitch.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/airshot.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/03kills.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/05kills.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/10kills.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/15kills.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/20kills.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/25kills.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/30kills.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/botlike.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/yoda.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/amazing.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/awesome.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/headshot.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/impressive.wav")); - - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/prepareforbattle.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/begin.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/timeoutcalled.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/1fragleft.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/2fragsleft.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/3fragsleft.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/terminated.wav")); - - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/1.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/2.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/3.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/4.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/5.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/6.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/7.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/8.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/9.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/10.wav")); - - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/lastsecond.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/narrowly.wav")); - - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/voteaccept.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/votecall.wav")); - precache_sound (strcat("announcer/", autocvar_cl_announcer, "/votefail.wav")); -} - void AuditLists() { entity e; @@ -281,7 +97,7 @@ void RemoveTeam(entity Team) if(!tm) { - print("Trying to remove a team which is not in the teamlist!"); + print(_("Trying to remove a team which is not in the teamlist!")); return; } parent.sort_next = Team.sort_next; @@ -298,7 +114,7 @@ entity GetTeam(float Team, float add) if(teamslots[num]) return teamslots[num]; if not(add) - return NULL; + return world; tm = spawn(); tm.team = Team; teamslots[num] = tm; @@ -306,12 +122,6 @@ entity GetTeam(float Team, float add) return tm; } -void CSQC_CheckEngine() -{ - hud_font = FONT_USER+1; - hud_bigfont = FONT_USER+2; -} - vector HUD_GetFontsize(string cvarname) { vector v; @@ -326,40 +136,14 @@ vector HUD_GetFontsize(string cvarname) float PreviewExists(string name) { - float f; - string file; - if(autocvar_cl_readpicture_force) return false; - file = strcat(name, ".tga"); - f = fopen(file, FILE_READ); - if(f >= 0) - { - fclose(f); - return true; - } - file = strcat(name, ".png"); - f = fopen(file, FILE_READ); - if(f >= 0) - { - fclose(f); - return true; - } - file = strcat(name, ".jpg"); - f = fopen(file, FILE_READ); - if(f >= 0) - { - fclose(f); - return true; - } - file = strcat(name, ".pcx"); - f = fopen(file, FILE_READ); - if(f >= 0) - { - fclose(f); - return true; - } + if (fexists(strcat(name, ".tga"))) return true; + if (fexists(strcat(name, ".png"))) return true; + if (fexists(strcat(name, ".jpg"))) return true; + if (fexists(strcat(name, ".pcx"))) return true; + return false; } @@ -382,6 +166,33 @@ string ColorTranslateRGB(string s) return s; } +string Team_ColorCode(float teamid) +{ + if (teamid == COLOR_TEAM1) + return "^1"; + else if (teamid == COLOR_TEAM2) + return "^4"; + else if (teamid == COLOR_TEAM3) + return "^3"; + else if (teamid == COLOR_TEAM4) + return "^6"; + else + return "^7"; +} + +// decolorizes and team colors the player name when needed +string playername(string thename, float teamid) +{ + string t; + if (teamplay) + { + t = Team_ColorCode(teamid); + return strcat(t, strdecolorize(thename)); + } + else + return strdecolorize(thename); +} + float cvar_or(string cv, float v) { string s; @@ -418,7 +229,7 @@ vector expandingbox_resize_centered_box_offset(float sz, vector boxsize, float b return boxsize * (0.5 * (1 - sz)); } -void drawborderlines(float thickness, vector pos, vector dim, vector color, float alpha, float drawflag) +void drawborderlines(float thickness, vector pos, vector dim, vector color, float theAlpha, float drawflag) { vector line_dim; @@ -426,18 +237,18 @@ void drawborderlines(float thickness, vector pos, vector dim, vector color, floa pos_x -= thickness; line_dim_x = thickness; line_dim_y = dim_y; - drawfill(pos, line_dim, color, alpha, drawflag); - drawfill(pos + (dim_x + thickness) * '1 0 0', line_dim, color, alpha, drawflag); + drawfill(pos, line_dim, color, theAlpha, drawflag); + drawfill(pos + (dim_x + thickness) * '1 0 0', line_dim, color, theAlpha, drawflag); // upper and lower lines pos_y -= thickness; line_dim_x = dim_x + thickness * 2; // make upper and lower lines longer line_dim_y = thickness; - drawfill(pos, line_dim, color, alpha, drawflag); - drawfill(pos + (dim_y + thickness) * '0 1 0', line_dim, color, alpha, drawflag); + drawfill(pos, line_dim, color, theAlpha, drawflag); + drawfill(pos + (dim_y + thickness) * '0 1 0', line_dim, color, theAlpha, drawflag); } -void drawpic_tiled(vector pos, string pic, vector sz, vector area, vector color, float alpha, float drawflag) +void drawpic_tiled(vector pos, string pic, vector sz, vector area, vector color, float theAlpha, float drawflag) { vector current_pos, end_pos, new_size, ratio; end_pos = pos + area; @@ -452,7 +263,7 @@ void drawpic_tiled(vector pos, string pic, vector sz, vector area, vector color, new_size_y = min(sz_y, end_pos_y - current_pos_y); ratio_x = new_size_x / sz_x; ratio_y = new_size_y / sz_y; - drawsubpic(current_pos, new_size, pic, '0 0 0', ratio, color, alpha, drawflag); + drawsubpic(current_pos, new_size, pic, '0 0 0', ratio, color, theAlpha, drawflag); current_pos_x += sz_x; } current_pos_y += sz_y; @@ -461,115 +272,95 @@ void drawpic_tiled(vector pos, string pic, vector sz, vector area, vector color, // drawpic wrapper to draw an image as large as possible with preserved aspect ratio into a box var float _drawpic_imgaspect; -var float _drawpic_aspect; var vector _drawpic_imgsize; var vector _drawpic_sz; -var vector _drawpic_oldsz; +var float _drawpic_oldsz; var string _drawpic_picpath; -#define drawpic_aspect(pos,pic,mySize,color,alpha,drawflag)\ +#define drawpic_aspect(pos,pic,mySize,color,theAlpha,drawflag)\ do {\ - _drawpic_imgsize = drawgetimagesize(pic);\ + _drawpic_imgsize = draw_getimagesize(pic);\ _drawpic_imgaspect = _drawpic_imgsize_x/_drawpic_imgsize_y;\ - _drawpic_oldsz = _drawpic_sz = mySize;\ - _drawpic_aspect = _drawpic_sz_x/_drawpic_sz_y;\ - if(_drawpic_aspect > _drawpic_imgaspect) {\ + _drawpic_sz = mySize;\ + if(_drawpic_sz_x/_drawpic_sz_y > _drawpic_imgaspect) {\ + _drawpic_oldsz = _drawpic_sz_x;\ _drawpic_sz_x = _drawpic_sz_y * _drawpic_imgaspect;\ - drawpic(pos + eX * (_drawpic_oldsz_x - _drawpic_sz_x) * 0.5, pic, _drawpic_sz, color, alpha, drawflag);\ + drawpic(pos + eX * (_drawpic_oldsz - _drawpic_sz_x) * 0.5, pic, _drawpic_sz, color, theAlpha, drawflag);\ } else {\ + _drawpic_oldsz = _drawpic_sz_y;\ _drawpic_sz_y = _drawpic_sz_x / _drawpic_imgaspect;\ - drawpic(pos + eY * (_drawpic_oldsz_y - _drawpic_sz_y) * 0.5, pic, _drawpic_sz, color, alpha, drawflag);\ + drawpic(pos + eY * (_drawpic_oldsz - _drawpic_sz_y) * 0.5, pic, _drawpic_sz, color, theAlpha, drawflag);\ }\ } while(0) // draw HUD element with image from gfx/hud/hud_skin/foo.tga if it exists, otherwise gfx/hud/default/foo.tga -#define drawpic_aspect_skin(pos,pic,sz,color,alpha,drawflag)\ +#define drawpic_aspect_skin(pos,pic,sz,color,theAlpha,drawflag)\ do{\ _drawpic_picpath = strcat(hud_skin_path, "/", pic);\ if(precache_pic(_drawpic_picpath) == "") {\ _drawpic_picpath = strcat("gfx/hud/default/", pic);\ }\ - drawpic_aspect(pos, _drawpic_picpath, sz, color, alpha, drawflag);\ + drawpic_aspect(pos, _drawpic_picpath, sz, color, theAlpha, drawflag);\ _drawpic_picpath = string_null;\ } while(0) // draw HUD element with image from gfx/hud/hud_skin/foo.tga if it exists, otherwise gfx/hud/default/foo.tga -#define drawpic_skin(pos,pic,sz,color,alpha,drawflag)\ +#define drawpic_skin(pos,pic,sz,color,theAlpha,drawflag)\ do{\ _drawpic_picpath = strcat(hud_skin_path, "/", pic);\ if(precache_pic(_drawpic_picpath) == "") {\ _drawpic_picpath = strcat("gfx/hud/default/", pic);\ }\ - drawpic(pos, _drawpic_picpath, sz, color, alpha, drawflag);\ + drawpic(pos, _drawpic_picpath, sz, color, theAlpha, drawflag);\ _drawpic_picpath = string_null;\ } while(0) -void drawpic_aspect_skin_expanding(vector position, string pic, vector scale, vector rgb, float alpha, float flag, float fadelerp) +void drawpic_aspect_skin_expanding(vector position, string pic, vector scale, vector rgb, float theAlpha, float flag, float fadelerp) { float sz; sz = expandingbox_sizefactor_from_fadelerp(fadelerp); - drawpic_skin(position + expandingbox_resize_centered_box_offset(sz, scale, 1), pic, scale * sz, rgb, alpha * (1 - fadelerp), flag); + drawpic_aspect_skin(position + expandingbox_resize_centered_box_offset(sz, scale, 1), pic, scale * sz, rgb, theAlpha * (1 - fadelerp), flag); } -void drawpic_aspect_skin_expanding_two(vector position, string pic, vector scale, vector rgb, float alpha, float flag, float fadelerp) +void drawpic_aspect_skin_expanding_two(vector position, string pic, vector scale, vector rgb, float theAlpha, float flag, float fadelerp) { - drawpic_aspect_skin_expanding(position, pic, scale, rgb, alpha, flag, fadelerp); - drawpic_skin(position, pic, scale, rgb, alpha * fadelerp, flag); -} + drawpic_aspect_skin_expanding(position, pic, scale, rgb, theAlpha, flag, fadelerp); + drawpic_skin(position, pic, scale, rgb, theAlpha * fadelerp, flag); +} +#define SET_POS_AND_SZ_Y_ASPECT(allow_colors)\ + float textaspect, oldsz;\ + textaspect = stringwidth(text, allow_colors, '1 1 1' * sz_y) / sz_y;\ + if(sz_x/sz_y > textaspect) {\ + oldsz = sz_x;\ + sz_x = sz_y * textaspect;\ + pos_x += (oldsz - sz_x) * 0.5;\ + } else {\ + oldsz = sz_y;\ + sz_y = sz_x / textaspect; \ + pos_y += (oldsz - sz_y) * 0.5;\ + } // drawstring wrapper to draw a string as large as possible with preserved aspect ratio into a box -void drawstring_aspect(vector pos, string text, vector sz, vector color, float alpha, float drawflag) { - vector textsize; - textsize = eX * stringwidth(text, FALSE, '1 1 1' * sz_y) + eY * sz_y; - - float textaspect; - textaspect = textsize_x/textsize_y; - - vector oldsz; - oldsz = sz; - float aspect; - aspect = sz_x/sz_y; - - if(aspect > textaspect) { - sz_x = sz_y * textaspect; - drawstring(pos + eX * (oldsz_x - sz_x) * 0.5, text, '1 1 0' * sz_y, color, alpha, drawflag); - } else { - sz_y = sz_x / textaspect; - drawstring(pos + eY * (oldsz_y - sz_y) * 0.5, text, '1 1 0' * sz_y, color, alpha, drawflag); - } +void drawstring_aspect(vector pos, string text, vector sz, vector color, float theAlpha, float drawflag) { + SET_POS_AND_SZ_Y_ASPECT(FALSE) + drawstring(pos, text, '1 1 0' * sz_y, color, theAlpha, drawflag); } // drawstring wrapper to draw a colorcodedstring as large as possible with preserved aspect ratio into a box -void drawcolorcodedstring_aspect(vector pos, string text, vector sz, float alpha, float drawflag) { - vector textsize; - textsize = eX * stringwidth(text, TRUE, '1 1 1' * sz_y) + eY * sz_y; - - float textaspect; - textaspect = textsize_x/textsize_y; - - vector oldsz; - oldsz = sz; - float aspect; - aspect = sz_x/sz_y; - - if(aspect > textaspect) { - sz_x = sz_y * textaspect; - drawcolorcodedstring(pos + eX * (oldsz_x - sz_x) * 0.5, text, '1 1 0' * sz_y, alpha, drawflag); - } else { - sz_y = sz_x / textaspect; - drawcolorcodedstring(pos + eY * (oldsz_y - sz_y) * 0.5, text, '1 1 0' * sz_y, alpha, drawflag); - } +void drawcolorcodedstring_aspect(vector pos, string text, vector sz, float theAlpha, float drawflag) { + SET_POS_AND_SZ_Y_ASPECT(TRUE) + drawcolorcodedstring(pos, text, '1 1 0' * sz_y, theAlpha, drawflag); } vector drawfontscale; -void drawstring_expanding(vector position, string text, vector scale, vector rgb, float alpha, float flag, float fadelerp) +void drawstring_expanding(vector position, string text, vector scale, vector rgb, float theAlpha, float flag, float fadelerp) { float sz; sz = expandingbox_sizefactor_from_fadelerp(fadelerp); drawfontscale = sz * '1 1 0'; dummyfunction(0, 0, 0, 0, 0, 0, 0, 0); - drawstring(position + expandingbox_resize_centered_box_offset(sz, scale, stringwidth(text, FALSE, scale * (sz / drawfontscale_x)) / (scale_x * sz)), text, scale * (sz / drawfontscale_x), rgb, alpha * (1 - fadelerp), flag); + drawstring(position + expandingbox_resize_centered_box_offset(sz, scale, stringwidth(text, FALSE, scale * (sz / drawfontscale_x)) / (scale_x * sz)), text, scale * (sz / drawfontscale_x), rgb, theAlpha * (1 - fadelerp), flag); // width parameter: // (scale_x * sz / drawfontscale_x) * drawfontscale_x * SIZE1 / (scale_x * sz) // SIZE1 @@ -577,57 +368,25 @@ void drawstring_expanding(vector position, string text, vector scale, vector rgb } // drawstring wrapper to draw a string as large as possible with preserved aspect ratio into a box -void drawstring_aspect_expanding(vector pos, string text, vector sz, vector color, float alpha, float drawflag, float fadelerp) { - vector textsize; - textsize = eX * stringwidth(text, FALSE, '1 1 1' * sz_y) + eY * sz_y; - - float textaspect; - textaspect = textsize_x/textsize_y; - - vector oldsz; - oldsz = sz; - float aspect; - aspect = sz_x/sz_y; - - if(aspect > textaspect) { - sz_x = sz_y * textaspect; - drawstring_expanding(pos + eX * (oldsz_x - sz_x) * 0.5, text, '1 1 0' * sz_y, color, alpha, drawflag, fadelerp); - } else { - sz_y = sz_x / textaspect; - drawstring_expanding(pos + eY * (oldsz_y - sz_y) * 0.5, text, '1 1 0' * sz_y, color, alpha, drawflag, fadelerp); - } +void drawstring_aspect_expanding(vector pos, string text, vector sz, vector color, float theAlpha, float drawflag, float fadelerp) { + SET_POS_AND_SZ_Y_ASPECT(FALSE) + drawstring_expanding(pos, text, '1 1 0' * sz_y, color, theAlpha, drawflag, fadelerp); } -void drawcolorcodedstring_expanding(vector position, string text, vector scale, float alpha, float flag, float fadelerp) +void drawcolorcodedstring_expanding(vector position, string text, vector scale, float theAlpha, float flag, float fadelerp) { float sz; sz = expandingbox_sizefactor_from_fadelerp(fadelerp); drawfontscale = sz * '1 1 0'; dummyfunction(0, 0, 0, 0, 0, 0, 0, 0); - drawcolorcodedstring(position + expandingbox_resize_centered_box_offset(sz, scale, stringwidth(text, TRUE, scale * (sz / drawfontscale_x)) / (scale_x * sz)), text, scale * (sz / drawfontscale_x), alpha * (1 - fadelerp), flag); + drawcolorcodedstring(position + expandingbox_resize_centered_box_offset(sz, scale, stringwidth(text, TRUE, scale * (sz / drawfontscale_x)) / (scale_x * sz)), text, scale * (sz / drawfontscale_x), theAlpha * (1 - fadelerp), flag); drawfontscale = '1 1 0'; } -void drawcolorcodedstring_aspect_expanding(vector pos, string text, vector sz, float alpha, float drawflag, float fadelerp) { - vector textsize; - textsize = eX * stringwidth(text, TRUE, '1 1 1' * sz_y) + eY * sz_y; - - float textaspect; - textaspect = textsize_x/textsize_y; - - vector oldsz; - oldsz = sz; - float aspect; - aspect = sz_x/sz_y; - - if(aspect > textaspect) { - sz_x = sz_y * textaspect; - drawcolorcodedstring_expanding(pos + eX * (oldsz_x - sz_x) * 0.5, text, '1 1 0' * sz_y, alpha, drawflag, fadelerp); - } else { - sz_y = sz_x / textaspect; - drawcolorcodedstring_expanding(pos + eY * (oldsz_y - sz_y) * 0.5, text, '1 1 0' * sz_y, alpha, drawflag, fadelerp); - } +void drawcolorcodedstring_aspect_expanding(vector pos, string text, vector sz, float theAlpha, float drawflag, float fadelerp) { + SET_POS_AND_SZ_Y_ASPECT(TRUE) + drawcolorcodedstring_expanding(pos, text, '1 1 0' * sz_y, theAlpha, drawflag, fadelerp); } // this draws the triangles of a model DIRECTLY. Don't expect high performance, really... @@ -809,3 +568,26 @@ void DrawCircleClippedPic(vector centre, float radius, string pic, float f, vect R_EndPolygon(); } } + +const vector GETPLAYERORIGIN_ERROR = '1123581321 2357111317 3141592653'; // way out of bounds for anything on the map +vector getplayerorigin(float pl) +{ + string s; + entity e; + + e = CSQCModel_server2csqc(pl + 1); + if(e) + return e.origin; + +#ifndef NO_LEGACY_NETWORKING + s = getplayerkeyvalue(pl, "TEMPHACK_origin"); + if(s != "") + return stov(s); +#endif + + e = entcs_receiver[pl]; + if(e) + return e.origin; + + return GETPLAYERORIGIN_ERROR; +} diff --git a/qcsrc/client/movetypes.qc b/qcsrc/client/movetypes.qc index 1d6a6e393d..49f35d8912 100644 --- a/qcsrc/client/movetypes.qc +++ b/qcsrc/client/movetypes.qc @@ -1,4 +1,8 @@ -.entity move_groundentity; +float STAT_MOVEFLAGS = 225; +float MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE = 4; +#define GRAVITY_UNAFFECTED_BY_TICRATE (getstati(STAT_MOVEFLAGS) & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE) + +.entity move_groundentity; // FIXME add move_groundnetworkentity? .float move_suspendedinair; .float move_didgravity; @@ -156,10 +160,10 @@ float _Movetype_UnstickEntity() // SV_UnstickEntity if(!_Movetype_TestEntityPosition('0 0 -1' * i)) goto success; if(!_Movetype_TestEntityPosition('0 0 1' * i)) goto success; } - dprint("Some entity is stuck\n"); + dprint(sprintf(_("Can't unstick an entity (edict: %d, classname: %s, origin: %s)\n"), num_for_edict(self), self.classname, vtos(self.move_origin))); return FALSE; :success - dprint("Unstuck some entity\n"); + dprint(sprintf(_("Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)\n"), num_for_edict(self), self.classname, vtos(self.move_origin))); _Movetype_LinkEdict(TRUE); return TRUE; } @@ -232,11 +236,21 @@ void _Movetype_Physics_Toss(float dt) // SV_Physics_Toss if(self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS) { - self.move_didgravity = TRUE; - if(self.gravity) - self.move_velocity_z -= dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY); + self.move_didgravity = 1; + if(GRAVITY_UNAFFECTED_BY_TICRATE) + { + if(self.gravity) + self.move_velocity_z -= 0.5 * dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY); + else + self.move_velocity_z -= 0.5 * dt * getstatf(STAT_MOVEVARS_GRAVITY); + } else - self.move_velocity_z -= dt * getstatf(STAT_MOVEVARS_GRAVITY); + { + if(self.gravity) + self.move_velocity_z -= dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY); + else + self.move_velocity_z -= dt * getstatf(STAT_MOVEVARS_GRAVITY); + } } self.move_angles = self.move_angles + self.move_avelocity * dt; @@ -318,12 +332,22 @@ void _Movetype_Physics_Toss(float dt) // SV_Physics_Toss break; } + if(GRAVITY_UNAFFECTED_BY_TICRATE) + if(self.move_didgravity > 0) + if(!(self.move_flags & FL_ONGROUND)) + { + if(self.gravity) + self.move_velocity_z -= 0.5 * dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY); + else + self.move_velocity_z -= 0.5 * dt * getstatf(STAT_MOVEVARS_GRAVITY); + } + _Movetype_CheckWaterTransition(); } void _Movetype_Physics_Frame(float movedt) { - self.move_didgravity = FALSE; + self.move_didgravity = -1; switch(self.move_movetype) { case MOVETYPE_PUSH: @@ -364,9 +388,6 @@ void Movetype_Physics_NoMatchServer() // optimized movedt = time - self.move_time; self.move_time = time; - //self.move_didgravity = ((self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS) && !(self.move_flags & FL_ONGROUND)); - // we use the field as set by the last run of this - _Movetype_Physics_Frame(movedt); if(wasfreed(self)) return; @@ -399,8 +420,8 @@ void Movetype_Physics_MatchTicrate(float tr, float sloppy) // SV_Physics_Entity dt -= n * tr; self.move_time += n * tr; - //self.move_didgravity = ((self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS) && !(self.move_flags & FL_ONGROUND)); - // we use the field as set by the last run of this + if(!self.move_didgravity) + self.move_didgravity = ((self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS) && !(self.move_flags & FL_ONGROUND)); for(i = 0; i < n; ++i) { @@ -415,12 +436,23 @@ void Movetype_Physics_MatchTicrate(float tr, float sloppy) // SV_Physics_Entity { // now continue the move from move_time to time self.velocity = self.move_velocity; - if(self.move_didgravity) + + if(self.move_didgravity > 0) { - if(self.gravity) - self.velocity_z -= dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY); + if(GRAVITY_UNAFFECTED_BY_TICRATE) + { + if(self.gravity) + self.velocity_z -= 0.5 * dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY); + else + self.velocity_z -= 0.5 * dt * getstatf(STAT_MOVEVARS_GRAVITY); + } else - self.velocity_z -= dt * getstatf(STAT_MOVEVARS_GRAVITY); + { + if(self.gravity) + self.velocity_z -= dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY); + else + self.velocity_z -= dt * getstatf(STAT_MOVEVARS_GRAVITY); + } } self.angles = self.move_angles + dt * self.avelocity; @@ -435,6 +467,17 @@ void Movetype_Physics_MatchTicrate(float tr, float sloppy) // SV_Physics_Entity if(!trace_startsolid) setorigin(self, trace_endpos); } + + if(self.move_didgravity > 0) + { + if(GRAVITY_UNAFFECTED_BY_TICRATE) + { + if(self.gravity) + self.velocity_z -= 0.5 * dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY); + else + self.velocity_z -= 0.5 * dt * getstatf(STAT_MOVEVARS_GRAVITY); + } + } } else { diff --git a/qcsrc/client/movetypes.qh b/qcsrc/client/movetypes.qh index 3ec9a8f1d3..c6ab6543cb 100644 --- a/qcsrc/client/movetypes.qh +++ b/qcsrc/client/movetypes.qh @@ -28,6 +28,7 @@ float MOVETYPE_BOUNCE = 10; float MOVETYPE_BOUNCEMISSILE = 11; // Like bounce but doesn't lose speed on bouncing float MOVETYPE_FOLLOW = 12; float MOVETYPE_FAKEPUSH = 13; +float MOVETYPE_FLY_WORLDONLY = 33; float FL_ITEM = 256; float FL_ONGROUND = 512; diff --git a/qcsrc/client/particles.qc b/qcsrc/client/particles.qc index b33b81a018..6e24893b02 100644 --- a/qcsrc/client/particles.qc +++ b/qcsrc/client/particles.qc @@ -58,7 +58,7 @@ void Draw_PointParticles() if(self.noise != "") { self.origin = p; - sound(self, CHAN_TRIGGER, self.noise, VOL_BASE * self.volume, self.atten); + sound(self, CH_AMBIENT, self.noise, VOL_BASE * self.volume, self.atten); } self.just_toggled = 0; } @@ -191,12 +191,12 @@ void Ent_PointParticles() .float glow_color; // palette index void Draw_Rain() { - te_particlerain(self.origin + self.mins, self.origin + self.maxs, self.velocity, self.count * drawframetime, self.glow_color); + te_particlerain(self.origin + self.mins, self.origin + self.maxs, self.velocity, floor(self.count * drawframetime + random()), self.glow_color); } void Draw_Snow() { - te_particlesnow(self.origin + self.mins, self.origin + self.maxs, self.velocity, self.count * drawframetime, self.glow_color); + te_particlesnow(self.origin + self.mins, self.origin + self.maxs, self.velocity, floor(self.count * drawframetime + random()), self.glow_color); } void Ent_RainOrSnow() diff --git a/qcsrc/client/prandom.qc b/qcsrc/client/prandom.qc index 1fae8abe0d..1132d06a32 100644 --- a/qcsrc/client/prandom.qc +++ b/qcsrc/client/prandom.qc @@ -9,7 +9,7 @@ float prandom() prandom_seed = c; #ifdef USE_PRANDOM_DEBUG - print("RANDOM -> ", ftos(c), "\n"); + dprint("RANDOM -> ", ftos(c), "\n"); #endif return c / 65536; // in [0..1[ @@ -34,14 +34,14 @@ void psrandom(float seed) { prandom_seed = seed; #ifdef USE_PRANDOM_DEBUG - print("SRANDOM ", ftos(seed), "\n"); + dprint("SRANDOM ", ftos(seed), "\n"); #endif } #ifdef USE_PRANDOM_DEBUG void prandom_debug() { - print("Current random seed = ", ftos(prandom_seed), "\n"); + dprint("Current random seed = ", ftos(prandom_seed), "\n"); } #endif #endif diff --git a/qcsrc/client/pre.qh b/qcsrc/client/pre.qh deleted file mode 100644 index 5b117982d8..0000000000 --- a/qcsrc/client/pre.qh +++ /dev/null @@ -1,5 +0,0 @@ -#ifdef USE_FTE -#pragma target FTE -#endif - -#define CSQC 1 diff --git a/qcsrc/client/progs.src b/qcsrc/client/progs.src index 1334d7d3c7..a33570a2f9 100644 --- a/qcsrc/client/progs.src +++ b/qcsrc/client/progs.src @@ -1,11 +1,13 @@ ../../csprogs.dat -pre.qh ../common/util-pre.qh +sys-pre.qh +../dpdefs/csprogsdefs.qc +sys-post.qh + Defs.qc -csqc_constants.qc +../dpdefs/keycodes.qc ../common/constants.qh -csqc_builtins.qc ../warpzonelib/anglestransform.qh ../warpzonelib/mathlib.qh @@ -14,12 +16,18 @@ csqc_builtins.qc ../common/util.qh ../common/items.qh - +../common/explosion_equation.qh ../common/mapinfo.qh +../common/command/markup.qh +../common/command/rpn.qh +../common/command/generic.qh +../common/command/shared_defs.qh + +command/cl_cmd.qh autocvars.qh -interpolate.qh +../csqcmodellib/interpolate.qh teamradar.qh hud.qh scoreboard.qh @@ -28,19 +36,28 @@ movetypes.qh prandom.qh bgmscript.qh noise.qh - +teamplay.qh +tturrets.qh +../server/tturrets/include/turrets_early.qh +../server/movelib.qc main.qh +vehicles/vehicles.qh +../common/csqcmodel_settings.qh +../csqcmodellib/common.qh +../csqcmodellib/cl_model.qh +../csqcmodellib/cl_player.qh +projectile.qh sortlist.qc miscfunctions.qc teamplay.qc -ctf.qc - teamradar.qc +hud_config.qc hud.qc scoreboard.qc mapvoting.qc +csqcmodel_hooks.qc rubble.qc hook.qc @@ -50,16 +67,22 @@ projectile.qc gibs.qc damage.qc casings.qc +../csqcmodellib/cl_model.qc +../csqcmodellib/cl_player.qc effects.qc wall.qc modeleffects.qc tuba.qc target_music.qc -//vehicles/spiderbot.qc +vehicles/vehicles.qc +shownames.qh +shownames.qc + +announcer.qc Main.qc View.qc -interpolate.qc +../csqcmodellib/interpolate.qc waypointsprites.qc movetypes.qc prandom.qc @@ -67,12 +90,20 @@ bgmscript.qc noise.qc ../common/util.qc -../common/gamecommand.qc +../common/command/markup.qc +../common/command/rpn.qc +../common/command/generic.qc ../common/mapinfo.qc ../common/items.qc ../server/w_all.qc +../common/explosion_equation.qc + +command/cl_cmd.qc ../warpzonelib/anglestransform.qc ../warpzonelib/mathlib.qc ../warpzonelib/common.qc ../warpzonelib/client.qc +tturrets.qc + +../common/if-this-file-errors-scroll-up-and-fix-the-warnings.fteqccfail diff --git a/qcsrc/client/projectile.qc b/qcsrc/client/projectile.qc index a2cef76454..85d5aedcb5 100644 --- a/qcsrc/client/projectile.qc +++ b/qcsrc/client/projectile.qc @@ -20,17 +20,18 @@ void SUB_Stop() .float gravity; .float snd_looping; .float silent; -.float traileffect; void Projectile_ResetTrail(vector to) { self.trail_oldorigin = to; self.trail_oldtime = time; } + void Projectile_DrawTrail(vector to) { vector from; float t0; + from = self.trail_oldorigin; t0 = self.trail_oldtime; self.trail_oldorigin = to; @@ -73,7 +74,7 @@ void Projectile_Draw() Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy); if(!(self.move_flags & FL_ONGROUND)) if(self.velocity != '0 0 0') - self.angles = vectoangles(self.velocity); + self.move_angles = self.angles = vectoangles(self.velocity); } else { @@ -148,7 +149,7 @@ void Projectile_Draw() { case PROJECTILE_BULLET_GLOWING: case PROJECTILE_BULLET_GLOWING_TRACER: - R_AddDynamicLight(self.origin, 50 * a, '1 1 0'); + adddynamiclight(self.origin, 50 * a, '1 1 0'); break; default: break; @@ -169,7 +170,7 @@ void loopsound(entity e, float ch, string samp, float vol, float attn) void Ent_RemoveProjectile() { if(self.snd_looping) - sound(self, CHAN_PROJECTILE, "misc/null.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTN_NORM); if(self.count & 0x80) { @@ -195,7 +196,7 @@ void Ent_Projectile() // effects // // projectiles don't send angles, because they always follow the velocity - + f = ReadByte(); self.count = (f & 0x80); self.iflags = (self.iflags & IFLAG_INTERNALMASK) | IFLAG_AUTOANGLES | IFLAG_ANGLES; @@ -274,26 +275,34 @@ void Ent_Projectile() case PROJECTILE_ELECTRO: setmodel(self, "models/ebomb.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break; case PROJECTILE_ROCKET: setmodel(self, "models/rocket.md3");self.traileffect = particleeffectnum("TR_ROCKET"); self.scale = 2; break; case PROJECTILE_BULLET: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_bullet"); break; - case PROJECTILE_BULLET_GLOWING: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_bullet"); break; + case PROJECTILE_BULLET_GLOWING: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_rifle_weak"); break; case PROJECTILE_BULLET_GLOWING_TRACER: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_rifle"); break; case PROJECTILE_CRYLINK: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break; case PROJECTILE_CRYLINK_BOUNCING: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break; case PROJECTILE_ELECTRO_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break; case PROJECTILE_GRENADE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break; case PROJECTILE_GRENADE_BOUNCING: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break; - case PROJECTILE_MINE: setmodel(self, "models/mine.md3");self.traileffect = particleeffectnum(""); break; + case PROJECTILE_MINE: setmodel(self, "models/mine.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break; case PROJECTILE_LASER: setmodel(self, "models/laser.mdl");self.traileffect = particleeffectnum(""); break; case PROJECTILE_HLAC: setmodel(self, "models/hlac_bullet.md3");self.traileffect = particleeffectnum(""); break; case PROJECTILE_PORTO_RED: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_WIZSPIKE"); self.scale = 4; break; case PROJECTILE_PORTO_BLUE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_WIZSPIKE"); self.scale = 4; break; case PROJECTILE_HOOKBOMB: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_KNIGHTSPIKE"); break; - case PROJECTILE_HAGAR: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("TR_GRENADE"); self.scale = 0.4; break; - case PROJECTILE_HAGAR_BOUNCING: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("TR_GRENADE"); self.scale = 0.4; break; + case PROJECTILE_HAGAR: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("tr_hagar"); self.scale = 0.75; break; + case PROJECTILE_HAGAR_BOUNCING: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("tr_hagar"); self.scale = 0.75; break; case PROJECTILE_FIREBALL: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("fireball"); break; // particle effect is good enough case PROJECTILE_FIREMINE: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("firemine"); break; // particle effect is good enough case PROJECTILE_TAG: setmodel(self, "models/laser.mdl"); self.traileffect = particleeffectnum("TR_ROCKET"); break; - case PROJECTILE_FLAC: setmodel(self, "models/hagarmissile.mdl"); self.scale = 0.4; self.traileffect = particleeffectnum("TR_ROCKET"); break; - case PROJECTILE_SEEKER: setmodel(self, "models/tagrocket.md3"); self.scale = 2; self.traileffect = particleeffectnum("TR_ROCKET"); break; + case PROJECTILE_FLAC: setmodel(self, "models/hagarmissile.mdl"); self.scale = 0.4; self.traileffect = particleeffectnum("TR_SEEKER"); break; + case PROJECTILE_SEEKER: setmodel(self, "models/tagrocket.md3"); self.traileffect = particleeffectnum("TR_SEEKER"); break; + + case PROJECTILE_RAPTORBOMB: setmodel(self, "models/vehicles/clusterbomb.md3"); self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = particleeffectnum(""); break; + case PROJECTILE_RAPTORBOMBLET: setmodel(self, "models/vehicles/bomblet.md3"); self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = particleeffectnum(""); break; + case PROJECTILE_RAPTORCANNON: setmodel(self, "models/plasmatrail.mdl"); self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break; + + case PROJECTILE_SPIDERROCKET: setmodel(self, "models/vehicles/rocket02.md3"); self.traileffect = particleeffectnum("spiderbot_rocket_thrust"); break; + case PROJECTILE_WAKIROCKET: setmodel(self, "models/vehicles/rocket01.md3"); self.traileffect = particleeffectnum("wakizashi_rocket_thrust"); break; + case PROJECTILE_WAKICANNON: setmodel(self, "models/laser.mdl"); self.traileffect = particleeffectnum(""); break; default: error("Received invalid CSQC projectile, can't work with this!"); break; @@ -310,7 +319,7 @@ void Ent_Projectile() { case PROJECTILE_ELECTRO: // only new engines support sound moving with object - loopsound(self, CHAN_PROJECTILE, "weapons/electro_fly.wav", VOL_BASE, ATTN_NORM); + loopsound(self, CH_SHOTS_SINGLE, "weapons/electro_fly.wav", VOL_BASE, ATTN_NORM); self.mins = '0 0 -4'; self.maxs = '0 0 -4'; self.move_movetype = MOVETYPE_BOUNCE; @@ -319,7 +328,7 @@ void Ent_Projectile() self.move_bounce_stopspeed = g_balance_electro_secondary_bouncestop; break; case PROJECTILE_ROCKET: - loopsound(self, CHAN_PROJECTILE, "weapons/rocket_fly.wav", VOL_BASE, ATTN_NORM); + loopsound(self, CH_SHOTS_SINGLE, "weapons/rocket_fly.wav", VOL_BASE, ATTN_NORM); self.mins = '-3 -3 -3'; self.maxs = '3 3 3'; break; @@ -360,19 +369,18 @@ void Ent_Projectile() self.move_touch = SUB_Null; break; case PROJECTILE_FIREBALL: - loopsound(self, CHAN_PROJECTILE, "weapons/fireball_fly2.wav", VOL_BASE, ATTN_NORM); + loopsound(self, CH_SHOTS_SINGLE, "weapons/fireball_fly2.wav", VOL_BASE, ATTN_NORM); self.mins = '-16 -16 -16'; self.maxs = '16 16 16'; break; case PROJECTILE_FIREMINE: - loopsound(self, CHAN_PROJECTILE, "weapons/fireball_fly.wav", VOL_BASE, ATTN_NORM); + loopsound(self, CH_SHOTS_SINGLE, "weapons/fireball_fly.wav", VOL_BASE, ATTN_NORM); self.move_movetype = MOVETYPE_BOUNCE; self.move_touch = SUB_Null; self.mins = '-4 -4 -4'; self.maxs = '4 4 4'; break; case PROJECTILE_TAG: - loopsound(self, CHAN_PROJECTILE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTN_NORM); self.mins = '-2 -2 -2'; self.maxs = '2 2 2'; break; @@ -381,9 +389,26 @@ void Ent_Projectile() self.maxs = '2 2 2'; break; case PROJECTILE_SEEKER: + loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTN_NORM); self.mins = '-4 -4 -4'; self.maxs = '4 4 4'; break; + case PROJECTILE_RAPTORBOMB: + self.mins = '-3 -3 -3'; + self.maxs = '3 3 3'; + break; + case PROJECTILE_RAPTORBOMBLET: + break; + case PROJECTILE_RAPTORCANNON: + break; + case PROJECTILE_SPIDERROCKET: + loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTN_NORM); + break; + case PROJECTILE_WAKIROCKET: + loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTN_NORM); + break; + case PROJECTILE_WAKICANNON: + break; default: break; } @@ -406,7 +431,7 @@ void Ent_Projectile() if(!(self.count & 0x80)) InterpolateOrigin_Note(); - + self.draw = Projectile_Draw; self.entremove = Ent_RemoveProjectile; } @@ -424,9 +449,11 @@ void Projectile_Precache() precache_model("models/rocket.md3"); precache_model("models/tagrocket.md3"); precache_model("models/tracer.mdl"); + precache_sound("weapons/electro_fly.wav"); precache_sound("weapons/rocket_fly.wav"); precache_sound("weapons/fireball_fly.wav"); precache_sound("weapons/fireball_fly2.wav"); precache_sound("weapons/tag_rocket_fly.wav"); + } diff --git a/qcsrc/client/projectile.qh b/qcsrc/client/projectile.qh new file mode 100644 index 0000000000..70c8ba0dfc --- /dev/null +++ b/qcsrc/client/projectile.qh @@ -0,0 +1,3 @@ +.float traileffect; +void Projectile_ResetTrail(vector to); +void Projectile_DrawTrail(vector to); diff --git a/qcsrc/client/scoreboard.qc b/qcsrc/client/scoreboard.qc index 31cdc45bfa..05c8df88cf 100644 --- a/qcsrc/client/scoreboard.qc +++ b/qcsrc/client/scoreboard.qc @@ -11,6 +11,47 @@ void drawstringcenter(vector, string, vector, vector, float, float); float SCOREBOARD_OFFSET = 50; +// wrapper to put all possible scores titles through gettext +string TranslateScoresLabel(string l) +{ + switch(l) + { + case "bckills": return CTX(_("SCO^bckills")); + case "bctime": return CTX(_("SCO^bctime")); + case "caps": return CTX(_("SCO^caps")); + case "deaths": return CTX(_("SCO^deaths")); + case "destroyed": return CTX(_("SCO^destroyed")); + case "drops": return CTX(_("SCO^drops")); + case "faults": return CTX(_("SCO^faults")); + case "fckills": return CTX(_("SCO^fckills")); + case "goals": return CTX(_("SCO^goals")); + case "kckills": return CTX(_("SCO^kckills")); + case "kdratio": return CTX(_("SCO^kdratio")); + case "k/d": return CTX(_("SCO^k/d")); + case "kd": return CTX(_("SCO^kd")); + case "kdr": return CTX(_("SCO^kdr")); + case "kills": return CTX(_("SCO^kills")); + case "laps": return CTX(_("SCO^laps")); + case "lives": return CTX(_("SCO^lives")); + case "losses": return CTX(_("SCO^losses")); + case "name": return CTX(_("SCO^name")); + case "nick": return CTX(_("SCO^nick")); + case "objectives": return CTX(_("SCO^objectives")); + case "pickups": return CTX(_("SCO^pickups")); + case "ping": return CTX(_("SCO^ping")); + case "pl": return CTX(_("SCO^pl")); + case "pushes": return CTX(_("SCO^pushes")); + case "rank": return CTX(_("SCO^rank")); + case "returns": return CTX(_("SCO^returns")); + case "revivals": return CTX(_("SCO^revivals")); + case "score": return CTX(_("SCO^score")); + case "suicides": return CTX(_("SCO^suicides")); + case "takes": return CTX(_("SCO^takes")); + case "ticks": return CTX(_("SCO^ticks")); + default: return l; + } +} + void MapVote_Draw(); void HUD_FinaleOverlay() { @@ -193,67 +234,69 @@ void HUD_UpdateTeamPos(entity Team) } } -void Cmd_HUD_Help(float argc) +void Cmd_HUD_Help() { - print("You can modify the scoreboard using the ^2scoreboard_columns_set command.\n"); - print("^3|---------------------------------------------------------------|\n"); - print("Usage:\n"); - print("^2scoreboard_columns_set default\n"); - print("^2scoreboard_columns_set ^7filed1 field2 ...\n"); - print("The following field names are recognized (case insensitive):\n"); - print("You can use a ^3|^7 to start the right-aligned fields.\n\n"); - - print("^3name^7 or ^3nick^7 Name of a player\n"); - print("^3ping^7 Ping time\n"); - print("^3pl^7 Packet loss\n"); - print("^3kills^7 Number of kills\n"); - print("^3deaths^7 Number of deaths\n"); - print("^3suicides^7 Number of suicides\n"); - print("^3frags^7 kills - suicides\n"); - print("^3kd^7 The kill-death ratio\n"); - print("^3caps^7 How often a flag (CTF) or a key (KeyHunt) was captured\n"); - print("^3pickups^7 How often a flag (CTF) or a key (KeyHunt) was picked up\n"); - print("^3fckills^7 Number of flag carrier kills\n"); - print("^3returns^7 Number of flag returns\n"); - print("^3drops^7 Number of flag drops\n"); - print("^3lives^7 Number of lives (LMS)\n"); - print("^3rank^7 Player rank\n"); - print("^3pushes^7 Number of players pushed into void\n"); - print("^3destroyed^7 Number of keys destroyed by pushing them into void\n"); - print("^3kckills^7 Number of keys carrier kills\n"); - print("^3losses^7 Number of times a key was lost\n"); - print("^3laps^7 Number of laps finished (race/cts)\n"); - print("^3time^7 Total time raced (race/cts)\n"); - print("^3fastest^7 Time of fastest lap (race/cts)\n"); - print("^3ticks^7 Number of ticks (DOM)\n"); - print("^3takes^7 Number of domination points taken (DOM)\n"); - print("^3score^7 Total score\n\n"); - - print("Before a field you can put a + or - sign, then a comma separated list\n"); - print("of game types, then a slash, to make the field show up only in these\n"); - print("or in all but these game types. You can also specify 'all' as a\n"); - print("field to show all fields available for the current game mode.\n\n"); - - print("The special game type names 'teams' and 'noteams' can be used to\n"); - print("include/exclude ALL teams/noteams game modes.\n\n"); - - print("Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4\n"); - print("will display name, ping and pl aligned to the left, and the fields\n"); - print("right of the vertical bar aligned to the right.\n"); - print("'field3' will only be shown in CTF, and 'field4' will be shown in all\n"); - print("other gamemodes except DM.\n"); + print(_("You can modify the scoreboard using the ^2scoreboard_columns_set command.\n")); + print(_("^3|---------------------------------------------------------------|\n")); + print(_("Usage:\n")); + print(_("^2scoreboard_columns_set default\n")); + print(_("^2scoreboard_columns_set ^7field1 field2 ...\n")); + print(_("The following field names are recognized (case insensitive):\n")); + print(_("You can use a ^3|^7 to start the right-aligned fields.\n\n")); + + print(_("^3name^7 or ^3nick^7 Name of a player\n")); + print(_("^3ping^7 Ping time\n")); + print(_("^3pl^7 Packet loss\n")); + print(_("^3kills^7 Number of kills\n")); + print(_("^3deaths^7 Number of deaths\n")); + print(_("^3suicides^7 Number of suicides\n")); + print(_("^3frags^7 kills - suicides\n")); + print(_("^3kd^7 The kill-death ratio\n")); + print(_("^3caps^7 How often a flag (CTF) or a key (KeyHunt) was captured\n")); + print(_("^3pickups^7 How often a flag (CTF) or a key (KeyHunt) or a ball (Keepaway) was picked up\n")); + print(_("^3fckills^7 Number of flag carrier kills\n")); + print(_("^3returns^7 Number of flag returns\n")); + print(_("^3drops^7 Number of flag drops\n")); + print(_("^3lives^7 Number of lives (LMS)\n")); + print(_("^3rank^7 Player rank\n")); + print(_("^3pushes^7 Number of players pushed into void\n")); + print(_("^3destroyed^7 Number of keys destroyed by pushing them into void\n")); + print(_("^3kckills^7 Number of keys carrier kills\n")); + print(_("^3losses^7 Number of times a key was lost\n")); + print(_("^3laps^7 Number of laps finished (race/cts)\n")); + print(_("^3time^7 Total time raced (race/cts)\n")); + print(_("^3fastest^7 Time of fastest lap (race/cts)\n")); + print(_("^3ticks^7 Number of ticks (DOM)\n")); + print(_("^3takes^7 Number of domination points taken (DOM)\n")); + print(_("^3bckills^7 Number of ball carrier kills\n")); + print(_("^3bctime^7 Total amount of time holding the ball in Keepaway\n")); + print(_("^3score^7 Total score\n\n")); + + print(_("Before a field you can put a + or - sign, then a comma separated list\n" + "of game types, then a slash, to make the field show up only in these\n" + "or in all but these game types. You can also specify 'all' as a\n" + "field to show all fields available for the current game mode.\n\n")); + + print(_("The special game type names 'teams' and 'noteams' can be used to\n" + "include/exclude ALL teams/noteams game modes.\n\n")); + + print(_("Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4\n")); + print(_("will display name, ping and pl aligned to the left, and the fields\n" + "right of the vertical bar aligned to the right.\n")); + print(_("'field3' will only be shown in CTF, and 'field4' will be shown in all\n" + "other gamemodes except DM.\n")); } string HUD_DefaultColumnLayout() { return strcat( // fteqcc sucks "ping pl name | ", - "-teams,race,lms/kills -teams,lms/deaths -teams,lms,race,ka/suicides -race,dm,tdm,ka/frags ", // tdm already has this in "score" + "-teams,race,lms/kills +freezetag/kills -teams,lms/deaths +freezetag/deaths -teams,lms,race,ka/suicides +freezetag/suicides -race,dm,tdm,ka,freezetag/frags ", // tdm already has this in "score" "+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns ", "+lms/lives +lms/rank ", "+kh/caps +kh/pushes +kh/destroyed ", "?+race/laps ?+race/time ?+race/fastest ", - "+as/objectives +nexball/faults +nexball/goals +ka/drops +ka/pickups +ka/bckills ", + "+as/objectives +nexball/faults +nexball/goals +ka/pickups +ka/bckills +ka/bctime +freezetag/revivals ", "-lms,race,nexball/score"); } @@ -265,17 +308,17 @@ void Cmd_HUD_SetFields(float argc) float missing; // TODO: re enable with gametype dependant cvars? - if(argc < 2) // no arguments provided + if(argc < 3) // no arguments provided argc = tokenizebyseparator(strcat("x ", autocvar_scoreboard_columns), " "); - if(argc < 2) + if(argc < 3) argc = tokenizebyseparator(strcat("x ", HUD_DefaultColumnLayout()), " "); - if(argc == 2) + if(argc == 3) { - if(argv(1) == "default") + if(argv(2) == "default") argc = tokenizebyseparator(strcat("x ", HUD_DefaultColumnLayout()), " "); - else if(argv(1) == "all") + else if(argv(2) == "all") { string s; s = "ping pl color name |"; @@ -296,7 +339,6 @@ void Cmd_HUD_SetFields(float argc) hud_num_fields = 0; - drawfont = hud_font; hud_fontsize = HUD_GetFontsize("hud_fontsize"); for(i = 0; i < argc - 1; ++i) @@ -317,13 +359,13 @@ void Cmd_HUD_SetFields(float argc) pattern = substring(str, 0, slash); str = substring(str, slash + 1, strlen(str) - (slash + 1)); - if not(isGametypeInFilter(gametype, teamplay, pattern)) + if not(isGametypeInFilter(gametype, teamplay, FALSE, pattern)) continue; } strunzone(hud_title[hud_num_fields]); - hud_title[hud_num_fields] = strzone(str); - hud_size[hud_num_fields] = stringwidth(str, FALSE, hud_fontsize); + hud_title[hud_num_fields] = strzone(TranslateScoresLabel(str)); + hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize); str = strtolower(str); if(str == "ping") { @@ -350,7 +392,7 @@ void Cmd_HUD_SetFields(float argc) else { if not(nocomplain) - print(strcat("^1Error:^7 Unknown score field: '", str, "'\n")); + print(sprintf("^1Error:^7 Unknown score field: '%s'\n", str)); continue; } :found @@ -384,10 +426,10 @@ void Cmd_HUD_SetFields(float argc) hud_size[i] = hud_size[i-1]; hud_field[i] = hud_field[i-1]; } - hud_title[0] = strzone("name"); + hud_title[0] = strzone(TranslateScoresLabel("name")); hud_field[0] = SP_NAME; ++hud_num_fields; - print("fixed missing field 'name'\n"); + print(sprintf(_("fixed missing field '%s'\n"), "name")); if(!have_separator) { @@ -402,7 +444,7 @@ void Cmd_HUD_SetFields(float argc) hud_field[1] = SP_SEPARATOR; hud_size[1] = stringwidth("|", FALSE, hud_fontsize); ++hud_num_fields; - print("fixed missing field '|'\n"); + print(sprintf(_("fixed missing field '%s'\n"), "|")); } } else if(!have_separator) @@ -412,25 +454,25 @@ void Cmd_HUD_SetFields(float argc) hud_size[hud_num_fields] = stringwidth("|", FALSE, hud_fontsize); hud_field[hud_num_fields] = SP_SEPARATOR; ++hud_num_fields; - print("fixed missing field '|'\n"); + print(sprintf(_("fixed missing field '%s'\n"), "|")); } if(!have_secondary) { strunzone(hud_title[hud_num_fields]); - hud_title[hud_num_fields] = strzone(scores_label[ps_secondary]); + hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_secondary])); hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize); hud_field[hud_num_fields] = ps_secondary; ++hud_num_fields; - print("fixed missing field '", scores_label[ps_secondary], "'\n"); + print(sprintf(_("fixed missing field '%s'\n"), scores_label[ps_secondary])); } if(!have_primary) { strunzone(hud_title[hud_num_fields]); - hud_title[hud_num_fields] = strzone(scores_label[ps_primary]); + hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_primary])); hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize); hud_field[hud_num_fields] = ps_primary; ++hud_num_fields; - print("fixed missing field '", scores_label[ps_primary], "'\n"); + print(sprintf(_("fixed missing field '%s'\n"), scores_label[ps_primary])); } } @@ -466,18 +508,18 @@ string HUD_GetField(entity pl, float field) { case SP_PING: if not(pl.gotscores) - return "\x8D\x8D\x8D"; // >>> sign - //str = getplayerkey(pl.sv_entnum, "ping"); + return "\xEE\x82\x8D\xEE\x82\x8D\xEE\x82\x8D"; // >>> sign + //str = getplayerkeyvalue(pl.sv_entnum, "ping"); f = pl.ping; if(f == 0) - return "N/A"; + return _("N/A"); tmp = max(0, min(220, f-80)) / 220; hud_field_rgb = '1 1 1' - '0 1 1'*tmp; return ftos(f); case SP_PL: if not(pl.gotscores) - return "N/A"; + return _("N/A"); f = pl.ping_packetloss; tmp = pl.ping_movementloss; if(f == 0 && tmp == 0) @@ -496,7 +538,7 @@ string HUD_GetField(entity pl, float field) } else if(!teamplay) { - f = stof(getplayerkey(pl.sv_entnum, "colors")); + f = stof(getplayerkeyvalue(pl.sv_entnum, "colors")); { hud_field_icon0 = "gfx/scoreboard/playercolor_base"; hud_field_icon1 = "gfx/scoreboard/playercolor_shirt"; @@ -518,16 +560,12 @@ string HUD_GetField(entity pl, float field) if(denom == 0) { hud_field_rgb = '0 1 0'; - str = ftos(num); + str = sprintf("%d", num); } else if(num <= 0) { hud_field_rgb = '1 0 0'; - str = ftos(num/denom); + str = sprintf("%.1f", num/denom); } else - str = ftos(num/denom); - - tmp = strstrofs(str, ".", 0); - if(tmp > 0) - str = substring(str, 0, tmp+2); + str = sprintf("%.1f", num/denom); return str; default: @@ -559,7 +597,7 @@ string HUD_FixScoreboardColumnWidth(float i, string str) if(hud_field_icon0 != "") { - sz = drawgetimagesize(hud_field_icon0); + sz = draw_getimagesize(hud_field_icon0); f = sz_x / sz_y; if(hud_fixscoreboardcolumnwidth_iconlen < f) hud_fixscoreboardcolumnwidth_iconlen = f; @@ -567,7 +605,7 @@ string HUD_FixScoreboardColumnWidth(float i, string str) if(hud_field_icon1 != "") { - sz = drawgetimagesize(hud_field_icon1); + sz = draw_getimagesize(hud_field_icon1); f = sz_x / sz_y; if(hud_fixscoreboardcolumnwidth_iconlen < f) hud_fixscoreboardcolumnwidth_iconlen = f; @@ -575,7 +613,7 @@ string HUD_FixScoreboardColumnWidth(float i, string str) if(hud_field_icon2 != "") { - sz = drawgetimagesize(hud_field_icon2); + sz = draw_getimagesize(hud_field_icon2); f = sz_x / sz_y; if(hud_fixscoreboardcolumnwidth_iconlen < f) hud_fixscoreboardcolumnwidth_iconlen = f; @@ -754,6 +792,7 @@ vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_siz body_table_height = 1.25 * hud_fontsize_y * max(1, tm.team_size); // no player? show 1 empty line + pos_y += autocvar_scoreboard_border_thickness; pos -= '1 1 0'; tmp_x = sbwidth + 2; @@ -855,7 +894,7 @@ vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_siz { if(pl.team != tm.team) continue; - HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localentnum - 1), i); + HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i); pos_y += 1.25 * hud_fontsize_y; ++i; } @@ -864,7 +903,7 @@ vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_siz { if(pl.team == COLOR_SPECTATOR) continue; - HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localentnum - 1), i); + HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i); pos_y += 1.25 * hud_fontsize_y; ++i; } @@ -883,10 +922,10 @@ float HUD_WouldDrawScoreboard() { return 1; else if (intermission == 1) return 1; - else if (getstati(STAT_HEALTH) <= 0 && autocvar_cl_deathscoreboard && gametype != GAME_CTS) + else if (intermission == 2) + return 0; + else if (spectatee_status != -1 && getstati(STAT_HEALTH) <= 0 && autocvar_cl_deathscoreboard && gametype != MAPINFO_TYPE_CTS) return 1; - else if (spectatee_status == -1) - return 1; else if (scoreboard_showscores_force) return 1; return 0; @@ -908,8 +947,8 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size) float weapon_height = height * 2/3; float weapon_width = sbwidth / weapon_cnt; - drawstring(pos, strcat("Accuracy stats (average ", ftos(average_accuracy), "%)"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL); - pos_y += 1.25 * hud_fontsize_y; + drawstring(pos, sprintf(_("Accuracy stats (average %d%%)"), average_accuracy), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL); + pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness; vector tmp; tmp_x = sbwidth; tmp_y = height * rows; @@ -933,17 +972,16 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size) drawfill(pos + '0 1 0' * weapon_height + '0 1 0' * height * i, '1 0 0' * sbwidth + '0 1 0' * fontsize, '1 1 1', scoreboard_highlight_alpha, DRAWFLAG_NORMAL); } - drawfont = hud_bigfont; average_accuracy = 0; float weapons_with_stats; weapons_with_stats = 0; if(rows == 2) pos_x += weapon_width / 2; - if(getstati(STAT_SWITCHWEAPON) == WEP_MINSTANEX) + if(switchweapon == WEP_MINSTANEX) g_minstagib = 1; // TODO: real detection for minstagib? - float weapon_stats, weapon_number; + float weapon_stats; if (!acc_levels) rgb = '1 1 1'; @@ -974,7 +1012,7 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size) average_accuracy += weapon_stats; // store sum of all accuracies in average_accuracy string s; - s = sprintf("%d%%", weapon_stats*100); + s = sprintf(_("%d%%"), weapon_stats*100); float padding; padding = (weapon_width - stringwidth(s, FALSE, '1 0 0' * fontsize)) / 2; // center the accuracy value @@ -1002,7 +1040,6 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size) pos_y += height; } } - drawfont = hud_font; if(weapons_with_stats) average_accuracy = floor(average_accuracy / weapons_with_stats); @@ -1016,6 +1053,59 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size) return pos; } +vector HUD_DrawKeyValue(vector pos, string key, string value) { + float px = pos_x; + pos_x += hud_fontsize_x * 0.25; + drawstring(pos, key, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL); + pos_x = xmax - stringwidth(value, FALSE, hud_fontsize) - hud_fontsize_x * 0.25; + drawstring(pos, value, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL); + pos_x = px; + pos_y+= hud_fontsize_y; + + return pos; +} + +vector HUD_DrawMapStats(vector pos, vector rgb, vector bg_size) { + float stat_secrets_found, stat_secrets_total; + float rows; + string val; + + // get secrets stats + stat_secrets_found = getstatf(STAT_SECRETS_FOUND); + stat_secrets_total = getstatf(STAT_SECRETS_TOTAL); + + // get number of rows + rows = (stat_secrets_total ? 1 : 0); + + // if no rows, return + if not(rows) + return pos; + + // draw table header + drawstring(pos, _("Map stats:"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL); + pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness; + + // draw table + vector tmp; + tmp_x = sbwidth; + tmp_y = hud_fontsize_y * rows; + + if (teamplay) + drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL); + else + drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL); + drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL); + + // draw secrets + val = sprintf("%d/%d", stat_secrets_found, stat_secrets_total); + pos = HUD_DrawKeyValue(pos, _("Secrets found:"), val); + + // update position + pos_y += 1.25 * hud_fontsize_y; + return pos; +} + + vector HUD_DrawScoreboardRankings(vector pos, entity pl, vector rgb, vector bg_size) { float i; @@ -1035,8 +1125,8 @@ vector HUD_DrawScoreboardRankings(vector pos, entity pl, vector rgb, vector bg_ hl_rgb_z = autocvar_scoreboard_color_bg_b + 0.5; pos_y += hud_fontsize_y; - drawstring(pos, strcat("Rankings"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL); - pos_y += hud_fontsize_y; + drawstring(pos, _("Rankings"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL); + pos_y += hud_fontsize_y + autocvar_scoreboard_border_thickness; vector tmp; tmp_x = sbwidth; tmp_y = 1.25 * hud_fontsize_y * RANKINGS_RECEIVED_CNT; @@ -1057,7 +1147,7 @@ vector HUD_DrawScoreboardRankings(vector pos, entity pl, vector rgb, vector bg_ continue; n = grecordholder[i]; p = race_PlaceName(i+1); - if(grecordholder[i] == GetPlayerName(player_localentnum - 1)) + if(grecordholder[i] == GetPlayerName(player_localnum)) drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL); else if(!mod(i, 2) && scoreboard_highlight) drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL); @@ -1066,6 +1156,7 @@ vector HUD_DrawScoreboardRankings(vector pos, entity pl, vector rgb, vector bg_ drawcolorcodedstring(pos + '8 0 0' * hud_fontsize_y, n, '1 1 0' * hud_fontsize_y, scoreboard_alpha_fg, DRAWFLAG_NORMAL); pos_y += 1.25 * hud_fontsize_y; } + pos_y += autocvar_scoreboard_border_thickness; return pos; } @@ -1111,12 +1202,13 @@ void HUD_DrawScoreboard() vector rgb, pos, tmp; entity pl, tm; + string str; - xmin = autocvar_scoreboard_offset_left * vid_conwidth; - ymin = autocvar_con_notify * autocvar_con_notifysize; + xmin = (autocvar_scoreboard_offset_left * vid_conwidth); + ymin = max((autocvar_con_notify * autocvar_con_notifysize), (autocvar_scoreboard_offset_vertical * vid_conwidth)); - xmax = (1 - autocvar_scoreboard_offset_right) * vid_conwidth; - ymax = vid_conheight - ymin; + xmax = ((1 - autocvar_scoreboard_offset_right) * vid_conwidth); + ymax = (vid_conheight - ymin); sbwidth = xmax - xmin; @@ -1126,32 +1218,33 @@ void HUD_DrawScoreboard() pos_z = 0; // Heading - drawfont = hud_bigfont; - drawstring(pos, "Scoreboard", '24 24 0', '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL); - - centerprint_start_x = vid_conwidth - 0.5 * (pos_x + stringwidth("Scoreboard", FALSE, '24 24 0')); - centerprint_start_y = pos_y; + vector sb_heading_fontsize; + sb_heading_fontsize = hud_fontsize * 2; + drawstring(pos, _("Scoreboard"), sb_heading_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL); - pos_y += 24; - - drawfont = hud_font; + pos_y += sb_heading_fontsize_y + hud_fontsize_y * 0.25; // Draw the scoreboard - vector bg_size = drawgetimagesize("gfx/scoreboard/scoreboard_bg") * autocvar_scoreboard_bg_scale; + vector bg_size = draw_getimagesize("gfx/scoreboard/scoreboard_bg") * autocvar_scoreboard_bg_scale; if(teamplay) { + vector team_score_baseoffset; + team_score_baseoffset = eY * (2 * autocvar_scoreboard_border_thickness + hud_fontsize_y) - eX * (autocvar_scoreboard_border_thickness + hud_fontsize_x * 0.25); for(tm = teams.sort_next; tm; tm = tm.sort_next) { if(tm.team == COLOR_SPECTATOR) continue; rgb = GetTeamRGB(tm.team); - drawstring(pos - '2 0 0' * hud_fontsize_x + '0 1 0' * hud_fontsize_y, ftos(tm.(teamscores[ts_primary])), '1 1 0' * hud_fontsize_y * 1.5, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL); + str = ftos(tm.(teamscores[ts_primary])); + drawstring(pos + team_score_baseoffset - eX * stringwidth(str, FALSE, hud_fontsize * 1.5), str, hud_fontsize * 1.5, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL); if(ts_primary != ts_secondary) - drawstring(pos - '2 0 0' * hud_fontsize_x + '0 2.5 0' * hud_fontsize_y, ftos(tm.(teamscores[ts_secondary])), '1 1 0' * hud_fontsize_y * 1, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL); - + { + str = ftos(tm.(teamscores[ts_secondary])); + drawstring(pos + team_score_baseoffset - eX * stringwidth(str, FALSE, hud_fontsize) + eY * hud_fontsize_y * 1.5, str, hud_fontsize, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL); + } pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size); } } @@ -1170,13 +1263,13 @@ void HUD_DrawScoreboard() } } - if(gametype == GAME_CTS || gametype == GAME_RACE) { + if(gametype == MAPINFO_TYPE_CTS || gametype == MAPINFO_TYPE_RACE) { if(race_speedaward) { - drawcolorcodedstring(pos, strcat("Speed award: ", ftos(race_speedaward), " ^7(", race_speedaward_holder, "^7)"), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL); + drawcolorcodedstring(pos, sprintf(_("Speed award: %d ^7(%s^7)"), race_speedaward, race_speedaward_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL); pos_y += 1.25 * hud_fontsize_y; } if(race_speedaward_alltimebest) { - drawcolorcodedstring(pos, strcat("All-time fastest: ", ftos(race_speedaward_alltimebest), " ^7(", race_speedaward_alltimebest_holder, "^7)"), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL); + drawcolorcodedstring(pos, sprintf(_("All-time fastest: %d ^7(%s^7)"), race_speedaward_alltimebest, race_speedaward_alltimebest_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL); pos_y += 1.25 * hud_fontsize_y; } pos = HUD_DrawScoreboardRankings(pos, pl, rgb, bg_size); @@ -1188,6 +1281,12 @@ void HUD_DrawScoreboard() pos = HUD_DrawScoreboardAccuracyStats(pos, rgb, bg_size); } + + if(teamplay) + pos = HUD_DrawMapStats(pos, GetTeamRGB(myteam), bg_size); + else + pos = HUD_DrawMapStats(pos, rgb, bg_size); + // List spectators float specs; specs = 0; @@ -1197,80 +1296,67 @@ void HUD_DrawScoreboard() if(pl.team != COLOR_SPECTATOR) continue; pos_y += 1.25 * hud_fontsize_y; - HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localentnum - 1), specs); + HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), specs); ++specs; } if(specs) { - drawstring(tmp, "Spectators", hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL); + drawstring(tmp, _("Spectators"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL); pos_y += 1.25 * hud_fontsize_y; } // Print info string - string str; float tl, fl, ll; - str = strcat("playing on ^2", shortmapname, "^7"); + str = sprintf(_("playing on ^2%s^7"), shortmapname); tl = getstatf(STAT_TIMELIMIT); fl = getstatf(STAT_FRAGLIMIT); ll = getstatf(STAT_LEADLIMIT); - if(gametype == GAME_LMS) + if(gametype == MAPINFO_TYPE_LMS) { if(tl > 0) - str = strcat(str, " for up to ^1", ftos(tl), " minutes^7"); + str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl)); } else { if(tl > 0) - str = strcat(str, " for ^1", ftos(tl), " minutes^7"); + str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl)); if(fl > 0) { if(tl > 0) - str = strcat(str, " or"); + str = strcat(str, _(" or")); if(teamplay) { - str = strcat(str, " until ^3", ScoreString(teamscores_flags[ts_primary], fl)); - if(teamscores_label[ts_primary] == "score") - str = strcat(str, " points^7"); - else if(teamscores_label[ts_primary] == "fastest") - str = strcat(str, " is beaten^7"); - else - str = strcat(str, " ", teamscores_label[ts_primary]); + str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], fl), + (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) : + (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) : + TranslateScoresLabel(teamscores_label[ts_primary]))); } else { - str = strcat(str, " until ^3", ScoreString(scores_flags[ps_primary], fl)); - if(scores_label[ps_primary] == "score") - str = strcat(str, " points^7"); - else if(scores_label[ps_primary] == "fastest") - str = strcat(str, " is beaten^7"); - else - str = strcat(str, " ", scores_label[ps_primary]); + str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(scores_flags[ps_primary], fl), + (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) : + (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) : + TranslateScoresLabel(scores_label[ps_primary]))); } } if(ll > 0) { if(tl > 0 || fl > 0) - str = strcat(str, " or"); + str = strcat(str, _(" or")); if(teamplay) { - str = strcat(str, " until a lead of ^3", ScoreString(teamscores_flags[ts_primary], ll)); - if(teamscores_label[ts_primary] == "score") - str = strcat(str, " points^7"); - else if(teamscores_label[ts_primary] == "fastest") - str = strcat(str, " is beaten^7"); - else - str = strcat(str, " ", teamscores_label[ts_primary]); + str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], ll), + (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) : + (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) : + TranslateScoresLabel(teamscores_label[ts_primary]))); } else { - str = strcat(str, " until a lead of ^3", ScoreString(scores_flags[ps_primary], ll)); - if(scores_label[ps_primary] == "score") - str = strcat(str, " points^7"); - else if(scores_label[ps_primary] == "fastest") - str = strcat(str, " is beaten^7"); - else - str = strcat(str, " ", scores_label[ps_primary]); + str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(scores_flags[ps_primary], ll), + (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) : + (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) : + TranslateScoresLabel(scores_label[ps_primary]))); } } } diff --git a/qcsrc/client/shownames.qc b/qcsrc/client/shownames.qc new file mode 100644 index 0000000000..d5e24888d3 --- /dev/null +++ b/qcsrc/client/shownames.qc @@ -0,0 +1,223 @@ +// self.isactive = player is in range and coordinates/status (health and armor) are up to date +// self.origin = player origin TODO: should maybe move this so it's the origin of the shownames tag already in SSQC for culling? +// self.healthvalue +// self.armorvalue +// self.sameteam = player is on same team as local client +// self.fadedelay = time to wait before name tag starts fading in for enemies +// self.pointtime = last time you pointed at this player +// +const float SHOWNAMES_FADESPEED = 4; +const float SHOWNAMES_FADEDELAY = 0.4; +void Draw_ShowNames(entity ent) +{ + if(!autocvar_hud_shownames) + return; + +#ifdef COMPAT_XON050_ENGINE + if((ent.sv_entnum == player_localentnum) || (ent.sv_entnum == spectatee_status)) // ent is me or person i'm spectating +#else + if(ent.sv_entnum == player_localentnum) // ent is me or person i'm spectating +#endif + if not (autocvar_hud_shownames_self && autocvar_chase_active) + return; + + makevectors(view_angles); + + if(ent.sameteam || (!ent.sameteam && autocvar_hud_shownames_enemies)) + { + ent.origin_z += autocvar_hud_shownames_offset; + + float hit; + if(ent.sameteam && !autocvar_hud_shownames_crosshairdistance) + { + hit = 1; + } + else + { + traceline(view_origin, ent.origin, MOVE_NORMAL, ent); + if(trace_fraction < 1 && trace_networkentity != ent.sv_entnum) + hit = 0; + else + hit = 1; + } + + // handle tag fading + float overlap, onscreen, crosshairdistance; + vector o, eo; + + o = project_3d_to_2d(ent.origin); + + if(autocvar_hud_shownames_antioverlap) + { + // fade tag out if another tag that is closer to you overlaps + entity e; + for(e = world; (e = find(e, classname, "shownames_tag")); ) + { + if(e == ent) + continue; + eo = project_3d_to_2d(e.origin); + if not(eo_z < 0 || eo_x < 0 || eo_y < 0 || eo_x > vid_conwidth || eo_y > vid_conheight) + { + eo_z = 0; + if(vlen((eX * o_x + eY * o_y) - eo) < autocvar_hud_shownames_antioverlap_distance && vlen(ent.origin - view_origin) > vlen(e.origin - view_origin)) + { + overlap = TRUE; + break; + } + } + } + } + + onscreen = (o_z >= 0 && o_x >= 0 && o_y >= 0 && o_x <= vid_conwidth && o_y <= vid_conheight); + crosshairdistance = sqrt( pow(o_x - vid_conwidth/2, 2) + pow(o_y - vid_conheight/2, 2) ); + + if(autocvar_hud_shownames_crosshairdistance) + { + if(autocvar_hud_shownames_crosshairdistance > crosshairdistance) + ent.pointtime = time; + + if not(ent.pointtime + autocvar_hud_shownames_crosshairdistance_time > time) + overlap = TRUE; + else + overlap = (autocvar_hud_shownames_crosshairdistance_antioverlap ? overlap : FALSE); // override what antioverlap says unless allowed by cvar. + } + + if(!ent.fadedelay) + ent.fadedelay = time + SHOWNAMES_FADEDELAY; + + if(!ent.sameteam && (!onscreen || !hit)) // out of view, fade out + { + ent.alpha = max(0, ent.alpha - SHOWNAMES_FADESPEED * frametime); + ent.fadedelay = 0; // reset fade in delay, enemy has left the view + } + else if(ent.healthvalue < 1) // dead player, fade out slowly + ent.alpha = max(0, ent.alpha - SHOWNAMES_FADESPEED * 0.25 * frametime); + else if(overlap) // tag overlap detected, fade out + ent.alpha = max(0, ent.alpha - SHOWNAMES_FADESPEED * frametime); + else if(ent.sameteam) // fade in for team mates + ent.alpha = min(1, ent.alpha + SHOWNAMES_FADESPEED * frametime); + else if(time > ent.fadedelay) // fade in for enemies + ent.alpha = min(1, ent.alpha + SHOWNAMES_FADESPEED * frametime); + + if(!ent.alpha) + return; + + float dist; + dist = vlen(ent.origin - view_origin); + + float a; + a = autocvar_hud_shownames_alpha; + a *= ent.alpha; + if(autocvar_hud_shownames_maxdistance) + { + if(dist >= autocvar_hud_shownames_maxdistance) + return; + a *= ((autocvar_hud_shownames_maxdistance - autocvar_hud_shownames_mindistance) - max(0, dist - autocvar_hud_shownames_mindistance)) / (autocvar_hud_shownames_maxdistance - autocvar_hud_shownames_mindistance); + } + + if(!a) + return; + + float resize; + resize = 1; + if(autocvar_hud_shownames_resize) // limit resize so its never smaller than 0.5... gets unreadable + resize = 0.5 + 0.5 * ((autocvar_hud_shownames_maxdistance - autocvar_hud_shownames_mindistance) - max(0, dist - autocvar_hud_shownames_mindistance)) / (autocvar_hud_shownames_maxdistance - autocvar_hud_shownames_mindistance); + + // draw the sprite image + if(o_z >= 0) + { + o_z = 0; + + vector myPos, mySize; + mySize = (eX * autocvar_hud_shownames_aspect + eY) * autocvar_hud_shownames_fontsize; + myPos = o - '0.5 0 0' * mySize_x - '0 1 0' * mySize_y; + + // size scaling + mySize_x *= resize; + mySize_y *= resize; + + myPos_x += 0.5 * (mySize_x / resize - mySize_x); + myPos_y += (mySize_y / resize - mySize_y); + + vector namepos; // this is where the origin of the string + float namewidth; + + namepos = myPos; + namewidth = mySize_x; + + if(autocvar_hud_shownames_status && teamplay) + { + if(ent.sameteam) + { + if(ent.healthvalue > 0) + { + HUD_Panel_DrawProgressBar(namepos + '0 1 0' * autocvar_hud_shownames_fontsize * resize, eX * 0.5 * mySize_x + eY * resize * autocvar_hud_shownames_statusbar_height, "nametag_statusbar", ent.healthvalue/autocvar_hud_panel_healtharmor_maxhealth, 0, 1, '1 0 0', a, DRAWFLAG_NORMAL); + + if(ent.armorvalue > 0) + HUD_Panel_DrawProgressBar(namepos + '0 1 0' * autocvar_hud_shownames_fontsize * resize + eX * 0.5 * mySize_x, eX * 0.5 * mySize_x + eY * resize * autocvar_hud_shownames_statusbar_height, "nametag_statusbar", ent.armorvalue/autocvar_hud_panel_healtharmor_maxarmor, 0, 0, '0 1 0', a, DRAWFLAG_NORMAL); + } + } + } + + string s; + s = GetPlayerName(ent.sv_entnum-1); + if((autocvar_hud_shownames_decolorize == 1 && teamplay) || autocvar_hud_shownames_decolorize == 2) + s = playername(s, GetPlayerColor(ent.sv_entnum-1)); + + drawfontscale = '1 1 0' * resize; + s = textShortenToWidth(s, namewidth, '1 1 0' * autocvar_hud_shownames_fontsize, stringwidth_colors); + + float width; + width = stringwidth(s, TRUE, '1 1 0' * autocvar_hud_shownames_fontsize); + + if (width != namewidth) + namepos_x += (namewidth - width) / 2; + drawcolorcodedstring(namepos, s, '1 1 0' * autocvar_hud_shownames_fontsize, a, DRAWFLAG_NORMAL); + drawfontscale = '1 1 0'; + } + } +} + +entity shownames_ent[255]; +void Draw_ShowNames_All() +{ + float i; + for(i = 0; i < maxclients; ++i) + { + float t; + t = GetPlayerColor(i); + if(t == COLOR_SPECTATOR) + continue; + + entity e; + e = shownames_ent[i]; + if(!e) + { + e = spawn(); + e.classname = "shownames_tag"; + e.sv_entnum = i+1; + shownames_ent[i] = e; + } + + entity entcs; + entcs = entcs_receiver[i]; + if(entcs) + { + e.healthvalue = entcs.healthvalue; + e.armorvalue = entcs.armorvalue; + e.sameteam = 1; /* (teamplay && (t == myteam)); */ + } + else + { + e.healthvalue = 2342; + e.armorvalue = 0; + e.sameteam = 0; + } + + e.origin = getplayerorigin(i); + if(e.origin == GETPLAYERORIGIN_ERROR) + continue; + + Draw_ShowNames(e); + } +} diff --git a/qcsrc/client/shownames.qh b/qcsrc/client/shownames.qh new file mode 100644 index 0000000000..adbfa57120 --- /dev/null +++ b/qcsrc/client/shownames.qh @@ -0,0 +1,5 @@ +.float healthvalue; +.float armorvalue; +.float sameteam; +.float fadedelay; +.float pointtime; diff --git a/qcsrc/client/sortlist.qc b/qcsrc/client/sortlist.qc index 9bf6cc84b2..225df0ce03 100644 --- a/qcsrc/client/sortlist.qc +++ b/qcsrc/client/sortlist.qc @@ -5,7 +5,7 @@ entity Sort_Spawn() { entity sort; sort = spawn(); - sort.sort_next = NULL; + sort.sort_next = world; sort.chain = sort; return sort; } @@ -15,7 +15,7 @@ entity Sort_New(float(entity,entity) cmp) entity sort; sort = spawn(); sort.sort_cmp = cmp; - sort.sort_next = NULL; + sort.sort_next = world; sort.chain = sort; return sort; } @@ -58,7 +58,7 @@ void Sort_Reset(entity sort) float Sort_HasNext(entity sort) { - return (sort.chain.sort_next != NULL); + return (sort.chain.sort_next != world); } entity Sort_Next(entity sort) @@ -69,7 +69,7 @@ entity Sort_Next(entity sort) next = spawn(); sort.chain.sort_next = next; next.sort_prev = sort.chain; - next.sort_next = NULL; + next.sort_next = world; } sort.chain = next; return next; diff --git a/qcsrc/client/sys-post.qh b/qcsrc/client/sys-post.qh new file mode 100644 index 0000000000..4fee9fec05 --- /dev/null +++ b/qcsrc/client/sys-post.qh @@ -0,0 +1,12 @@ +#pragma noref 0 + +#undef ATTN_NORM + +#ifdef COMPAT_050_ENGINE +// WORKAROUND for 0.5.0 engine +// FIXME remove this after 0.6 release +#undef getproperty +#undef getpropertyvec +float (float property) getproperty = #303; +vector (float property) getpropertyvec = #303; +#endif diff --git a/qcsrc/client/sys-pre.qh b/qcsrc/client/sys-pre.qh new file mode 100644 index 0000000000..1dac05bc16 --- /dev/null +++ b/qcsrc/client/sys-pre.qh @@ -0,0 +1,16 @@ +#ifdef USE_FTE +#pragma target FTE +#endif + +#define CSQC + +#define ATTN_NORM builtin_ATTN_NORM + +#ifdef COMPAT_050_ENGINE +// WORKAROUND for 0.5.0 engine +// FIXME remove this after 0.6 release +#define getproperty builtin_getproperty +#define getpropertyvec builtin_getpropertyvec +#endif + +#pragma noref 1 diff --git a/qcsrc/client/target_music.qc b/qcsrc/client/target_music.qc index 5703c146d2..c4573296a6 100644 --- a/qcsrc/client/target_music.qc +++ b/qcsrc/client/target_music.qc @@ -19,7 +19,7 @@ void TargetMusic_Advance() for(e = world; (e = findfloat(e, enttype, ENT_CLIENT_TRIGGER_MUSIC)); ) if(e.noise) { vol0 = e.lastvol; - if(getsoundtime(e, CHAN_VOICE) < 0) + if(getsoundtime(e, CH_BGM_SINGLE) < 0) { vol0 = -1; } @@ -43,16 +43,16 @@ void TargetMusic_Advance() if(vol != vol0) { if(vol0 < 0) - sound(e, CHAN_VOICE, e.noise, vol, ATTN_NONE); // restart + sound(e, CH_BGM_SINGLE, e.noise, vol, ATTN_NONE); // restart else - sound(e, CHAN_VOICE, "", vol, ATTN_NONE); + sound(e, CH_BGM_SINGLE, "", vol, ATTN_NONE); e.lastvol = vol; } } music_trigger = world; if(best) - bgmtime = getsoundtime(best, CHAN_VOICE); + bgmtime = getsoundtime(best, CH_BGM_SINGLE); else bgmtime = gettime(GETTIME_CDTRACK); } @@ -87,10 +87,10 @@ void Net_TargetMusic() strunzone(e.noise); e.noise = strzone(noi); precache_sound(e.noise); - sound(e, CHAN_VOICE, e.noise, 0, ATTN_NONE); - if(getsoundtime(e, CHAN_VOICE) < 0) + sound(e, CH_BGM_SINGLE, e.noise, 0, ATTN_NONE); + if(getsoundtime(e, CH_BGM_SINGLE) < 0) { - print("Cannot initialize sound ", e.noise, "\n"); + print(sprintf(_("Cannot initialize sound %s\n"), e.noise)); strunzone(e.noise); e.noise = string_null; } @@ -175,10 +175,10 @@ void Ent_ReadTriggerMusic() if(self.noise != s) { precache_sound(self.noise); - sound(self, CHAN_VOICE, self.noise, 0, ATTN_NONE); - if(getsoundtime(self, CHAN_VOICE) < 0) + sound(self, CH_BGM_SINGLE, self.noise, 0, ATTN_NONE); + if(getsoundtime(self, CH_BGM_SINGLE) < 0) { - print("Cannot initialize sound ", self.noise, "\n"); + print(sprintf(_("Cannot initialize sound %s\n"), self.noise)); strunzone(self.noise); self.noise = string_null; } diff --git a/qcsrc/client/teamplay.qc b/qcsrc/client/teamplay.qc index 02c40ba26e..80d89318f4 100644 --- a/qcsrc/client/teamplay.qc +++ b/qcsrc/client/teamplay.qc @@ -1,6 +1,3 @@ -float teamplay; -float myteam; - float TeamByColor(float color) { switch(color) @@ -12,20 +9,31 @@ float TeamByColor(float color) default: return 0; } } +float ColorByTeam(float i) +{ + switch(i) + { + case 0: return COLOR_TEAM1; + case 1: return COLOR_TEAM2; + case 2: return COLOR_TEAM3; + case 3: return COLOR_TEAM4; + default: return COLOR_TEAM1; + } +} float GetPlayerColorForce(float i) { if(!teamplay) return 0; else - return stof(getplayerkey(i, "colors")) & 15; + return stof(getplayerkeyvalue(i, "colors")) & 15; } float GetPlayerColor(float i) { if not(playerslots[i].gotscores) // unconnected return COLOR_SPECTATOR; - else if(stof(getplayerkey(i, "frags")) == FRAGS_SPECTATOR) + else if(stof(getplayerkeyvalue(i, "frags")) == FRAGS_SPECTATOR) return COLOR_SPECTATOR; else return GetPlayerColorForce(i); @@ -33,7 +41,7 @@ float GetPlayerColor(float i) string GetPlayerName(float i) { - return ColorTranslateRGB(getplayerkey(i, "name")); + return ColorTranslateRGB(getplayerkeyvalue(i, "name")); } vector GetTeamRGB(float color) @@ -52,10 +60,10 @@ string GetTeamName(float color) { switch(color) { - default: return "Spectators"; - case COLOR_TEAM1: return "Red Team"; - case COLOR_TEAM2: return "Blue Team"; - case COLOR_TEAM3: return "Yellow Team"; - case COLOR_TEAM4: return "Pink Team"; + default: return _("Spectators"); + case COLOR_TEAM1: return _("Red Team"); + case COLOR_TEAM2: return _("Blue Team"); + case COLOR_TEAM3: return _("Yellow Team"); + case COLOR_TEAM4: return _("Pink Team"); } } diff --git a/qcsrc/client/teamplay.qh b/qcsrc/client/teamplay.qh new file mode 100644 index 0000000000..83359906bc --- /dev/null +++ b/qcsrc/client/teamplay.qh @@ -0,0 +1,2 @@ +float teamplay; +float myteam; diff --git a/qcsrc/client/teamradar.qc b/qcsrc/client/teamradar.qc index cccce7680b..f3ec99bfee 100644 --- a/qcsrc/client/teamradar.qc +++ b/qcsrc/client/teamradar.qc @@ -5,7 +5,6 @@ vector teamradar_size2d; // 2D size vector teamradar_extraclip_mins, teamradar_extraclip_maxs; // for non-centered radar display float teamradar_size; // 2D scale factor float hud_panel_radar_scale; // window size = ...qu -float hud_panel_radar_nohudhack; float v_flipped; float vlen2d(vector v) @@ -15,7 +14,7 @@ float vlen2d(vector v) float vlen_maxnorm2d(vector v) { - return max4(v_x, v_y, -v_x, -v_y); + return max(v_x, v_y, -v_x, -v_y); } float vlen_minnorm2d(vector v) @@ -81,7 +80,7 @@ void draw_teamradar_background(float fg) } } -void(vector coord3d, vector pangles, vector rgb) draw_teamradar_player = +void draw_teamradar_player(vector coord3d, vector pangles, vector rgb) { vector coord, rgb2; @@ -118,7 +117,7 @@ void(vector coord3d, vector pangles, vector rgb) draw_teamradar_player = R_PolygonVertex(coord-v_forward, '1 0 0', rgb, panel_fg_alpha); R_PolygonVertex(coord-v_right*3-v_forward*2, '1 1 0', rgb, panel_fg_alpha); R_EndPolygon(); -}; +} void draw_teamradar_icon(vector coord, float icon, entity pingdata, vector rgb, float a) { @@ -171,13 +170,18 @@ void draw_teamradar_link(vector start, vector end, float colors) float hud_panel_radar_scale; float hud_panel_radar_foreground_alpha; float hud_panel_radar_rotation; -vector hud_panel_radar_size; +noref vector hud_panel_radar_size; // fteqcc sucks float hud_panel_radar_zoommode; void teamradar_loadcvars() { v_flipped = autocvar_v_flipped; hud_panel_radar_scale = autocvar_hud_panel_radar_scale; + if (hud_panel_radar_maximized && !autocvar__hud_configure) + { + if (autocvar_hud_panel_radar_maximized_scale > 0) + hud_panel_radar_scale = autocvar_hud_panel_radar_maximized_scale; + } hud_panel_radar_foreground_alpha = autocvar_hud_panel_radar_foreground_alpha * panel_fg_alpha; hud_panel_radar_rotation = autocvar_hud_panel_radar_rotation; hud_panel_radar_zoommode = autocvar_hud_panel_radar_zoommode; @@ -188,9 +192,6 @@ void teamradar_loadcvars() if(!hud_panel_radar_foreground_alpha) hud_panel_radar_foreground_alpha = 0.8 * panel_fg_alpha; if(!hud_panel_radar_size_x) hud_panel_radar_size_x = 128; if(!hud_panel_radar_size_y) hud_panel_radar_size_y = hud_panel_radar_size_x; - - hud_panel_radar_size_z = 0; - hud_panel_radar_nohudhack = 0; } // radar links diff --git a/qcsrc/client/teamradar.qh b/qcsrc/client/teamradar.qh index 2a93fe163a..2dbdf89658 100644 --- a/qcsrc/client/teamradar.qh +++ b/qcsrc/client/teamradar.qh @@ -2,6 +2,6 @@ // to make entities have dots on the team radar .float teamradar_icon; -.float teamradar_times[MAX_TEAMRADAR_TIMES]; FTEQCC_YOU_SUCK_THIS_IS_NOT_UNREFERENCED(teamradar_times); +.float teamradar_times[MAX_TEAMRADAR_TIMES]; .float teamradar_time_index; .vector teamradar_color; diff --git a/qcsrc/client/tturrets.qc b/qcsrc/client/tturrets.qc new file mode 100644 index 0000000000..2b9ec0297b --- /dev/null +++ b/qcsrc/client/tturrets.qc @@ -0,0 +1,668 @@ +string tid2info_base; +string tid2info_head; +string tid2info_name; +vector tid2info_min; +vector tid2info_max; + +void turret_tid2info(float _tid); +void turret_precache(float _tid); +float turret_is_precache[TID_LAST]; + +void turrets_precache() +{ + turret_precache(TID_COMMON); +} + +void turret_precache(float _tid) +{ + if (!turret_is_precache[TID_COMMON]) + { + precache_sound ("weapons/rocket_impact.wav"); + precache_model ("models/turrets/base-gib1.md3"); + precache_model ("models/turrets/base-gib2.md3"); + precache_model ("models/turrets/base-gib3.md3"); + precache_model ("models/turrets/base-gib4.md3"); + precache_model ("models/turrets/head-gib1.md3"); + precache_model ("models/turrets/head-gib2.md3"); + precache_model ("models/turrets/head-gib3.md3"); + precache_model ("models/turrets/head-gib4.md3"); + precache_model ("models/turrets/terrainbase.md3"); + precache_model ("models/turrets/base.md3"); + precache_model ("models/turrets/rocket.md3"); + } + turret_tid2info(_tid); + if(turret_is_precache[_tid]) + return; + + switch(_tid) + { + case TID_EWHEEL: + precache_model ("models/turrets/ewheel-base2.md3"); + precache_model ("models/turrets/ewheel-gun1.md3"); + break; + case TID_FLAC: + precache_model ("models/turrets/flac.md3"); + break; + case TID_FUSION: + precache_model ("models/turrets/reactor.md3"); + break; + case TID_HELLION: + precache_model ("models/turrets/hellion.md3"); + break; + case TID_HK: + precache_model ("models/turrets/hk.md3"); + break; + case TID_MACHINEGUN: + precache_model ("models/turrets/machinegun.md3"); + precache_sound ("weapons/uzi_fire.wav"); + break; + case TID_MLRS: + precache_model ("models/turrets/mlrs.md3"); + break; + case TID_PHASER: + precache_model ("models/turrets/phaser.md3"); + precache_model ("models/turrets/phaser_beam.md3"); + precache_sound ("turrets/phaser.wav"); + break; + case TID_PLASMA: + precache_model ("models/turrets/plasma.md3"); + break; + case TID_PLASMA_DUAL: + precache_model ("models/turrets/plasmad.md3"); + break; + case TID_TESLA: + precache_model ("models/turrets/tesla_head.md3"); + precache_model ("models/turrets/tesla_base.md3"); + break; + case TID_WALKER: + precache_model ("models/turrets/walker_head_minigun.md3"); + precache_model ("models/turrets/walker_body.md3"); + precache_sound ("weapons/uzi_fire.wav"); + break; + } + turret_is_precache[_tid] = TRUE; +} + +void turret_tid2info(float _tid) +{ + tid2info_base = "models/turrets/base.md3"; + tid2info_min = '-32 -32 0'; + tid2info_max = '32 32 64'; + + switch(_tid) + { + case TID_EWHEEL: + tid2info_base = "models/turrets/ewheel-base2.md3"; + tid2info_head = "models/turrets/ewheel-gun1.md3"; + tid2info_name = "eWheel"; + break; + case TID_FLAC: + tid2info_head = "models/turrets/flac.md3"; + tid2info_name = "Flac Cannon"; + break; + case TID_FUSION: + tid2info_head = "models/turrets/reactor.md3"; + tid2info_name = "Fusion Reactor"; + tid2info_min = '-34 -34 0'; + tid2info_max = '34 34 90'; + break; + case TID_HELLION: + tid2info_head = "models/turrets/hellion.md3"; + tid2info_name = "Hellion"; + break; + case TID_HK: + tid2info_head = "models/turrets/hk.md3"; + tid2info_name = "Hunter-Killer"; + break; + case TID_MACHINEGUN: + tid2info_head = "models/turrets/machinegun.md3"; + tid2info_name = "Machinegun"; + break; + case TID_MLRS: + tid2info_head = "models/turrets/mlrs.md3"; + tid2info_name = "MLRS"; + break; + case TID_PHASER: + tid2info_head = "models/turrets/phaser.md3"; + tid2info_name = "Phaser"; + break; + case TID_PLASMA: + tid2info_head = "models/turrets/plasma.md3"; + tid2info_name = "Plasma"; + break; + case TID_PLASMA_DUAL: + tid2info_head = "models/turrets/plasmad.md3"; + tid2info_name = "Dual Plasma"; + break; + case TID_TESLA: + tid2info_base = "models/turrets/tesla_base.md3"; + tid2info_head = "models/turrets/tesla_head.md3"; + tid2info_name = "Tesla coil"; + tid2info_min = '-60 -60 0'; + tid2info_max ='60 60 128'; + break; + case TID_WALKER: + tid2info_base = "models/turrets/walker_body.md3"; + tid2info_head = "models/turrets/walker_head_minigun.md3"; + tid2info_name = "Walker"; + tid2info_min = '-70 -70 0'; + tid2info_max = '70 70 95'; + break; + } +} + +void turret_remove() +{ + remove(self.tur_head); + //remove(self.enemy); + self.tur_head = world; +} + +.vector glowmod; +void turret_changeteam() +{ + switch(self.team - 1) + { + case COLOR_TEAM1: // Red + self.glowmod = '2 0 0'; + self.teamradar_color = '1 0 0'; + break; + + case COLOR_TEAM2: // Blue + self.glowmod = '0 0 2'; + self.teamradar_color = '0 0 1'; + break; + + case COLOR_TEAM3: // Yellow + self.glowmod = '1 1 0'; + self.teamradar_color = '1 1 0'; + break; + + case COLOR_TEAM4: // Pink + self.glowmod = '1 0 1'; + self.teamradar_color = '1 0 1'; + break; + } + + if(self.team) + self.colormap = 1024 + (self.team - 1) * 17; + + self.tur_head.colormap = self.colormap; + self.tur_head.glowmod = self.glowmod; + +} + +void turret_head_draw() +{ + self.drawmask = MASK_NORMAL; +} + +void turret_draw() +{ + float dt; + + dt = time - self.move_time; + self.move_time = time; + if(dt <= 0) + return; + + self.tur_head.angles += dt * self.tur_head.move_avelocity; + + if (self.health < 127) + { + dt = random(); + + if(dt < 0.03) + te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16); + } + + if(self.health < 85) + if(dt < 0.01) + pointparticles(particleeffectnum("smoke_large"), (self.origin + (randomvec() * 80)), '0 0 0', 1); + + if(self.health < 32) + if(dt < 0.015) + pointparticles(particleeffectnum("smoke_small"), (self.origin + (randomvec() * 80)), '0 0 0', 1); + +} + +void turret_draw2d() +{ + if(self.netname == "") + return; + + if(autocvar_cl_hidewaypoints) // also check g_waypointsprites_turrets after next release (needs changed to clients default/config .cfg) + return; + + float dist = vlen(self.origin - view_origin); + vector o; + /* + // TODO: Vehicle tactical hud + o = project_3d_to_2d(self.origin + '0 0 32'); + if(o_z < 0 + || o_x < (vid_conwidth * waypointsprite_edgeoffset_left) + || o_y < (vid_conheight * waypointsprite_edgeoffset_top) + || o_x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right)) + || o_y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom))) + return; // Dont draw wp's for turrets out of view + o_z = 0; + if(hud != HUD_NORMAL) + { + switch(hud) + { + case HUD_SPIDERBOT: + case HUD_WAKIZASHI: + case HUD_RAPTOR: + vector pz = drawgetimagesize("gfx/vehicles/axh-bracket.tga") * 0.25; + drawpic(o - pz * 0.5 , "gfx/vehicles/axh-bracket.tga", pz , '1 1 1', 0.75, DRAWFLAG_NORMAL); + break; + } + } + */ + + if(dist > self.maxdistance) + return; + + string spriteimage = self.netname; + float t = (GetPlayerColor(player_localnum) + 1); + float a = self.alpha * autocvar_hud_panel_fg_alpha; + vector rgb = spritelookupcolor(spriteimage, self.teamradar_color); + + + if(self.maxdistance > waypointsprite_normdistance) + a *= pow(bound(0, (self.maxdistance - dist) / (self.maxdistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent); + else if(self.maxdistance > 0) + a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha; + + if(rgb == '0 0 0') + { + self.teamradar_color = '1 0 1'; + print(sprintf("WARNING: sprite of name %s has no color, using pink so you notice it\n", spriteimage)); + } + + string txt = self.netname; + if(autocvar_g_waypointsprite_spam && waypointsprite_count >= autocvar_g_waypointsprite_spam) + txt = _("Spam"); + else + txt = spritelookuptext(spriteimage); + + if(time - floor(time) > 0.5 && t == self.team) + { + if(self.helpme && time < self.helpme) + { + a *= SPRITE_HELPME_BLINK; + txt = sprintf(_("%s under attack!"), txt); + } + else + a *= spritelookupblinkvalue(spriteimage); + } + + if(autocvar_g_waypointsprite_uppercase) + txt = strtoupper(txt); + + if(a > 1) + { + rgb *= a; + a = 1; + } + + if(a <= 0) + return; + + rgb = fixrgbexcess(rgb); + + o = project_3d_to_2d(self.origin + '0 0 64'); + if(o_z < 0 + || o_x < (vid_conwidth * waypointsprite_edgeoffset_left) + || o_y < (vid_conheight * waypointsprite_edgeoffset_top) + || o_x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right)) + || o_y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom))) + return; // Dont draw wp's for turrets out of view + + o_z = 0; + + float edgedistance_min, crosshairdistance; + edgedistance_min = min((o_y - (vid_conheight * waypointsprite_edgeoffset_top)), + (o_x - (vid_conwidth * waypointsprite_edgeoffset_left)), + (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right)) - o_x, + (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)) - o_y); + + float vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height); + + crosshairdistance = sqrt( pow(o_x - vid_conwidth/2, 2) + pow(o_y - vid_conheight/2, 2) ); + + t = waypointsprite_scale * vidscale; + a *= waypointsprite_alpha; + + { + a = a * (1 - (1 - waypointsprite_distancefadealpha) * (bound(0, dist/waypointsprite_distancefadedistance, 1))); + t = t * (1 - (1 - waypointsprite_distancefadescale) * (bound(0, dist/waypointsprite_distancefadedistance, 1))); + } + if (edgedistance_min < waypointsprite_edgefadedistance) { + a = a * (1 - (1 - waypointsprite_edgefadealpha) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1))); + t = t * (1 - (1 - waypointsprite_edgefadescale) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1))); + } + if(crosshairdistance < waypointsprite_crosshairfadedistance) { + a = a * (1 - (1 - waypointsprite_crosshairfadealpha) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1))); + t = t * (1 - (1 - waypointsprite_crosshairfadescale) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1))); + } + + o = drawspritearrow(o, M_PI, rgb, a, SPRITE_ARROW_SCALE * t); + o = drawspritetext(o, M_PI, (SPRITE_HEALTHBAR_WIDTH + 2 * SPRITE_HEALTHBAR_BORDER) * t, rgb, a, waypointsprite_fontsize * '1 1 0', txt); + drawhealthbar( + o, + 0, + self.health / 255, + '0 0 0', + '0 0 0', + 0.5 * SPRITE_HEALTHBAR_WIDTH * t, + 0.5 * SPRITE_HEALTHBAR_HEIGHT * t, + SPRITE_HEALTHBAR_MARGIN * t + 0.5 * waypointsprite_fontsize, + SPRITE_HEALTHBAR_BORDER * t, + 0, + rgb, + a * SPRITE_HEALTHBAR_BORDERALPHA, + rgb, + a * SPRITE_HEALTHBAR_HEALTHALPHA, + DRAWFLAG_NORMAL + ); +} + +void turret_walker_draw() +{ + float dt; + + dt = time - self.move_time; + self.move_time = time; + if(dt <= 0) + return; + + fixedmakevectors(self.angles); + movelib_groundalign4point(300, 100, 0.25); + setorigin(self, self.origin + self.velocity * dt); + self.tur_head.angles += dt * self.tur_head.move_avelocity; + self.angles_y = self.move_angles_y; + + if (self.health < 127) + if(random() < 0.15) + te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16); +} + +void turret_ewheel_draw() +{ + float dt; + + dt = time - self.move_time; + self.move_time = time; + if(dt <= 0) + return; + + fixedmakevectors(self.angles); + setorigin(self, self.origin + self.velocity * dt); + self.tur_head.angles += dt * self.tur_head.move_avelocity; + self.angles_y = self.move_angles_y; + + if (self.health < 127) + if(random() < 0.05) + te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16); +} + +void(entity e, entity tagentity, string tagname) setattachment = #443; +void turret_construct() +{ + if(self.tur_head == world) + self.tur_head = spawn(); + + turret_tid2info(self.turret_type); + self.netname = tid2info_name; + + setorigin(self, self.origin); + setmodel(self, tid2info_base); + setmodel(self.tur_head, tid2info_head); + setsize(self, tid2info_min, tid2info_max); + setsize(self.tur_head, '0 0 0', '0 0 0'); + + if(self.turret_type == TID_EWHEEL) + setattachment(self.tur_head, self, ""); + else + setattachment(self.tur_head, self, "tag_head"); + + self.tur_head.classname = "turret_head"; + self.tur_head.owner = self; + self.tur_head.move_movetype = MOVETYPE_NOCLIP; + self.move_movetype = MOVETYPE_NOCLIP; + self.tur_head.angles = self.angles; + self.health = 255; + self.solid = SOLID_BBOX; + self.tur_head.solid = SOLID_NOT; + self.movetype = MOVETYPE_NOCLIP; + self.tur_head.movetype = MOVETYPE_NOCLIP; + self.draw = turret_draw; + self.entremove = turret_remove; + self.drawmask = MASK_NORMAL; + self.tur_head.drawmask = MASK_NORMAL; + self.anim_start_time = 0; + self.draw2d = turret_draw2d; + self.maxdistance = 4000; // use g_waypointsprites_turrets_maxdist after next release (needs changed to cleint's default) + self.teamradar_color = '1 0 0'; + self.alpha = 1; + + if(self.turret_type == TID_EWHEEL || self.turret_type == TID_WALKER) + { + self.gravity = 1; + self.movetype = MOVETYPE_BOUNCE; + self.move_movetype = MOVETYPE_BOUNCE; + self.move_origin = self.origin; + self.move_time = time; + switch(self.turret_type) + { + case TID_EWHEEL: + self.draw = turret_ewheel_draw; + break; + case TID_WALKER: + self.draw = turret_walker_draw; + break; + + } + } +} + +entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, float _explode); +void turret_gibboom(); +void turret_gib_draw() +{ + Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy); + + self.drawmask = MASK_NORMAL; + + if(self.cnt) + { + if(time >= self.nextthink) + { + turret_gibboom(); + remove(self); + } + } + else + { + self.alpha = bound(0, self.nextthink - time, 1); + if(self.alpha < ALPHA_MIN_VISIBLE) + remove(self); + } +} + +void turret_gibboom() +{ + float i; + + sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1); + + for (i = 1; i < 5; i = i + 1) + turret_gibtoss(strcat("models/turrets/head-gib", ftos(i), ".md3"), self.origin + '0 0 2', self.velocity + randomvec() * 700, '0 0 0', FALSE); +} + +entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, float _explode) +{ + entity gib; + + traceline(_from, _to, MOVE_NOMONSTERS, world); + if(trace_startsolid) + return world; + + gib = spawn(); + setorigin(gib, _from); + setmodel(gib, _model); + gib.colormod = _cmod; + gib.solid = SOLID_CORPSE; + gib.draw = turret_gib_draw; + gib.cnt = _explode; + setsize(gib, '-1 -1 -1', '1 1 1'); + if(_explode) + { + gib.nextthink = time + 0.2 * (autocvar_cl_gibs_lifetime * (1 + prandom() * 0.15)); + gib.effects = EF_FLAME; + } + else + gib.nextthink = time + autocvar_cl_gibs_lifetime * (1 + prandom() * 0.15); + + gib.gravity = 1; + gib.move_movetype = MOVETYPE_BOUNCE; + gib.move_origin = gib.origin = _from; + gib.move_velocity = _to; + gib.move_avelocity = prandomvec() * 32; + gib.move_time = time; + gib.damageforcescale = 1; + gib.classname = "turret_gib"; + + return gib; +} + +void turret_die() +{ + entity headgib; + + sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1); + turret_tid2info(self.turret_type); + + // Base + if(self.turret_type == TID_EWHEEL) + turret_gibtoss(tid2info_base, self.origin + '0 0 18', self.velocity + '0 0 400' + '0.1 0.1 1' * (random() * 400), '-1 -1 -1', TRUE); + else if (self.turret_type == TID_WALKER) + turret_gibtoss(tid2info_base, self.origin + '0 0 18', self.velocity + '0 0 300' + '0.1 0.1 1' * (random() * 200), '-1 -1 -1', TRUE); + else if (self.turret_type == TID_TESLA) + turret_gibtoss(tid2info_base, self.origin + '0 0 18', '0 0 200', '-1 -1 -1', FALSE); + else + { + if (random() > 0.5) + { + turret_gibtoss("models/turrets/base-gib2.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', FALSE); + turret_gibtoss("models/turrets/base-gib3.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', FALSE); + turret_gibtoss("models/turrets/base-gib4.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', FALSE); + } + else + turret_gibtoss("models/turrets/base-gib1.md3", self.origin + '0 0 8', '0 0 0', '0 0 0', TRUE); + + headgib = turret_gibtoss(tid2info_head, self.origin + '0 0 32', '0 0 200' + randomvec() * 200, '-1 -1 -1', TRUE); + if(headgib) + { + headgib.angles = headgib.move_angles = self.tur_head.angles; + headgib.avelocity = headgib.move_avelocity = self.tur_head.move_avelocity + randomvec() * 45; + headgib.avelocity_y = headgib.move_avelocity_y = headgib.move_avelocity_y * 5; + headgib.gravity = 0.5; + } + } + + setmodel(self, "null"); + setmodel(self.tur_head, "null"); +} + +void ent_turret() +{ + float sf; + sf = ReadByte(); + + if(sf & TNSF_SETUP) + { + self.turret_type = ReadByte(); + + self.origin_x = ReadCoord(); + self.origin_y = ReadCoord(); + self.origin_z = ReadCoord(); + + self.angles_x = ReadAngle(); + self.angles_y = ReadAngle(); + + turret_precache(self.turret_type); + turret_construct(); + self.colormap = 1024; + self.glowmod = '0 1 1'; + self.tur_head.colormap = self.colormap; + self.tur_head.glowmod = self.glowmod; + } + + if(sf & TNSF_ANG) + { + if(self.tur_head == world) // aparenly this can happpen before TNSF_SETUP. great. + self.tur_head = spawn(); + + self.tur_head.move_angles_x = ReadShort(); + self.tur_head.move_angles_y = ReadShort(); + //self.tur_head.angles = self.angles + self.tur_head.move_angles; + self.tur_head.angles = self.tur_head.move_angles; + } + + if(sf & TNSF_AVEL) + { + if(self.tur_head == world) // aparenly this can happpen before TNSF_SETUP. great. + self.tur_head = spawn(); + + self.tur_head.move_avelocity_x = ReadShort(); + self.tur_head.move_avelocity_y = ReadShort(); + } + + if(sf & TNSF_MOVE) + { + self.origin_x = ReadShort(); + self.origin_y = ReadShort(); + self.origin_z = ReadShort(); + setorigin(self, self.origin); + + self.velocity_x = ReadShort(); + self.velocity_y = ReadShort(); + self.velocity_z = ReadShort(); + + self.move_angles_y = ReadShort(); + + self.move_time = time; + self.move_velocity = self.velocity; + self.move_origin = self.origin; + } + + if(sf & TNSF_ANIM) + { + self.frame1time = ReadCoord(); + self.frame = ReadByte(); + } + + if(sf & TNSF_STATUS) + { + float _tmp; + _tmp = ReadByte(); + if(_tmp != self.team) + { + self.team = _tmp; + turret_changeteam(); + } + + _tmp = ReadByte(); + if(_tmp == 0 && self.health != 0) + turret_die(); + else if(self.health && self.health != _tmp) + self.helpme = servertime + 10; + + self.health = _tmp; + } + //self.enemy.health = self.health / 255; +} diff --git a/qcsrc/client/tturrets.qh b/qcsrc/client/tturrets.qh new file mode 100644 index 0000000000..cf74f48ad2 --- /dev/null +++ b/qcsrc/client/tturrets.qh @@ -0,0 +1,3 @@ +void ent_turret(); +void turrets_precache(); +.entity tur_head; diff --git a/qcsrc/client/tuba.qc b/qcsrc/client/tuba.qc index 5f1228557f..2fea077c5d 100644 --- a/qcsrc/client/tuba.qc +++ b/qcsrc/client/tuba.qc @@ -1,6 +1,79 @@ -#define TUBA_STARTNOTE(n) strcat((checkextension("DP_SND_SETPARAMS") ? "weapons/tuba_loopnote" : "weapons/tuba_note"), ftos(n), ".wav") -.float cnt; // note +#define TUBA_MIN -18 +#define TUBA_MAX 27 +#define TUBA_INSTRUMENTS 2 + +#define TUBA_STARTNOTE(i,n) strcat("weapons/tuba", (i ? ftos(i) : ""), "_loopnote", ftos(n), ".wav") +.float note; // note .float attenuate; // if set, attenuate it +.float cnt; // current volume +.float count; // initial volume +.float tuba_instrument; + +float Tuba_PitchStep; + +void tubasound(entity e, float restart) +{ + string snd1; + + snd1 = string_null; + + if(Tuba_PitchStep) + { + string snd2; + float f1, f2; + float p1, p2; + float m; + + f1 = 1; + p1 = 1; + snd2 = string_null; + f2 = 0; + p2 = 1; + + m = mod(e.note, Tuba_PitchStep); + if(m) + { + if(e.note - m < TUBA_MIN) + { + if(restart) + snd1 = TUBA_STARTNOTE(e.tuba_instrument, e.note - m + Tuba_PitchStep); + p1 = pow(2.0, (m - Tuba_PitchStep) / 12.0); + } + else if(e.note - m + Tuba_PitchStep > TUBA_MAX) + { + if(restart) + snd1 = TUBA_STARTNOTE(e.tuba_instrument, e.note - m); + p1 = pow(2.0, m / 12.0); + } + else + { + if(restart) + snd1 = TUBA_STARTNOTE(e.tuba_instrument, e.note - m); + f1 = cos(M_PI_2 * m / Tuba_PitchStep); + p1 = pow(2.0, m / 12.0); + if(restart) + snd2 = TUBA_STARTNOTE(e.tuba_instrument, e.note - m + Tuba_PitchStep); + f2 = sin(M_PI_2 * m / Tuba_PitchStep); + p2 = pow(2.0, (m - Tuba_PitchStep) / 12.0); + } + } + else + { + if(restart) + snd1 = TUBA_STARTNOTE(e.tuba_instrument, e.note); + } + + sound7(e, CH_TUBA, snd1, e.cnt * f1, e.attenuate * autocvar_g_balance_tuba_attenuation, 100 * p1, 0); + if(f2) + sound7(e.enemy, CH_TUBA, snd2, e.cnt * f2, e.attenuate * autocvar_g_balance_tuba_attenuation, 100 * p2, 0); + } + else + { + if(restart) + snd1 = TUBA_STARTNOTE(e.tuba_instrument, e.note); + sound(e, CH_TUBA, snd1, e.cnt, e.attenuate * autocvar_g_balance_tuba_attenuation); + } +} void Ent_TubaNote_Think() { @@ -13,18 +86,27 @@ void Ent_TubaNote_Think() self.nextthink = time; if(self.cnt <= 0) { - sound(self, CHAN_PROJECTILE, "misc/null.wav", 0, 0); + sound(self, CH_TUBA, "misc/null.wav", 0, 0); + if(self.enemy) + { + sound(self.enemy, CH_TUBA, "misc/null.wav", 0, 0); + remove(self.enemy); + } remove(self); } else - sound(self, CHAN_PROJECTILE, "", self.cnt, self.attenuate * autocvar_g_balance_tuba_attenuation); + { + tubasound(self, 0); + } } void Ent_TubaNote_UpdateSound() { self.enemy.cnt = bound(0, VOL_BASE * autocvar_g_balance_tuba_volume, 1); self.enemy.count = self.enemy.cnt; - sound(self.enemy, CHAN_PROJECTILE, TUBA_STARTNOTE(self.cnt), self.enemy.cnt, self.enemy.attenuate * autocvar_g_balance_tuba_attenuation); + self.enemy.note = self.note; + self.enemy.tuba_instrument = self.tuba_instrument; + tubasound(self.enemy, 1); } void Ent_TubaNote_StopSound() @@ -35,43 +117,83 @@ void Ent_TubaNote_StopSound() void Ent_TubaNote(float bIsNew) { - float f, n; + float f, n, i, att, upd; f = ReadByte(); - n = floor(f / 2) - 42; - if(n != self.cnt || bIsNew) - if(self.enemy) - Ent_TubaNote_StopSound(); - if(!self.enemy) + + upd = 0; + + if(f & 1) { - self.enemy = spawn(); - self.enemy.classname = "tuba_note"; - bIsNew = TRUE; + n = ReadChar(); + i = ReadByte(); + att = (i & 1); + i = floor(i / 2); + + if(n != self.note || i != self.tuba_instrument || bIsNew) + { + if(self.enemy) + Ent_TubaNote_StopSound(); + } + + if(!self.enemy) + { + self.enemy = spawn(); + self.enemy.classname = "tuba_note"; + if(Tuba_PitchStep) + { + self.enemy.enemy = spawn(); + self.enemy.enemy.classname = "tuba_note_2"; + } + bIsNew = TRUE; + } + + self.enemy.attenuate = att; + + if(bIsNew) + { + self.note = n; + self.tuba_instrument = i; + upd = 1; + } } - if(f & 1) + + if(f & 2) { self.enemy.origin_x = ReadCoord(); self.enemy.origin_y = ReadCoord(); self.enemy.origin_z = ReadCoord(); setorigin(self.enemy, self.enemy.origin); - self.enemy.attenuate = ReadByte(); + if(self.enemy.enemy) + setorigin(self.enemy.enemy, self.enemy.origin); } + self.think = Ent_TubaNote_StopSound; self.entremove = Ent_TubaNote_StopSound; self.enemy.think = Ent_TubaNote_Think; self.enemy.nextthink = time + 10; - if(bIsNew) - { - self.cnt = n; + + if(upd) Ent_TubaNote_UpdateSound(); - } } void Tuba_Precache() { - float i; - for(i = -18; i <= +27; ++i) + float i, n; + Tuba_PitchStep = autocvar_g_balance_tuba_pitchstep; + if(Tuba_PitchStep) + { + if(!checkextension("DP_SND_SOUND7_WIP2") && !checkextension("DP_SND_SOUND7")) + { + print("^1NOTE:^7 requested pitch shifting, but not supported by this engine build\n"); + Tuba_PitchStep = 0; + } + } + for(n = TUBA_MIN; n <= TUBA_MAX; ++n) { - precache_sound(TUBA_STARTNOTE(i)); + if(!Tuba_PitchStep || (mod(n, Tuba_PitchStep) == 0)) + { + for(i = 0; i < TUBA_INSTRUMENTS; ++i) + precache_sound(TUBA_STARTNOTE(i, n)); + } } - //precache_sound(""); // we want to change volume of existing sounds } diff --git a/qcsrc/client/vehicles/racer.qc b/qcsrc/client/vehicles/racer.qc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/qcsrc/client/vehicles/raptor.qc b/qcsrc/client/vehicles/raptor.qc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/qcsrc/client/vehicles/spiderbot.qc b/qcsrc/client/vehicles/spiderbot.qc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/qcsrc/client/vehicles/vehicles.qc b/qcsrc/client/vehicles/vehicles.qc new file mode 100644 index 0000000000..ccb9cff583 --- /dev/null +++ b/qcsrc/client/vehicles/vehicles.qc @@ -0,0 +1,722 @@ +#define hud_bg "gfx/vehicles/frame.tga" +#define hud_sh "gfx/vehicles/vh-shield.tga" + +#define hud_hp_bar "gfx/vehicles/bar_up_left.tga" +#define hud_hp_ico "gfx/vehicles/health.tga" +#define hud_sh_bar "gfx/vehicles/bar_dwn_left.tga" +#define hud_sh_ico "gfx/vehicles/shield.tga" + +#define hud_ammo1_bar "gfx/vehicles/bar_up_right.tga" +#define hud_ammo1_ico "gfx/vehicles/bullets.tga" +#define hud_ammo2_bar "gfx/vehicles/bar_dwn_right.tga" +#define hud_ammo2_ico "gfx/vehicles/rocket.tga" + +entity dropmark; +float autocvar_cl_vehicles_hudscale; +float autocvar_cl_vehicles_hudalpha; + + +void CSQC_WAKIZASHI_HUD(); +void CSQC_SPIDER_HUD(); +void CSQC_RAPTOR_HUD(); +void CSQC_BUMBLE_HUD(); + +#define MAX_AXH 4 +entity AuxiliaryXhair[MAX_AXH]; +const var void Draw_Not(); + +.string axh_image; +.float axh_fadetime; +.float axh_drawflag; +.float axh_scale; + +void AuxiliaryXhair_Draw2D() +{ + vector loc, psize; + + psize = self.axh_scale * draw_getimagesize(self.axh_image); + loc = project_3d_to_2d(self.origin) - 0.5 * psize; + if not (loc_z < 0 || loc_x < 0 || loc_y < 0 || loc_x > vid_conwidth || loc_y > vid_conheight) + { + loc_z = 0; + psize_z = 0; + drawpic(loc, self.axh_image, psize, self.colormod, self.alpha, self.axh_drawflag); + } + + if(time - self.cnt > self.axh_fadetime) + self.draw2d = Draw_Not; +} + +void Net_AuXair2(float bIsNew) +{ + float axh_id; + entity axh; + + axh_id = bound(0, ReadByte(), MAX_AXH); + axh = AuxiliaryXhair[axh_id]; + + if(axh == world || wasfreed(axh)) // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist?) + { + axh = spawn(); + axh.draw2d = Draw_Not; + axh.drawmask = MASK_NORMAL; + axh.axh_drawflag = DRAWFLAG_ADDITIVE; + axh.axh_fadetime = 0.1; + axh.axh_image = "gfx/vehicles/axh-ring.tga"; + axh.axh_scale = 1; + axh.alpha = 1; + AuxiliaryXhair[axh_id] = axh; + } + + axh.draw2d = AuxiliaryXhair_Draw2D; + + axh.origin_x = ReadCoord(); + axh.origin_y = ReadCoord(); + axh.origin_z = ReadCoord(); + + axh.colormod_x = ReadByte() / 255; + axh.colormod_y = ReadByte() / 255; + axh.colormod_z = ReadByte() / 255; + axh.cnt = time; +} + +void Net_VehicleSetup() +{ + + float hud_id, i; + + hud_id = ReadByte(); + + // hud_id == 0 means we exited a vehicle, so stop alarm sound/s + if(hud_id == 0) + { + sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTN_NONE); + sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTN_NONE); + + return; + } + + hud_id = bound(HUD_SPIDERBOT, hud_id, HUD_RAPTOR); + + // Init auxiliary crosshairs + entity axh; + for(i = 0; i < MAX_AXH; ++i) + { + axh = AuxiliaryXhair[i]; + if(axh != world && !wasfreed(axh)) // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist?) + remove(axh); + + axh = spawn(); + axh.draw2d = Draw_Not; + axh.drawmask = MASK_NORMAL; + axh.axh_drawflag = DRAWFLAG_NORMAL; + axh.axh_fadetime = 0.1; + axh.axh_image = "gfx/vehicles/axh-ring.tga"; + axh.axh_scale = 1; + axh.alpha = 1; + AuxiliaryXhair[i] = axh; + } + + switch(hud_id) + { + case HUD_SPIDERBOT: + // Minigun1 + AuxiliaryXhair[0].axh_image = "gfx/vehicles/axh-ring.tga"; + AuxiliaryXhair[0].axh_scale = 0.25; + // Minigun2 + AuxiliaryXhair[1].axh_image = "gfx/vehicles/axh-ring.tga"; + AuxiliaryXhair[1].axh_scale = 0.25; + // Rocket + AuxiliaryXhair[2].axh_image = "gfx/vehicles/axh-special1.tga"; + AuxiliaryXhair[2].axh_scale = 0.5; + break; + + case HUD_WAKIZASHI: + AuxiliaryXhair[0].axh_image = "gfx/vehicles/axh-bracket.tga"; + AuxiliaryXhair[0].axh_scale = 0.25; + break; + + case HUD_RAPTOR: + AuxiliaryXhair[0].axh_image = "gfx/vehicles/axh-special2.tga"; + AuxiliaryXhair[0].axh_scale = 0.5; + //AuxiliaryXhair[0].alpha = 0.5; + + AuxiliaryXhair[1].axh_image = "gfx/vehicles/axh-bracket.tga"; + AuxiliaryXhair[1].axh_scale = 0.25; + //AuxiliaryXhair[1].alpha = 0.75; + //AuxiliaryXhair[1].axh_drawflag = DRAWFLAG_NORMAL; + break; + + case HUD_BUMBLEBEE: + // Plasma cannons + AuxiliaryXhair[0].axh_image = "gfx/vehicles/axh-ring.tga"; + AuxiliaryXhair[0].axh_scale = 0.25; + // Raygun + AuxiliaryXhair[1].axh_image = "gfx/vehicles/axh-special1.tga"; + AuxiliaryXhair[1].axh_scale = 0.25; + break; + } +} +#define HUD_GETSTATS \ + float vh_health = getstati(STAT_VEHICLESTAT_HEALTH); \ + float shield = getstati(STAT_VEHICLESTAT_SHIELD); \ + float energy = getstati(STAT_VEHICLESTAT_ENERGY); \ + float ammo1 = getstati(STAT_VEHICLESTAT_AMMO1); \ + float reload1 = getstati(STAT_VEHICLESTAT_RELOAD1); \ + float ammo2 = getstati(STAT_VEHICLESTAT_AMMO2); \ + float reload2 = getstati(STAT_VEHICLESTAT_RELOAD2); + +void CSQC_BUMBLE_HUD() +{ +} + + +#define spider_ico "gfx/vehicles/sbot.tga" +#define spider_rkt "gfx/vehicles/sbot_rpods.tga" +#define spider_mgun "gfx/vehicles/sbot_mguns.tga" +#define spider_xhair "gfx/vehicles/axh-special1.tga" +float alarm1time; +float alarm2time; + +void CSQC_SPIDER_HUD() +{ + if(autocvar_r_letterbox) + return; + + vector picsize, hudloc, pic2size, picloc; + float i; + + // Fetch health & ammo stats + HUD_GETSTATS + + picsize = draw_getimagesize(hud_bg) * autocvar_cl_vehicles_hudscale; + hudloc_y = vid_conheight - picsize_y; + hudloc_x = vid_conwidth * 0.5 - picsize_x * 0.5; + + drawpic(hudloc, hud_bg, picsize, '1 1 1', autocvar_cl_vehicles_hudalpha, DRAWFLAG_NORMAL); + + //drawstring(hudloc + '145 19 0', strcat(ftos(vh_health), "%"),'15 15 0','0 1 0', 1, DRAWFLAG_NORMAL); + //drawstring(hudloc + '175 34 0', strcat(ftos(shield), "%"),'15 15 0','0 0 1', 1, DRAWFLAG_NORMAL); + //drawstring(hudloc + '136 102 0', strcat(ftos(ammo1), "%"),'14 14 0','1 1 0', 1, DRAWFLAG_NORMAL); + //drawstring(hudloc + '179 69 0', strcat(ftos(9 - ammo2), " / 8"),'14 14 0','1 1 0', 1, DRAWFLAG_NORMAL); + + ammo1 *= 0.01; + shield *= 0.01; + vh_health *= 0.01; + reload2 *= 0.01; + + pic2size = draw_getimagesize(spider_ico) * (autocvar_cl_vehicles_hudscale * 0.8); + picloc = picsize * 0.5 - pic2size * 0.5; + if(vh_health < 0.25) + drawpic(hudloc + picloc, spider_ico, pic2size, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL); + else + drawpic(hudloc + picloc, spider_ico, pic2size, '1 1 1' * vh_health + '1 0 0' * (1 - vh_health), 1, DRAWFLAG_NORMAL); + drawpic(hudloc + picloc, spider_rkt, pic2size, '1 1 1' * reload2 + '1 0 0' * (1 - reload2), 1, DRAWFLAG_NORMAL); + drawpic(hudloc + picloc, spider_mgun, pic2size, '1 1 1' * ammo1 + '1 0 0' * (1 - ammo1), 1, DRAWFLAG_NORMAL); + drawpic(hudloc + picloc, hud_sh, pic2size, '1 1 1', shield, DRAWFLAG_NORMAL); + +// Health bar + picsize = draw_getimagesize(hud_hp_bar) * autocvar_cl_vehicles_hudscale; + picloc = '69 69 0' * autocvar_cl_vehicles_hudscale; + drawsetcliparea(hudloc_x + picloc_x + (picsize_x * (1 - vh_health)), 0, vid_conwidth, vid_conheight); + drawpic(hudloc + picloc, hud_hp_bar, picsize, '1 1 1', 1 , DRAWFLAG_NORMAL); + drawresetcliparea(); +// .. and icon + picsize = draw_getimagesize(hud_hp_ico) * autocvar_cl_vehicles_hudscale; + picloc = '37 65 0' * autocvar_cl_vehicles_hudscale; + if(vh_health < 0.25) + { + if(alarm1time < time) + { + alarm1time = time + 2; + sound(self, CH_PAIN_SINGLE, "vehicles/alarm.wav", VOL_BASEVOICE, ATTN_NONE); + } + drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL); + } + else + { + drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); + if(alarm1time) + { + sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTN_NONE); + alarm1time = 0; + } + } +// Shield bar + picsize = draw_getimagesize(hud_sh_bar) * autocvar_cl_vehicles_hudscale; + picloc = '69 140 0' * autocvar_cl_vehicles_hudscale; + drawsetcliparea(hudloc_x + picloc_x + (picsize_x * (1 - shield)), 0, vid_conwidth, vid_conheight); + drawpic(hudloc + picloc, hud_sh_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); + drawresetcliparea(); +// .. and icon + picloc = '40 136 0' * autocvar_cl_vehicles_hudscale; + picsize = draw_getimagesize(hud_sh_ico) * autocvar_cl_vehicles_hudscale; + if(shield < 0.25) + { + if(alarm2time < time) + { + alarm2time = time + 1; + sound(self, CH_TRIGGER_SINGLE, "vehicles/alarm_shield.wav", VOL_BASEVOICE, ATTN_NONE); + } + drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL); + } + else + { + drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); + if(alarm2time) + { + sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTN_NONE); + alarm2time = 0; + } + } + + +// Minigun bar + picsize = draw_getimagesize(hud_ammo1_bar) * autocvar_cl_vehicles_hudscale; + picloc = '450 69 0' * autocvar_cl_vehicles_hudscale; + drawsetcliparea(hudloc_x + picloc_x, picloc_y, picsize_x * ammo1, vid_conheight); + drawpic(hudloc + picloc, hud_ammo1_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); + drawresetcliparea(); +// .. and icon + picsize = draw_getimagesize(hud_ammo1_ico) * autocvar_cl_vehicles_hudscale; + picloc = '664 60 0' * autocvar_cl_vehicles_hudscale; + if(ammo1 < 0.2) + drawpic(hudloc + picloc, hud_ammo1_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL); + else + drawpic(hudloc + picloc, hud_ammo1_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); + +// Rocket ammo bar + picsize = draw_getimagesize(hud_ammo2_bar) * autocvar_cl_vehicles_hudscale; + ammo1 = picsize_x / 8; + picloc = '450 140 0' * autocvar_cl_vehicles_hudscale; + drawsetcliparea(hudloc_x + picloc_x, hudloc_y + picloc_y, picsize_x * reload2, vid_conheight); + drawpic(hudloc + picloc, hud_ammo2_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); + drawresetcliparea(); + +// .. and icons + pic2size = 0.35 * draw_getimagesize(hud_ammo2_ico) * autocvar_cl_vehicles_hudscale; + picloc_x -= pic2size_x; + picloc_y += pic2size_y * 2.25; + if(ammo2 == 9) + { + for(i = 1; i < 9; ++i) + { + picloc_x += ammo1; + drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, ((8 * reload2 <= i) ? '0 0 0' : '1 1 1'), 0.75, DRAWFLAG_NORMAL); + } + } + else + { + for(i = 1; i < 9; ++i) + { + picloc_x += ammo1; + drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, ((i >= ammo2) ? '1 1 1' : '0 0 0'), 0.75, DRAWFLAG_NORMAL); + } + } + pic2size = draw_getimagesize(hud_ammo2_ico) * autocvar_cl_vehicles_hudscale; + picloc = '664 130 0' * autocvar_cl_vehicles_hudscale; + if(ammo2 == 9) + drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL); + else + drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, '1 1 1', 1, DRAWFLAG_NORMAL); + + if (scoreboard_showscores) + HUD_DrawScoreboard(); + else + { + picsize = draw_getimagesize(spider_xhair); + picsize_x *= autocvar_cl_vehicle_spiderbot_cross_size; + picsize_y *= autocvar_cl_vehicle_spiderbot_cross_size; + + drawpic('0.5 0 0' * (vid_conwidth - picsize_x) + '0 0.5 0' * (vid_conheight - picsize_y), spider_xhair, picsize, '1 1 1', autocvar_cl_vehicle_spiderbot_cross_alpha, DRAWFLAG_ADDITIVE); + } +} + +#define raptor_ico "gfx/vehicles/raptor.tga" +#define raptor_gun "gfx/vehicles/raptor_guns.tga" +#define raptor_bomb "gfx/vehicles/raptor_bombs.tga" +#define raptor_drop "gfx/vehicles/axh-dropcross.tga" +#define raptor_xhair "gfx/vehicles/axh-ring.tga" +void CSQC_RAPTOR_HUD() +{ + if(autocvar_r_letterbox) + return; + + vector picsize, hudloc, pic2size, picloc; + + // Fetch health & ammo stats + HUD_GETSTATS + + picsize = draw_getimagesize(hud_bg) * autocvar_cl_vehicles_hudscale; + hudloc_y = vid_conheight - picsize_y; + hudloc_x = vid_conwidth * 0.5 - picsize_x * 0.5; + + drawpic(hudloc, hud_bg, picsize, '1 1 1', autocvar_cl_vehicles_hudalpha, DRAWFLAG_NORMAL); + + ammo1 *= 0.01; + ammo2 *= 0.01; + shield *= 0.01; + vh_health *= 0.01; + energy *= 0.01; + reload1 = reload2 * 0.01; + //reload2 *= 0.01; + + pic2size = draw_getimagesize(spider_ico) * (autocvar_cl_vehicles_hudscale * 0.8); + picloc = picsize * 0.5 - pic2size * 0.5; + if(vh_health < 0.25) + drawpic(hudloc + picloc, raptor_ico, pic2size, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL); + else + drawpic(hudloc + picloc, raptor_ico, pic2size, '1 1 1' * vh_health + '1 0 0' * (1 - vh_health), 1, DRAWFLAG_NORMAL); + drawpic(hudloc + picloc, raptor_bomb, pic2size, '1 1 1' * reload1 + '1 0 0' * (1 - reload1), 1, DRAWFLAG_NORMAL); + drawpic(hudloc + picloc, raptor_gun, pic2size, '1 1 1' * energy + '1 0 0' * (1 - energy), 1, DRAWFLAG_NORMAL); + drawpic(hudloc + picloc, hud_sh, pic2size, '1 1 1', shield, DRAWFLAG_NORMAL); + +// Health bar + picsize = draw_getimagesize(hud_hp_bar) * autocvar_cl_vehicles_hudscale; + picloc = '69 69 0' * autocvar_cl_vehicles_hudscale; + drawsetcliparea(hudloc_x + picloc_x + (picsize_x * (1 - vh_health)), 0, vid_conwidth, vid_conheight); + drawpic(hudloc + picloc, hud_hp_bar, picsize, '1 1 1', 1 , DRAWFLAG_NORMAL); + drawresetcliparea(); +// .. and icon + picsize = draw_getimagesize(hud_hp_ico) * autocvar_cl_vehicles_hudscale; + picloc = '37 65 0' * autocvar_cl_vehicles_hudscale; + if(vh_health < 0.25) + { + if(alarm1time < time) + { + alarm1time = time + 2; + sound(self, CH_PAIN_SINGLE, "vehicles/alarm.wav", VOL_BASEVOICE, ATTN_NONE); + } + + drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL); + } + else + { + drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); + if(alarm1time) + { + sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTN_NONE); + alarm1time = 0; + } + } + +// Shield bar + picsize = draw_getimagesize(hud_sh_bar) * autocvar_cl_vehicles_hudscale; + picloc = '69 140 0' * autocvar_cl_vehicles_hudscale; + drawsetcliparea(hudloc_x + picloc_x + (picsize_x * (1 - shield)), 0, vid_conwidth, vid_conheight); + drawpic(hudloc + picloc, hud_sh_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); + drawresetcliparea(); +// .. and icon + picloc = '40 136 0' * autocvar_cl_vehicles_hudscale; + picsize = draw_getimagesize(hud_sh_ico) * autocvar_cl_vehicles_hudscale; + if(shield < 0.25) + { + if(alarm2time < time) + { + alarm2time = time + 1; + sound(self, CH_TRIGGER_SINGLE, "vehicles/alarm_shield.wav", VOL_BASEVOICE, ATTN_NONE); + } + drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL); + } + else + { + drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); + if(alarm2time) + { + sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTN_NONE); + alarm2time = 0; + } + } + +// Gun bar + picsize = draw_getimagesize(hud_ammo1_bar) * autocvar_cl_vehicles_hudscale; + picloc = '450 69 0' * autocvar_cl_vehicles_hudscale; + drawsetcliparea(hudloc_x + picloc_x, picloc_y, picsize_x * energy, vid_conheight); + drawpic(hudloc + picloc, hud_ammo1_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); + drawresetcliparea(); +// .. and icon + picsize = draw_getimagesize(hud_ammo1_ico) * autocvar_cl_vehicles_hudscale; + picloc = '664 60 0' * autocvar_cl_vehicles_hudscale; + if(energy < 0.2) + drawpic(hudloc + picloc, hud_ammo1_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL); + else + drawpic(hudloc + picloc, hud_ammo1_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); + +// Bomb bar + picsize = draw_getimagesize(hud_ammo2_bar) * autocvar_cl_vehicles_hudscale; + picloc = '450 140 0' * autocvar_cl_vehicles_hudscale; + drawsetcliparea(hudloc_x + picloc_x, hudloc_y + picloc_y, picsize_x * reload1, vid_conheight); + drawpic(hudloc + picloc, hud_ammo2_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); + drawresetcliparea(); +// .. and icon + pic2size = draw_getimagesize(hud_ammo2_ico) * autocvar_cl_vehicles_hudscale; + picloc = '664 130 0' * autocvar_cl_vehicles_hudscale; + if(reload1 != 1) + drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL); + else + drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, '1 1 1', 1, DRAWFLAG_NORMAL); + +// Bombing crosshair + if(!dropmark) + { + dropmark = spawn(); + dropmark.owner = self; + dropmark.gravity = 1; + } + + if(reload2 == 100) + { + vector where; + + setorigin(dropmark, pmove_org); + dropmark.velocity = pmove_vel; + tracetoss(dropmark, self); + + where = project_3d_to_2d(trace_endpos); + + setorigin(dropmark, trace_endpos); + picsize = draw_getimagesize(raptor_drop) * 0.2; + + if not (where_z < 0 || where_x < 0 || where_y < 0 || where_x > vid_conwidth || where_y > vid_conheight) + { + where_x -= picsize_x * 0.5; + where_y -= picsize_y * 0.5; + where_z = 0; + drawpic(where, raptor_drop, picsize, '0 2 0', 1, DRAWFLAG_ADDITIVE); + } + dropmark.cnt = time + 5; + } + else + { + vector where; + if(dropmark.cnt > time) + { + where = project_3d_to_2d(dropmark.origin); + picsize = draw_getimagesize(raptor_drop) * 0.25; + + if not (where_z < 0 || where_x < 0 || where_y < 0 || where_x > vid_conwidth || where_y > vid_conheight) + { + where_x -= picsize_x * 0.5; + where_y -= picsize_y * 0.5; + where_z = 0; + drawpic(where, raptor_drop, picsize, '2 0 0', 1, DRAWFLAG_ADDITIVE); + } + } + } + + if (scoreboard_showscores) + HUD_DrawScoreboard(); + else + { + picsize = draw_getimagesize(raptor_xhair); + picsize_x *= 0.5; + picsize_y *= 0.5; + + drawpic('0.5 0 0' * (vid_conwidth - picsize_x) + '0 0.5 0' * (vid_conheight - picsize_y), raptor_xhair, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); + } +} + +#define waki_ico "gfx/vehicles/waki.tga" +#define waki_eng "gfx/vehicles/waki_e.tga" +#define waki_gun "gfx/vehicles/waki_guns.tga" +#define waki_rkt "gfx/vehicles/waki_rockets.tga" +#define waki_xhair "gfx/vehicles/axh-special1.tga" +void CSQC_WAKIZASHI_HUD() +{ +/* + drawpic(hudloc, waki_s, picsize, '1 1 1', shield, DRAWFLAG_NORMAL); + drawpic(hudloc, waki_b, picsize, '0 1 0' * health + '1 0 0' * (1 - health), 1, DRAWFLAG_NORMAL); + drawpic(hudloc, waki_r, picsize, '1 1 1' * reload1 + '1 0 0' * (1 - reload1), 1, DRAWFLAG_NORMAL); + drawpic(hudloc, waki_e, picsize, '1 1 1' * energy + '1 0 0' * (1 - energy), 1, DRAWFLAG_NORMAL); +*/ + if(autocvar_r_letterbox) + return; + + vector picsize, hudloc, pic2size, picloc; + + // Fetch health & ammo stats + HUD_GETSTATS + + picsize = draw_getimagesize(hud_bg) * autocvar_cl_vehicles_hudscale; + hudloc_y = vid_conheight - picsize_y; + hudloc_x = vid_conwidth * 0.5 - picsize_x * 0.5; + + drawpic(hudloc, hud_bg, picsize, '1 1 1', autocvar_cl_vehicles_hudalpha, DRAWFLAG_NORMAL); + + shield *= 0.01; + vh_health *= 0.01; + energy *= 0.01; + reload1 *= 0.01; + + pic2size = draw_getimagesize(spider_ico) * (autocvar_cl_vehicles_hudscale * 0.8); + picloc = picsize * 0.5 - pic2size * 0.5; + if(vh_health < 0.25) + drawpic(hudloc + picloc, waki_ico, pic2size, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL); + else + drawpic(hudloc + picloc, waki_ico, pic2size, '1 1 1' * vh_health + '1 0 0' * (1 - vh_health), 1, DRAWFLAG_NORMAL); + drawpic(hudloc + picloc, waki_eng, pic2size, '1 1 1' * energy + '1 0 0' * (1 - energy), 1, DRAWFLAG_NORMAL); + drawpic(hudloc + picloc, waki_gun, pic2size, '1 1 1' * energy + '1 0 0' * (1 - energy), 1, DRAWFLAG_NORMAL); + drawpic(hudloc + picloc, waki_rkt, pic2size, '1 1 1' * reload1 + '1 0 0' * (1 - reload1), 1, DRAWFLAG_NORMAL); + drawpic(hudloc + picloc, hud_sh, pic2size, '1 1 1', shield, DRAWFLAG_NORMAL); + +// Health bar + picsize = draw_getimagesize(hud_hp_bar) * autocvar_cl_vehicles_hudscale; + picloc = '69 69 0' * autocvar_cl_vehicles_hudscale; + drawsetcliparea(hudloc_x + picloc_x + (picsize_x * (1 - vh_health)), 0, vid_conwidth, vid_conheight); + drawpic(hudloc + picloc, hud_hp_bar, picsize, '1 1 1', 1 , DRAWFLAG_NORMAL); + drawresetcliparea(); +// .. and icon + picsize = draw_getimagesize(hud_hp_ico) * autocvar_cl_vehicles_hudscale; + picloc = '37 65 0' * autocvar_cl_vehicles_hudscale; + if(vh_health < 0.25) + { + if(alarm1time < time) + { + alarm1time = time + 2; + sound(self, CH_PAIN_SINGLE, "vehicles/alarm.wav", VOL_BASEVOICE, ATTN_NONE); + } + + drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL); + } + else + { + drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); + if(alarm1time) + { + sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTN_NONE); + alarm1time = 0; + } + } + + +// Shield bar + picsize = draw_getimagesize(hud_sh_bar) * autocvar_cl_vehicles_hudscale; + picloc = '69 140 0' * autocvar_cl_vehicles_hudscale; + drawsetcliparea(hudloc_x + picloc_x + (picsize_x * (1 - shield)), 0, vid_conwidth, vid_conheight); + drawpic(hudloc + picloc, hud_sh_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); + drawresetcliparea(); +// .. and icon + picloc = '40 136 0' * autocvar_cl_vehicles_hudscale; + picsize = draw_getimagesize(hud_sh_ico) * autocvar_cl_vehicles_hudscale; + if(shield < 0.25) + { + if(alarm2time < time) + { + alarm2time = time + 1; + sound(self, CH_TRIGGER_SINGLE, "vehicles/alarm_shield.wav", VOL_BASEVOICE, ATTN_NONE); + } + drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL); + } + else + { + drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); + if(alarm2time) + { + sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTN_NONE); + alarm2time = 0; + } + } + +// Gun bar + picsize = draw_getimagesize(hud_ammo1_bar) * autocvar_cl_vehicles_hudscale; + picloc = '450 69 0' * autocvar_cl_vehicles_hudscale; + drawsetcliparea(hudloc_x + picloc_x, picloc_y, picsize_x * energy, vid_conheight); + drawpic(hudloc + picloc, hud_ammo1_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); + drawresetcliparea(); +// .. and icon + picsize = draw_getimagesize(hud_ammo1_ico) * autocvar_cl_vehicles_hudscale; + picloc = '664 60 0' * autocvar_cl_vehicles_hudscale; + if(energy < 0.2) + drawpic(hudloc + picloc, hud_ammo1_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL); + else + drawpic(hudloc + picloc, hud_ammo1_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); + +// Bomb bar + picsize = draw_getimagesize(hud_ammo2_bar) * autocvar_cl_vehicles_hudscale; + picloc = '450 140 0' * autocvar_cl_vehicles_hudscale; + drawsetcliparea(hudloc_x + picloc_x, hudloc_y + picloc_y, picsize_x * reload1, vid_conheight); + drawpic(hudloc + picloc, hud_ammo2_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); + drawresetcliparea(); +// .. and icon + pic2size = draw_getimagesize(hud_ammo2_ico) * autocvar_cl_vehicles_hudscale; + picloc = '664 130 0' * autocvar_cl_vehicles_hudscale; + if(reload1 != 1) + drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL); + else + drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, '1 1 1', 1, DRAWFLAG_NORMAL); + + if (scoreboard_showscores) + HUD_DrawScoreboard(); + else + { + picsize = draw_getimagesize(waki_xhair); + picsize_x *= 0.5; + picsize_y *= 0.5; + + + drawpic('0.5 0 0' * (vid_conwidth - picsize_x) + '0 0.5 0' * (vid_conheight - picsize_y), waki_xhair, picsize, '1 1 1', 1, DRAWFLAG_NORMAL); + } +} + +void Vehicles_Precache() +{ +// fixme: HAAAAKKKZZZ!!!!!!!!!!!! (this belongs as a setting in default.cfg) + autocvar_cl_vehicles_hudscale = 0.5; + autocvar_cl_vehicles_hudalpha = 0.75; + + + precache_model("models/vehicles/wakizashi.dpm"); + + precache_model("models/vehicles/bomblet.md3"); + precache_model("models/vehicles/clusterbomb.md3"); + precache_model("models/vehicles/clusterbomb_fragment.md3"); + precache_model("models/vehicles/rocket01.md3"); + precache_model("models/vehicles/rocket02.md3"); + + precache_sound ("vehicles/alarm.wav"); + precache_sound ("vehicles/alarm_shield.wav"); +} + +void RaptorCBShellfragDraw() +{ + + Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy); + if(wasfreed(self)) + return; + + self.move_avelocity += randomvec() * 15; + self.renderflags = 0; + if(self.cnt < time) + self.alpha = bound(0, self.nextthink - time, 1); + + if(self.alpha < ALPHA_MIN_VISIBLE) + remove(self); +} + +void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang) +{ + entity sfrag; + + sfrag = spawn(); + setmodel(sfrag, "models/vehicles/clusterbomb_fragment.md3"); + setorigin(sfrag, _org); + + sfrag.move_movetype = MOVETYPE_BOUNCE; + sfrag.gravity = 0.15; + sfrag.solid = SOLID_CORPSE; + + sfrag.draw = RaptorCBShellfragDraw; + + sfrag.move_origin = sfrag.origin = _org; + sfrag.move_velocity = _vel; + sfrag.move_avelocity = prandomvec() * vlen(sfrag.move_velocity); + sfrag.angles = self.move_angles = _ang; + + sfrag.move_time = time; + sfrag.damageforcescale = 4; + + sfrag.nextthink = time + 3; + sfrag.cnt = time + 2; + sfrag.alpha = 1; + sfrag.drawmask = MASK_NORMAL; +} diff --git a/qcsrc/client/vehicles/vehicles.qh b/qcsrc/client/vehicles/vehicles.qh new file mode 100644 index 0000000000..66b2af1bf6 --- /dev/null +++ b/qcsrc/client/vehicles/vehicles.qh @@ -0,0 +1,4 @@ +void RaptorCBShellfragDraw(); +void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang); +void Vehicles_Precache(); + diff --git a/qcsrc/client/waypointsprites.qc b/qcsrc/client/waypointsprites.qc index 1a35579839..78ddc8b793 100644 --- a/qcsrc/client/waypointsprites.qc +++ b/qcsrc/client/waypointsprites.qc @@ -6,9 +6,14 @@ float waypointsprite_minalpha; float waypointsprite_distancealphaexponent; float waypointsprite_timealphaexponent; float waypointsprite_scale; +float waypointsprite_fontsize; float waypointsprite_edgefadealpha; float waypointsprite_edgefadescale; float waypointsprite_edgefadedistance; +float waypointsprite_edgeoffset_bottom; +float waypointsprite_edgeoffset_left; +float waypointsprite_edgeoffset_right; +float waypointsprite_edgeoffset_top; float waypointsprite_crosshairfadealpha; float waypointsprite_crosshairfadescale; float waypointsprite_crosshairfadedistance; @@ -17,6 +22,7 @@ float waypointsprite_distancefadescale; float waypointsprite_distancefadedistance; float waypointsprite_alpha; +.float helpme; .float rule; .string netname; // primary picture .string netname2; // secondary picture @@ -32,14 +38,14 @@ float waypointsprite_alpha; .float build_starthealth; .float build_finished; -vector SPRITE_SIZE = '288 36 0'; -vector SPRITE_HOTSPOT = '144 36 0'; float SPRITE_HEALTHBAR_WIDTH = 144; float SPRITE_HEALTHBAR_HEIGHT = 9; float SPRITE_HEALTHBAR_MARGIN = 6; float SPRITE_HEALTHBAR_BORDER = 2; float SPRITE_HEALTHBAR_BORDERALPHA = 1; float SPRITE_HEALTHBAR_HEALTHALPHA = 0.5; +float SPRITE_ARROW_SCALE = 1.0; +float SPRITE_HELPME_BLINK = 2; void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f) { @@ -106,6 +112,275 @@ void drawhealthbar(vector org, float rot, float h, vector sz, vector hotspot, fl drawquad(o + ri * (border + align * ((1 - h) * width)), ri * width * h, up * height, "", hrgb, ha, f); } +// returns location of sprite text +vector drawspritearrow(vector o, float ang, vector rgb, float a, float t) +{ + float SQRT2 = 1.414; + float BORDER; BORDER = 1.5 * t; + float TSIZE; TSIZE = 8 * t; + float RLENGTH; RLENGTH = 8 * t; + float RWIDTH; RWIDTH = 4 * t; + float MLENGTH; MLENGTH = 4 * t; + + R_BeginPolygon("", DRAWFLAG_NORMAL); + R_PolygonVertex(o + rotate(eX * -(TSIZE + BORDER * (1 + SQRT2)) + eY * (TSIZE + BORDER), ang), '0 0 0', '0 0 0', a); + R_PolygonVertex(o + rotate(eX * (TSIZE + BORDER * (1 + SQRT2)) + eY * (TSIZE + BORDER), ang), '0 0 0', '0 0 0', a); + R_PolygonVertex(o + rotate(eY * -( BORDER * SQRT2), ang), '0 0 0', '0 0 0', a); + R_EndPolygon(); + R_BeginPolygon("", DRAWFLAG_NORMAL); + R_PolygonVertex(o + rotate(eX * -(RWIDTH + BORDER) + eY * (TSIZE + BORDER), ang), '0 0 0', '0 0 0', a); + R_PolygonVertex(o + rotate(eX * -(RWIDTH + BORDER) + eY * (TSIZE + RLENGTH + BORDER), ang), '0 0 0', '0 0 0', a); + R_PolygonVertex(o + rotate(eX * (RWIDTH + BORDER) + eY * (TSIZE + RLENGTH + BORDER), ang), '0 0 0', '0 0 0', a); + R_PolygonVertex(o + rotate(eX * (RWIDTH + BORDER) + eY * (TSIZE + BORDER), ang), '0 0 0', '0 0 0', a); + R_EndPolygon(); + + R_BeginPolygon("", DRAWFLAG_ADDITIVE); + R_PolygonVertex(o + rotate(eX * -TSIZE + eY * TSIZE, ang), '0 0 0', rgb, a); + R_PolygonVertex(o + rotate(eX * TSIZE + eY * TSIZE, ang), '0 0 0', rgb, a); + R_PolygonVertex(o + rotate('0 0 0', ang), '0 0 0', rgb, a); + R_EndPolygon(); + R_BeginPolygon("", DRAWFLAG_ADDITIVE); + R_PolygonVertex(o + rotate(eX * -RWIDTH + eY * TSIZE, ang), '0 0 0', rgb, a); + R_PolygonVertex(o + rotate(eX * -RWIDTH + eY * (TSIZE + RLENGTH), ang), '0 0 0', rgb, a); + R_PolygonVertex(o + rotate(eX * RWIDTH + eY * (TSIZE + RLENGTH), ang), '0 0 0', rgb, a); + R_PolygonVertex(o + rotate(eX * RWIDTH + eY * TSIZE, ang), '0 0 0', rgb, a); + R_EndPolygon(); + + return + o + rotate(eY * (TSIZE + RLENGTH + MLENGTH), ang); +} + +// returns location of sprite healthbar +vector drawspritetext(vector o, float ang, float minwidth, vector rgb, float a, vector fontsize, string s) +{ + float algnx, algny; + float sw, w, h; + float aspect, sa, ca; + + sw = stringwidth(s, FALSE, fontsize); + if(sw > minwidth) + w = sw; + else + w = minwidth; + h = fontsize_y; + + // how do corners work? + aspect = vid_conwidth / vid_conheight; + sa = sin(ang); + ca = cos(ang) * aspect; + if(fabs(sa) > fabs(ca)) + { + algnx = (sa < 0); + algny = 0.5 - 0.5 * ca / fabs(sa); + } + else + { + algnx = 0.5 - 0.5 * sa / fabs(ca); + algny = (ca < 0); + } + + // align + o_x -= w * algnx; + o_y -= h * algny; + + // we want to be onscreen + if(o_x < 0) + o_x = 0; + if(o_y < 0) + o_y = 0; + if(o_x > vid_conwidth - w) + o_x = vid_conwidth - w; + if(o_y > vid_conheight - h) + o_x = vid_conheight - h; + + o_x += 0.5 * (w - sw); + + drawstring(o, s, fontsize, rgb, a, DRAWFLAG_NORMAL); + + o_x += 0.5 * sw; + o_y += 0.5 * h; + + return o; +} + +float spritelookupblinkvalue(string s) +{ + switch(s) + { + case "ons-cp-atck-neut": return 2; + case "ons-cp-atck-red": return 2; + case "ons-cp-atck-blue": return 2; + case "ons-cp-dfnd-red": return 0.5; + case "ons-cp-dfnd-blue": return 0.5; + case "item-invis": return 2; + case "item-extralife": return 2; + case "item-speed": return 2; + case "item-strength": return 2; + case "item-shield": return 2; + case "item-fuelregen": return 2; + case "item-jetpack": return 2; + case "tagged-target": return 2; + default: return 1; + } +} +vector spritelookupcolor(string s, vector def) +{ + switch(s) + { + case "keycarrier-friend": return '0 1 0'; + case "wpn-laser": return '1 0.5 0.5'; + case "wpn-shotgun": return '0.5 0.25 0'; + case "wpn-uzi": return '1 1 0'; + case "wpn-gl": return '1 0 0'; + case "wpn-electro": return '0 0.5 1'; + case "wpn-crylink": return '1 0.5 1'; + case "wpn-nex": return '0.5 1 1'; + case "wpn-hagar": return '1 1 0.5'; + case "wpn-rl": return '1 1 0'; + case "wpn-porto": return '0.5 0.5 0.5'; + case "wpn-minstanex": return '0.5 1 1'; + case "wpn-hookgun": return '0 0.5 0'; + case "wpn-fireball": return '1 0.5 0'; + case "wpn-hlac": return '0 1 0'; + case "wpn-campingrifle": return '0.5 1 0'; + case "wpn-minelayer": return '0.75 1 0'; + default: return def; + } +} +string spritelookuptext(string s) +{ + switch(s) + { + case "as-push": return _("Push"); + case "as-destroy": return _("Destroy"); + case "as-defend": return _("Defend"); + case "bluebase": return _("Blue base"); + case "danger": return _("DANGER"); + case "flagcarrier": return _("Flag carrier"); + case "flagdropped": return _("Dropped flag"); + case "helpme": return _("Help me!"); + case "here": return _("Here"); + case "key-dropped": return _("Dropped key"); + case "keycarrier-blue": return _("Key carrier"); + case "keycarrier-finish": return _("Run here"); + case "keycarrier-friend": return _("Key carrier"); + case "keycarrier-pink": return _("Key carrier"); + case "keycarrier-red": return _("Key carrier"); + case "keycarrier-yellow": return _("Key carrier"); + case "redbase": return _("Red base"); + case "waypoint": return _("Waypoint"); + case "ons-gen-red": return _("Generator"); + case "ons-gen-blue": return _("Generator"); + case "ons-gen-shielded": return _("Generator"); + case "ons-cp-neut": return _("Control point"); + case "ons-cp-red": return _("Control point"); + case "ons-cp-blue": return _("Control point"); + case "ons-cp-atck-neut": return _("Control point"); + case "ons-cp-atck-red": return _("Control point"); + case "ons-cp-atck-blue": return _("Control point"); + case "ons-cp-dfnd-red": return _("Control point"); + case "ons-cp-dfnd-blue": return _("Control point"); + case "race-checkpoint": return _("Checkpoint"); + case "race-finish": return _("Finish"); + case "race-start": return _("Start"); + case "race-start-finish": return (race_checkpointtime || race_mycheckpointtime) ? _("Finish") : _("Start"); + case "nb-ball": return _("Ball"); + case "ka-ball": return _("Ball"); + case "ka-ballcarrier": return _("Ball carrier"); + case "wpn-laser": return _("Laser"); + case "wpn-shotgun": return _("Shotgun"); + case "wpn-uzi": return _("Machine Gun"); + case "wpn-gl": return _("Mortar"); + case "wpn-electro": return _("Electro"); + case "wpn-crylink": return _("Crylink"); + case "wpn-nex": return _("Nex"); + case "wpn-hagar": return _("Hagar"); + case "wpn-rl": return _("Rocket Launcher"); + case "wpn-porto": return _("Port-O-Launch"); + case "wpn-minstanex": return _("Minstanex"); + case "wpn-hookgun": return _("Hook"); + case "wpn-fireball": return _("Fireball"); + case "wpn-hlac": return _("HLAC"); + case "wpn-campingrifle": return _("Rifle"); + case "wpn-minelayer": return _("Mine Layer"); + case "dom-neut": return _("Control point"); + case "dom-red": return _("Control point"); + case "dom-blue": return _("Control point"); + case "dom-yellow": return _("Control point"); + case "dom-pink": return _("Control point"); + case "item-invis": return _("Invisibility"); + case "item-extralife": return _("Extra life"); + case "item-speed": return _("Speed"); + case "item-strength": return _("Strength"); + case "item-shield": return _("Shield"); + case "item-fuelregen": return _("Fuel regen"); + case "item-jetpack": return _("Jet Pack"); + case "freezetag_frozen": return _("Frozen!"); + case "tagged-target": return _("Tagged"); + case "vehicle": return _("Vehicle"); + default: return s; + } +} + +vector fixrgbexcess_move(vector rgb, vector src, vector dst) +{ + vector yvec = '0.299 0.587 0.114'; + return rgb + dst * ((src * yvec) / (dst * yvec)) * ((rgb - '1 1 1') * src); +} +vector fixrgbexcess(vector rgb) +{ + if(rgb_x > 1) + { + rgb = fixrgbexcess_move(rgb, '1 0 0', '0 1 1'); + if(rgb_y > 1) + { + rgb = fixrgbexcess_move(rgb, '0 1 0', '0 0 1'); + if(rgb_z > 1) + rgb_z = 1; + } + else if(rgb_z > 1) + { + rgb = fixrgbexcess_move(rgb, '0 0 1', '0 1 0'); + if(rgb_y > 1) + rgb_y = 1; + } + } + else if(rgb_y > 1) + { + rgb = fixrgbexcess_move(rgb, '0 1 0', '1 0 1'); + if(rgb_x > 1) + { + rgb = fixrgbexcess_move(rgb, '1 0 0', '0 0 1'); + if(rgb_z > 1) + rgb_z = 1; + } + else if(rgb_z > 1) + { + rgb = fixrgbexcess_move(rgb, '0 0 1', '1 0 0'); + if(rgb_x > 1) + rgb_x = 1; + } + } + else if(rgb_z > 1) + { + rgb = fixrgbexcess_move(rgb, '0 0 1', '1 1 0'); + if(rgb_x > 1) + { + rgb = fixrgbexcess_move(rgb, '1 0 0', '0 1 0'); + if(rgb_y > 1) + rgb_y = 1; + } + else if(rgb_y > 1) + { + rgb = fixrgbexcess_move(rgb, '0 1 0', '1 0 0'); + if(rgb_x > 1) + rgb_x = 1; + } + } + return rgb; +} + +float waypointsprite_count, waypointsprite_newcount; void Draw_WaypointSprite() { string spriteimage; @@ -128,7 +403,7 @@ void Draw_WaypointSprite() InterpolateOrigin_Do(); - t = GetPlayerColor(player_localentnum - 1) + 1; + t = GetPlayerColor(player_localnum) + 1; spriteimage = ""; @@ -161,6 +436,8 @@ void Draw_WaypointSprite() if(spriteimage == "") return; + + ++waypointsprite_newcount; float dist; dist = vlen(self.origin - view_origin); @@ -173,34 +450,52 @@ void Draw_WaypointSprite() else if(self.maxdistance > 0) a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha; + vector rgb; + rgb = self.teamradar_color; + rgb = spritelookupcolor(spriteimage, rgb); + if(rgb == '0 0 0') + { + self.teamradar_color = '1 0 1'; + print(sprintf("WARNING: sprite of name %s has no color, using pink so you notice it\n", spriteimage)); + } + + if(time - floor(time) > 0.5) + { + if(self.helpme && time < self.helpme) + a *= SPRITE_HELPME_BLINK; + else + a *= spritelookupblinkvalue(spriteimage); + } + + if(a > 1) + { + rgb *= a; + a = 1; + } + if(a <= 0) return; - - // draw the sprite image + + rgb = fixrgbexcess(rgb); + vector o; - float rot; - o = project_3d_to_2d(self.origin); - rot = 0; + float ang; - if(o_z < 0 || o_x < 0 || o_y < 0 || o_x > vid_conwidth || o_y > vid_conheight) + o = project_3d_to_2d(self.origin); + if(o_z < 0 + || o_x < (vid_conwidth * waypointsprite_edgeoffset_left) + || o_y < (vid_conheight * waypointsprite_edgeoffset_top) + || o_x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right)) + || o_y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom))) { // scale it to be just in view vector d; float f1, f2; - // get the waypoint angle vector - /* - d_x = view_right * (self.origin - view_origin) * vid_conwidth / vid_width; - d_y = -view_up * (self.origin - view_origin) * vid_conheight / (vid_height * vid_pixelheight); - d_z = 0; - */ - d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight; - - /* - if(autocvar_v_flipped) - d_x = -d_x; - */ + ang = atan2(-d_x, -d_y); + if(o_z < 0) + ang += M_PI; f1 = d_x / vid_conwidth; f2 = d_y / vid_conheight; @@ -210,14 +505,12 @@ void Draw_WaypointSprite() if(d_z * f1 > 0) { // RIGHT edge - d = d * (0.5 / f1); - rot = 3; + d = d * ((0.5 - waypointsprite_edgeoffset_right) / f1); } else { // LEFT edge - d = d * (-0.5 / f1); - rot = 1; + d = d * (-(0.5 - waypointsprite_edgeoffset_left) / f1); } } else @@ -225,33 +518,38 @@ void Draw_WaypointSprite() if(d_z * f2 > 0) { // BOTTOM edge - d = d * (0.5 / f2); - rot = 0; + d = d * ((0.5 - waypointsprite_edgeoffset_bottom) / f2); } else { // TOP edge - d = d * (-0.5 / f2); - rot = 2; + d = d * (-(0.5 - waypointsprite_edgeoffset_top) / f2); } } o = d + '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight; } + else + { +#if 1 + ang = M_PI; +#else + vector d; + d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight; + ang = atan2(-d_x, -d_y); +#endif + } o_z = 0; + float edgedistance_min, crosshairdistance; + edgedistance_min = min((o_y - (vid_conheight * waypointsprite_edgeoffset_top)), + (o_x - (vid_conwidth * waypointsprite_edgeoffset_left)), + (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right)) - o_x, + (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)) - o_y); + float vidscale; vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height); - t = stof(db_get(tempdb, strcat("/spriteframes/", spriteimage))); - if(t == 0) - spriteimage = strcat("models/sprites/", spriteimage); - else - spriteimage = strcat("models/sprites/", spriteimage, "_frame", ftos(mod(floor((max(0, time - self.spawntime)) * 2), t))); - - float edgedistance_min, crosshairdistance; - edgedistance_min = min4(o_y, o_x,vid_conwidth - o_x, vid_conheight - o_y); - crosshairdistance = sqrt( pow(o_x - vid_conwidth/2, 2) + pow(o_y - vid_conheight/2, 2) ); t = waypointsprite_scale * vidscale; @@ -269,7 +567,6 @@ void Draw_WaypointSprite() a = a * (1 - (1 - waypointsprite_crosshairfadealpha) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1))); t = t * (1 - (1 - waypointsprite_crosshairfadescale) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1))); } - drawrotpic(o, rot * 90 * DEG2RAD, spriteimage, SPRITE_SIZE * t, SPRITE_HOTSPOT * t, '1 1 1', a, DRAWFLAG_MIPMAP); if(self.build_finished) { @@ -286,14 +583,52 @@ void Draw_WaypointSprite() self.health = -1; } + o = drawspritearrow(o, ang, rgb, a, SPRITE_ARROW_SCALE * t); + + string txt; + if(autocvar_g_waypointsprite_spam && waypointsprite_count >= autocvar_g_waypointsprite_spam) + txt = _("Spam"); + else + txt = spritelookuptext(spriteimage); + if(self.helpme && time < self.helpme) + txt = sprintf(_("%s needing help!"), txt); + if(autocvar_g_waypointsprite_uppercase) + txt = strtoupper(txt); + if(self.health >= 0) { - float align; + o = drawspritetext(o, ang, (SPRITE_HEALTHBAR_WIDTH + 2 * SPRITE_HEALTHBAR_BORDER) * t, rgb, a, waypointsprite_fontsize * '1 1 0', txt); + + float align, marg; if(self.build_finished) align = 0.5; else align = 0; - drawhealthbar(o, rot * 90 * DEG2RAD, self.health, SPRITE_SIZE * t, SPRITE_HOTSPOT * t, SPRITE_HEALTHBAR_WIDTH * t, SPRITE_HEALTHBAR_HEIGHT * t, SPRITE_HEALTHBAR_MARGIN * t, SPRITE_HEALTHBAR_BORDER * t, align, self.teamradar_color, a * SPRITE_HEALTHBAR_BORDERALPHA, self.teamradar_color, a * SPRITE_HEALTHBAR_HEALTHALPHA, DRAWFLAG_NORMAL); + if(cos(ang) > 0) + marg = -(SPRITE_HEALTHBAR_MARGIN + SPRITE_HEALTHBAR_HEIGHT + 2 * SPRITE_HEALTHBAR_BORDER) * t - 0.5 * waypointsprite_fontsize; + else + marg = SPRITE_HEALTHBAR_MARGIN * t + 0.5 * waypointsprite_fontsize; + drawhealthbar( + o, + 0, + self.health, + '0 0 0', + '0 0 0', + SPRITE_HEALTHBAR_WIDTH * t, + SPRITE_HEALTHBAR_HEIGHT * t, + marg, + SPRITE_HEALTHBAR_BORDER * t, + align, + rgb, + a * SPRITE_HEALTHBAR_BORDERALPHA, + rgb, + a * SPRITE_HEALTHBAR_HEALTHALPHA, + DRAWFLAG_NORMAL + ); + } + else + { + o = drawspritetext(o, ang, 0, rgb, a, waypointsprite_fontsize * '1 1 0', txt); } } @@ -336,7 +671,6 @@ void Ent_WaypointSprite() else self.build_starthealth = 0; self.build_finished = servertime + t / 32; - //print("build: ", ftos(self.build_finished - self.build_started), "\n"); } } else @@ -400,6 +734,9 @@ void Ent_WaypointSprite() self.teamradar_color_x = ReadByte() / 255.0; self.teamradar_color_y = ReadByte() / 255.0; self.teamradar_color_z = ReadByte() / 255.0; + self.helpme = ReadByte() * 0.1; + if(self.helpme > 0) + self.helpme += servertime; } InterpolateOrigin_Note(); @@ -407,6 +744,29 @@ void Ent_WaypointSprite() self.entremove = Ent_RemoveWaypointSprite; } +void WaypointSprite_Load_Frames(string ext) +{ + float dh, n, i, o, f; + string s, sname, sframes; + dh = search_begin(strcat("models/sprites/*_frame*", ext), FALSE, FALSE); + if (dh < 0) + return; + float ext_len = strlen(ext); + n = search_getsize(dh); + for(i = 0; i < n; ++i) + { + s = search_getfilename(dh, i); + s = substring(s, 15, strlen(s) - 15 - ext_len); // strip models/sprites/ and extension + + o = strstrofs(s, "_frame", 0); + sname = strcat("/spriteframes/", substring(s, 0, o)); + sframes = substring(s, o + 6, strlen(s) - o - 6); + f = stof(sframes) + 1; + db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname))))); + } + search_end(dh); +} + void WaypointSprite_Load() { waypointsprite_fadedistance = vlen(mi_scale); @@ -416,9 +776,14 @@ void WaypointSprite_Load() waypointsprite_distancealphaexponent = autocvar_g_waypointsprite_distancealphaexponent; waypointsprite_timealphaexponent = autocvar_g_waypointsprite_timealphaexponent; waypointsprite_scale = autocvar_g_waypointsprite_scale; + waypointsprite_fontsize = autocvar_g_waypointsprite_fontsize; waypointsprite_edgefadealpha = autocvar_g_waypointsprite_edgefadealpha; waypointsprite_edgefadescale = autocvar_g_waypointsprite_edgefadescale; waypointsprite_edgefadedistance = autocvar_g_waypointsprite_edgefadedistance; + waypointsprite_edgeoffset_bottom = autocvar_g_waypointsprite_edgeoffset_bottom; + waypointsprite_edgeoffset_left = autocvar_g_waypointsprite_edgeoffset_left; + waypointsprite_edgeoffset_right = autocvar_g_waypointsprite_edgeoffset_right; + waypointsprite_edgeoffset_top = autocvar_g_waypointsprite_edgeoffset_top; waypointsprite_crosshairfadealpha = autocvar_g_waypointsprite_crosshairfadealpha; waypointsprite_crosshairfadescale = autocvar_g_waypointsprite_crosshairfadescale; waypointsprite_crosshairfadedistance = autocvar_g_waypointsprite_crosshairfadedistance; @@ -429,38 +794,11 @@ void WaypointSprite_Load() if(!waypointsprite_initialized) { - float dh, n, i, o, f; - string s, sname, sframes; - - dh = search_begin("models/sprites/*_frame*.tga", FALSE, FALSE); - n = search_getsize(dh); - for(i = 0; i < n; ++i) - { - s = search_getfilename(dh, i); - s = substring(s, 15, strlen(s) - 15 - 4); // strip models/sprites/ and .tga - - o = strstrofs(s, "_frame", 0); - sname = strcat("/spriteframes/", substring(s, 0, o)); - sframes = substring(s, o + 6, strlen(s) - o - 6); - f = stof(sframes) + 1; - db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname))))); - } - search_end(dh); - - dh = search_begin("models/sprites/*_frame*.jpg", FALSE, FALSE); - n = search_getsize(dh); - for(i = 0; i < n; ++i) - { - s = search_getfilename(dh, i); - s = substring(s, 15, strlen(s) - 15 - 4); // strip models/sprites/ and .jpg - - o = strstrofs(s, "_frame", 0); - sname = strcat("/spriteframes/", substring(s, 0, o)); - sframes = substring(s, o + 6, strlen(s) - o - 6); - f = stof(sframes) + 1; - db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname))))); - } - search_end(dh); + WaypointSprite_Load_Frames(".tga"); + WaypointSprite_Load_Frames(".jpg"); waypointsprite_initialized = true; } + + waypointsprite_count = waypointsprite_newcount; + waypointsprite_newcount = 0; } diff --git a/qcsrc/common/campaign_file.qc b/qcsrc/common/campaign_file.qc index 08cec80928..067cd8054d 100644 --- a/qcsrc/common/campaign_file.qc +++ b/qcsrc/common/campaign_file.qc @@ -18,7 +18,7 @@ float CampaignFile_Load(float offset, float n) campaign_entries = 0; campaign_title = string_null; - fn = strcat("maps/campaign", campaign_name, ".txt"); + fn = language_filename(strcat("maps/campaign", campaign_name, ".txt")); fh = fopen(fn, FILE_READ); if(fh >= 0) { diff --git a/qcsrc/common/campaign_setup.qc b/qcsrc/common/campaign_setup.qc index 3aae078adb..525b2856d4 100644 --- a/qcsrc/common/campaign_setup.qc +++ b/qcsrc/common/campaign_setup.qc @@ -8,5 +8,5 @@ void CampaignSetup(float n) localcmd(ftos(campaign_offset + n)); localcmd("\n"); localcmd("disconnect\nmaxplayers 16\n"); - MapInfo_LoadMap(campaign_mapname[n]); + MapInfo_LoadMap(campaign_mapname[n], 1); } diff --git a/qcsrc/common/command/generic.qc b/qcsrc/common/command/generic.qc new file mode 100644 index 0000000000..8cf7f5aa52 --- /dev/null +++ b/qcsrc/common/command/generic.qc @@ -0,0 +1,492 @@ +// ========================================================= +// Generic program common command code, written by Samual +// Last updated: December 28th, 2011 +// ========================================================= + +// used by generic commands for better help/usage information +string GetProgramCommandPrefix(void) +{ + #ifdef SVQC + return "sv_cmd"; + #endif + #ifdef CSQC + return "cl_cmd"; + #endif + #ifdef MENUQC + return "menu_cmd"; + #endif +} + + +// ======================= +// Command Sub-Functions +// ======================= + +void GenericCommand_addtolist(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + float i; + + if(argc >= 2) + { + string original_cvar = argv(1); + string tmp_string = argv(2); + + if(cvar_string(original_cvar) == "") // cvar was empty + { + cvar_set(original_cvar, tmp_string); + } + else // add it to the end of the list if the list doesn't already have it + { + argc = tokenizebyseparator(cvar_string(original_cvar), " "); + + for(i = 0; i < argc; ++i) + if(argv(i) == tmp_string) + return; // already in list + + cvar_set(original_cvar, strcat(tmp_string, " ", cvar_string(original_cvar))); + } + return; + } + } + + default: + print("Incorrect parameters for ^2addtolist^7\n"); + case CMD_REQUEST_USAGE: + { + print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " addtolist variable value")); + print(" Where 'variable' is what to add 'value' to.\n"); + print("See also: ^2removefromlist^7\n"); + return; + } + } +} + +void GenericCommand_dumpcommands(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + float fh; + string filename = strcat(GetProgramCommandPrefix(), "_dump.txt"); + fh = fopen(filename, FILE_WRITE); + + if(fh >= 0) + { + #ifdef SVQC + CMD_Write("dump of server console commands:\n"); + GameCommand_macro_write_aliases(fh); + + CMD_Write("\ndump of networked client only commands:\n"); + ClientCommand_macro_write_aliases(fh); + + CMD_Write("\ndump of common commands:\n"); + CommonCommand_macro_write_aliases(fh); + + CMD_Write("\ndump of ban commands:\n"); + BanCommand_macro_write_aliases(fh); + #endif + + #ifdef CSQC + CMD_Write("dump of client commands:\n"); + LocalCommand_macro_write_aliases(fh); + #endif + + CMD_Write("\ndump of generic commands:\n"); + GenericCommand_macro_write_aliases(fh); + + print("Completed dump of aliases in ^2data/data/", GetProgramCommandPrefix(), "_dump.txt^7.\n"); + + fclose(fh); + } + else + { + print("^1Error: ^7Could not dump to file!\n"); + } + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " dumpcommands")); + print(" No arguments required.\n"); + return; + } + } +} + +void GenericCommand_maplist(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + string tmp_string; + float i; + + switch(argv(1)) + { + case "add": // appends new maps to the maplist + { + if(argc == 3) + { + if (!fexists(strcat("maps/", argv(2), ".bsp"))) + { + print("maplist: ERROR: ", argv(2), " does not exist!\n"); + break; + } + + if(cvar_string("g_maplist") == "") + cvar_set("g_maplist", argv(2)); + else + cvar_set("g_maplist", strcat(argv(2), " ", cvar_string("g_maplist"))); + + return; + } + break; // go to usage + } + + case "cleanup": // scans maplist and only adds back the ones which are really usable + { + MapInfo_Enumerate(); + MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0); + argc = tokenizebyseparator(cvar_string("g_maplist"), " "); + + for(i = 0; i < argc; ++i) + if(MapInfo_CheckMap(argv(i))) + tmp_string = strcat(tmp_string, " ", argv(i)); + + tmp_string = substring(tmp_string, 1, strlen(tmp_string) - 1); + cvar_set("g_maplist", tmp_string); + + return; + } + + case "remove": // scans maplist and only adds back whatever maps were not provided in argv(2) + { + if(argc == 3) + { + argc = tokenizebyseparator(cvar_string("g_maplist"), " "); + + for(i = 0; i < argc; ++i) + if(argv(i) != argv(2)) + tmp_string = strcat(tmp_string, " ", argv(i)); + + tmp_string = substring(tmp_string, 1, strlen(tmp_string) - 1); + cvar_set("g_maplist", tmp_string); + + return; + } + break; // go to usage + } + + case "shuffle": // randomly shuffle the maplist + { + cvar_set("g_maplist", shufflewords(cvar_string("g_maplist"))); + return; + } + + default: break; + } + } + + default: + print("Incorrect parameters for ^2maplist^7\n"); + case CMD_REQUEST_USAGE: + { + print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " maplist action [map]")); + print(" Where 'action' is the command to complete,\n"); + print(" and 'map' is what it acts upon (if required).\n"); + print(" Full list of commands here: \"add, cleanup, remove, shuffle.\"\n"); + return; + } + } +} + +void GenericCommand_removefromlist(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argc == 3) + { + float i; + string original_cvar = argv(1); + string removal = argv(2); + string tmp_string; + + argc = tokenizebyseparator(cvar_string(original_cvar), " "); + + for(i = 0; i < argc; ++i) + if(argv(i) != removal) + tmp_string = strcat(tmp_string, " ", argv(i)); + + tmp_string = substring(tmp_string, 1, strlen(tmp_string) - 1); + cvar_set(original_cvar, tmp_string); + + return; + } + } + + default: + print("Incorrect parameters for ^2removefromlist^7\n"); + case CMD_REQUEST_USAGE: + { + print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " removefromlist variable value")); + print(" Where 'variable' is what cvar to remove 'value' from.\n"); + print("See also: ^2addtolist^7\n"); + return; + } + } +} + +void GenericCommand_settemp(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argc >= 3) + { + if(cvar_settemp(argv(1), argv(2))) + dprint("Creating new settemp tracker for ", argv(1), " and setting it to \"", argv(2), "\" temporarily.\n"); + else + dprint("Already had a tracker for ", argv(1), ", updating it to \"", argv(2), "\".\n"); + + return; + } + } + + default: + print("Incorrect parameters for ^2settemp^7\n"); + case CMD_REQUEST_USAGE: + { + print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " settemp \"cvar\" \"arguments\"\n")); + print(" Where 'cvar' is the cvar you want to temporarily set with 'arguments'.\n"); + print("See also: ^2settemp_restore^7\n"); + return; + } + } +} + +void GenericCommand_settemp_restore(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + float i = cvar_settemp_restore(); + + if(i) + dprint("Restored ", ftos(i), " temporary cvar settings to their original values.\n"); + else + dprint("Nothing to restore.\n"); + + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " settemp_restore\n")); + print(" No arguments required.\n"); + print("See also: ^2settemp^7\n"); + return; + } + } +} + +/* use this when creating a new command, making sure to place it in alphabetical order... also, +** ADD ALL NEW COMMANDS TO commands.cfg WITH PROPER ALIASES IN THE SAME FASHION! +void GenericCommand_(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " ")); + print(" No arguments required.\n"); + return; + } + } +} +*/ + +// ================================== +// Macro system for server commands +// ================================== + +// Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;) +#define GENERIC_COMMANDS(request,arguments,command) \ + GENERIC_COMMAND("addtolist", GenericCommand_addtolist(request, arguments), "Add a string to a cvar") \ + GENERIC_COMMAND("dumpcommands", GenericCommand_dumpcommands(request), "Dump all commands on the program to *_cmd_dump.txt") \ + GENERIC_COMMAND("maplist", GenericCommand_maplist(request, arguments), "Automatic control of maplist") \ + GENERIC_COMMAND("removefromlist", GenericCommand_removefromlist(request, arguments), "Remove a string from a cvar") \ + GENERIC_COMMAND("rpn", GenericCommand_rpn(request, arguments, command), "RPN calculator") \ + GENERIC_COMMAND("settemp", GenericCommand_settemp(request, arguments), "Temporarily set a value to a cvar which is restored later") \ + GENERIC_COMMAND("settemp_restore", GenericCommand_settemp_restore(request, arguments), "Restore all cvars set by settemp command") \ + /* nothing */ + +void GenericCommand_macro_help() +{ + #define GENERIC_COMMAND(name,function,description) \ + { print(" ^2", name, "^7: ", description, "\n"); } + + GENERIC_COMMANDS(0, 0, "") + #undef GENERIC_COMMAND + + return; +} + +float GenericCommand_macro_command(float argc, string command) +{ + #define GENERIC_COMMAND(name,function,description) \ + { if(name == strtolower(argv(0))) { function; return TRUE; } } + + GENERIC_COMMANDS(CMD_REQUEST_COMMAND, argc, command) + #undef GENERIC_COMMAND + + return FALSE; +} + +float GenericCommand_macro_usage(float argc) +{ + #define GENERIC_COMMAND(name,function,description) \ + { if(name == strtolower(argv(1))) { function; return TRUE; } } + + GENERIC_COMMANDS(CMD_REQUEST_USAGE, argc, "") + #undef GENERIC_COMMAND + + return FALSE; +} + +void GenericCommand_macro_write_aliases(float fh) +{ + #define GENERIC_COMMAND(name,function,description) \ + { CMD_Write_Alias("qc_cmd_svmenu", name, description); } + + GENERIC_COMMANDS(0, 0, "") + #undef GENERIC_COMMAND + + return; +} + + +// =========================================== +// Main Common Function For Generic Commands +// =========================================== +// Commands spread out among all programs (menu, client, and server) + +float GenericCommand(string command) +{ + float argc = tokenize_console(command); + float n, j, f, i; + string s, s2, c; + vector rgb; + + // Guide for working with argc arguments by example: + // argc: 1 - 2 - 3 - 4 + // argv: 0 - 1 - 2 - 3 + // cmd vote - master - login - password + + if(GenericCommand_macro_command(argc, command)) // continue as usual and scan for normal commands + { + return TRUE; // handled by one of the above GenericCommand_* functions + } + else if(argc >= 3 && argv(0) == "red") + { + s = substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2)); + localcmd(strcat(argv(1), " ", GenericCommand_markup(s))); + return TRUE; + } + else if(argc >= 3 && crc16(0, argv(0)) == 38566 && crc16(0, strcat(argv(0), argv(0), argv(0))) == 59830) + { + // other test case + s = strconv(2, 0, 0, substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2))); + + n = floor(random() * 6 + 2); + + s2 = ""; + for(i = 0; i < n; ++i) + { + s2 = strcat(s2, "AH"); + } + + if(random() < 0.1) + s2 = strcat(substring(s2, 1, strlen(s2) - 1), "A"); + + if(s == "") + s = s2; + else + if(random() < 0.8) + s = strcat(s, " ", s2); + else + s = strcat(s2, " ", s); + + s2 = substring(s, strlen(s) - 2, 2); + if(s2 == "AH" || s2 == "AY") + s = strcat(s, "))"); + else + s = strcat(s, " ))"); + + if(random() < 0.1) + s = substring(s, 0, strlen(s) - 1); + + if(random() < 0.1) + s = strconv(1, 0, 0, s); + + localcmd(strcat(argv(1), " ", s)); + + return TRUE; + } + else if(argc >= 3 && crc16(0, argv(0)) == 3826 && crc16(0, strcat(argv(0), argv(0), argv(0))) == 55790) + { + // test case for terencehill's color codes + s = strdecolorize(substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2))); + s2 = ""; + + n = strlen(s); + j = ((6 * max(1, floor(strlen(s)/32 + random() * 2 - 1))) / n) * (1 - 2 * (random() > 0.5)); + f = random() * 6; + + for(i = 0; i < n; ++i) + { + c = substring(s, i, 1); + + if(c == ";") + c = ":"; + else if(c == "^") + { + c = "^^"; + if(substring(s, i+1, 1) == "^") + ++i; + } + + if(c != " ") + { + rgb = hsl_to_rgb('1 0 0' * (j * i + f) + '0 1 .5'); + c = strcat(rgb_to_hexcolor(rgb), c); + } + s2 = strcat(s2, c); + } + + localcmd(strcat(argv(1), " ", s2)); + + return TRUE; + } + + return FALSE; +} diff --git a/qcsrc/common/command/generic.qh b/qcsrc/common/command/generic.qh new file mode 100644 index 0000000000..3078a0f054 --- /dev/null +++ b/qcsrc/common/command/generic.qh @@ -0,0 +1,17 @@ +// ========================================================= +// Declarations for common command code, written by Samual +// Last updated: December 28th, 2011 +// ========================================================= + +// Used by other game command systems for common commands, +// and it returns true if handled, false if not. +// Note: It tokenizes its input, so be careful! +float GenericCommand(string command); + +// Returns command prefix specific for whatever program it is compiled in +string GetProgramCommandPrefix(void); + +// used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file +#define CMD_Write(s) fputs(fh, s) +#define CMD_Write_Alias(execute,command,description) CMD_Write(sprintf("alias %-20s \"%-13s %-20s ${* ?}\" // %s\n", command, execute, command, description)) +void GenericCommand_macro_write_aliases(float fh); \ No newline at end of file diff --git a/qcsrc/common/command/markup.qc b/qcsrc/common/command/markup.qc new file mode 100644 index 0000000000..cb1a8cc371 --- /dev/null +++ b/qcsrc/common/command/markup.qc @@ -0,0 +1,111 @@ +// ========================================================= +// Markup chat characters command code, reworked by Samual +// Last updated: December 28th, 2011 +// ========================================================= + +void GenericCommand_markup_init() +{ + float i; + if (markup_init) + return; + markup_init = 1; + i = 0; + markup_from[i] = "&alien"; markup_to[i] = "\x12"; ++i; + markup_from[i] = "&:-)"; markup_to[i] = "\x13"; ++i; + markup_from[i] = "&:-("; markup_to[i] = "\x14"; ++i; + markup_from[i] = "&x-P"; markup_to[i] = "\x15"; ++i; + markup_from[i] = "&:-/"; markup_to[i] = "\x16"; ++i; + markup_from[i] = "&:-D"; markup_to[i] = "\x17"; ++i; + markup_from[i] = "&<<"; markup_to[i] = "\x18"; ++i; + markup_from[i] = "&>>"; markup_to[i] = "\x19"; ++i; + markup_from[i] = "&dot"; markup_to[i] = "\x1a"; ++i; + markup_from[i] = "&^_"; markup_to[i] = "\x1b"; ++i; + markup_from[i] = "&ysplat"; markup_to[i] = "\x1c"; ++i; + markup_from[i] = "&-]"; markup_to[i] = "\x1d"; ++i; + markup_from[i] = "&--"; markup_to[i] = "\x1e"; ++i; + markup_from[i] = "&[-"; markup_to[i] = "\x1f"; ++i; + markup_from[i] = "&s<"; markup_to[i] = "\x2c"; ++i; + markup_from[i] = "&s>"; markup_to[i] = "\x2e"; ++i; + markup_from[i] = "&<-"; markup_to[i] = "\x7f"; ++i; + markup_from[i] = "&[="; markup_to[i] = "\x80"; ++i; + markup_from[i] = "&=="; markup_to[i] = "\x81"; ++i; + markup_from[i] = "&=]"; markup_to[i] = "\x82"; ++i; + markup_from[i] = "&r!"; markup_to[i] = "\x84"; ++i; + markup_from[i] = "&|o|"; markup_to[i] = "\x85"; ++i; + markup_from[i] = "&|u|"; markup_to[i] = "\x86"; ++i; + markup_from[i] = "&|i|"; markup_to[i] = "\x87"; ++i; + markup_from[i] = "&|c|"; markup_to[i] = "\x88"; ++i; + markup_from[i] = "&[c]"; markup_to[i] = "\x89"; ++i; + markup_from[i] = "&[n]"; markup_to[i] = "\x8a"; ++i; + markup_from[i] = "&[]"; markup_to[i] = "\x8b"; ++i; + markup_from[i] = "&r?"; markup_to[i] = "\x8c"; ++i; + markup_from[i] = "&|>"; markup_to[i] = "\x8d"; ++i; + markup_from[i] = "&splat0"; markup_to[i] = "\x8e"; ++i; + markup_from[i] = "&splat1"; markup_to[i] = "\x8f"; ++i; + markup_from[i] = "&[["; markup_to[i] = "\x90"; ++i; + markup_from[i] = "&]]"; markup_to[i] = "\x91"; ++i; + markup_from[i] = "&splat2"; markup_to[i] = "\x9a"; ++i; + markup_from[i] = "&)("; markup_to[i] = "\x9b"; ++i; + markup_from[i] = "&splat3"; markup_to[i] = "\x9c"; ++i; + markup_from[i] = "&(."; markup_to[i] = "\x9d"; ++i; + markup_from[i] = "&.."; markup_to[i] = "\x9e"; ++i; + markup_from[i] = "&.)"; markup_to[i] = "\x9f"; ++i; + markup_from[i] = "&<|"; markup_to[i] = "\xff"; ++i; +} + +string GenericCommand_markup(string s2) +{ + float red, ccase, i, j; + string s, s3; + + GenericCommand_markup_init(); + + s = ""; + + red = 0; + ccase = 0; + for(i = 0; i < strlen(s2); ++i) + { + for(j = 0; j < NUM_MARKUPS; ++j) + { + s3 = substring(s2, i, strlen(markup_from[j])); + if (s3 == markup_from[j]) + { + s = strcat(s, markup_to[j]); + i += strlen(markup_from[j]) - 1; + break; + } + } + + if(j == NUM_MARKUPS) + { + if(substring(s2, i, 2) == "&&") + { + s = strcat(s, strconv(ccase, red, red, "&")); + ++i; + } + else if(substring(s2, i, 2) == "&d") + { + red = 2; + ccase = 0; + ++i; + } + else if(substring(s2, i, 2) == "&a") + { + red = 2; + ccase = 2; + ++i; + } + else if(substring(s2, i, 2) == "&n") + { + red = 0; + ccase = 0; + ++i; + } + else + s = strcat(s, strconv(ccase, red, red, substring(s2, i, 1))); + } + } + + return s; +} diff --git a/qcsrc/common/command/markup.qh b/qcsrc/common/command/markup.qh new file mode 100644 index 0000000000..6cf09d3ed4 --- /dev/null +++ b/qcsrc/common/command/markup.qh @@ -0,0 +1,9 @@ +// ========================================================== +// Declarations for markup command code, reworked by Samual +// Last updated: December 28th, 2011 +// ========================================================== + +#define NUM_MARKUPS 41 +float markup_init; +string markup_from[NUM_MARKUPS]; +string markup_to[NUM_MARKUPS]; diff --git a/qcsrc/common/command/rpn.qc b/qcsrc/common/command/rpn.qc new file mode 100644 index 0000000000..d6c624bbb1 --- /dev/null +++ b/qcsrc/common/command/rpn.qc @@ -0,0 +1,559 @@ +// ======================================== +// RPN command code, written by divVerent +// Last updated: December 28th, 2011 +// ======================================== + +string rpn_pop() +{ + if(rpn_sp > 0) { + --rpn_sp; + return rpn_stack[rpn_sp]; + } else { + print("rpn: stack underflow\n"); + rpn_error = TRUE; + return ""; + } +} +void rpn_push(string s) +{ + if(rpn_sp < MAX_RPN_STACK) { + rpn_stack[rpn_sp] = s; + ++rpn_sp; + } else { + print("rpn: stack overflow\n"); + rpn_error = TRUE; + } +} +string rpn_get() +{ + if(rpn_sp > 0) { + return rpn_stack[rpn_sp - 1]; + } else { + print("rpn: empty stack\n"); + rpn_error = TRUE; + return ""; + } +} +void rpn_set(string s) +{ + if(rpn_sp > 0) { + rpn_stack[rpn_sp - 1] = s; + } else { + print("rpn: empty stack\n"); + rpn_error = TRUE; + } +} + +float rpn_getf() { return stof(rpn_get()); } +float rpn_popf() { return stof(rpn_pop()); } +void rpn_pushf(float f) { return rpn_push(ftos(f)); } +void rpn_setf(float f) { return rpn_set(ftos(f)); } + +void GenericCommand_rpn(float request, float argc, string command) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + float i, j, f, n, f2, f3, rpnpos; + vector rgb; + string s, s2, c, rpncmd; + + if(!rpn_db) + { + rpn_db = db_create(); + db_put(rpn_db, "stack.pointer", "0"); + db_put(rpn_db, "stack.pos", "-1"); + } + + if(argc >= 2) + { + rpn_sp = 0; + rpn_error = FALSE; + for(rpnpos = 1; rpnpos < argc; ++rpnpos) + { + rpncmd = argv(rpnpos); + f = strlen(rpncmd); + if(rpncmd == "") { + } else if(stof(substring(rpncmd, 0, 1)) > 0) { + rpn_push(rpncmd); + } else if(substring(rpncmd, 0, 1) == "0") { + rpn_push(rpncmd); + } else if(f >= 2 && substring(rpncmd, 0, 1) == "+") { + rpn_push(rpncmd); + } else if(f >= 2 && substring(rpncmd, 0, 1) == "-") { + rpn_push(rpncmd); + } else if(f >= 2 && substring(rpncmd, 0, 1) == "/") { + rpn_push(substring(rpncmd, 1, strlen(rpncmd) - 1)); + } else if(rpncmd == "clear") { + rpn_sp = 0; + } else if(rpncmd == "def" || rpncmd == "=") { + s = rpn_pop(); + s2 = rpn_pop(); + + if(s2 != "") + { + #ifdef MENUQC + registercvar(s2, "", 0); + #else + registercvar(s2, ""); + #endif + if(!rpn_error) // don't change cvars if a stack error had happened! + cvar_set(s2, s); + } + else + { + print("rpn: empty cvar name for 'def'\n"); + rpn_error = TRUE; + } + } else if(rpncmd == "defs" || rpncmd == "@") { + s = ""; + i = rpn_popf(); + j = (i == 0); + while(rpn_sp > 1 && (j || i > 0)) + { + s = strcat("/", rpn_pop(), " ", s); + --i; + } + s2 = rpn_pop(); + if(s2 != "") + { + #ifdef MENUQC + registercvar(s2, "", 0); + #else + registercvar(s2, ""); + #endif + if(!rpn_error) // don't change cvars if a stack error had happened! + cvar_set(s2, s); + } + else + { + print("rpn: empty cvar name for 'defs'\n"); + rpn_error = TRUE; + } + } else if(rpncmd == "load") { + rpn_set(cvar_string(rpn_get())); + } else if(rpncmd == "exch") { + s = rpn_pop(); + s2 = rpn_get(); + rpn_set(s); + rpn_push(s2); + } else if(rpncmd == "dup") { + rpn_push(rpn_get()); + } else if(rpncmd == "pop") { + rpn_pop(); + } else if(rpncmd == "add" || rpncmd == "+") { + f = rpn_popf(); + rpn_setf(rpn_getf() + f); + } else if(rpncmd == "sub" || rpncmd == "-") { + f = rpn_popf(); + rpn_setf(rpn_getf() - f); + } else if(rpncmd == "mul" || rpncmd == "*") { + f = rpn_popf(); + rpn_setf(rpn_getf() * f); + } else if(rpncmd == "div" || rpncmd == "/") { + f = rpn_popf(); + rpn_setf(rpn_getf() / f); + } else if(rpncmd == "mod" || rpncmd == "%") { + f = rpn_popf(); + f2 = rpn_getf(); + rpn_setf(f2 - f * floor(f2 / f)); + } else if(rpncmd == "abs") { + rpn_setf(fabs(rpn_getf())); + } else if(rpncmd == "sgn") { + f = rpn_getf(); + if(f < 0) + rpn_set("-1"); + else if(f > 0) + rpn_set("1"); + else + rpn_set("0"); + } else if(rpncmd == "neg" || rpncmd == "~") { + rpn_setf(-rpn_getf()); + } else if(rpncmd == "floor" || rpncmd == "f") { + rpn_setf(floor(rpn_getf())); + } else if(rpncmd == "ceil" || rpncmd == "c") { + rpn_setf(ceil(rpn_getf())); + } else if(rpncmd == "max") { + f = rpn_popf(); + f2 = rpn_getf(); + rpn_setf(max(f2, f)); + } else if(rpncmd == "min") { + f = rpn_popf(); + f2 = rpn_getf(); + rpn_setf(min(f2, f)); + } else if(rpncmd == "bound") { + f = rpn_popf(); + f2 = rpn_popf(); + f3 = rpn_getf(); + rpn_setf(bound(f3, f2, f)); + } else if(rpncmd == "when") { + f = rpn_popf(); + f2 = rpn_popf(); + f3 = rpn_getf(); + if(f) + rpn_setf(f3); + else + rpn_setf(f2); + } else if(rpncmd == ">" || rpncmd == "gt") { + f = rpn_popf(); + rpn_setf(rpn_getf() > f); + } else if(rpncmd == "<" || rpncmd == "lt") { + f = rpn_popf(); + rpn_setf(rpn_getf() < f); + } else if(rpncmd == "==" || rpncmd == "eq") { + f = rpn_popf(); + rpn_setf(rpn_getf() == f); + } else if(rpncmd == ">=" || rpncmd == "ge") { + f = rpn_popf(); + rpn_setf(rpn_getf() >= f); + } else if(rpncmd == "<=" || rpncmd == "le") { + f = rpn_popf(); + rpn_setf(rpn_getf() <= f); + } else if(rpncmd == "!=" || rpncmd == "ne") { + f = rpn_popf(); + rpn_setf(rpn_getf() != f); + } else if(rpncmd == "rand") { + rpn_setf(ceil(random() * rpn_getf()) - 1); + } else if(rpncmd == "crc16") { + rpn_setf(crc16(FALSE, rpn_get())); + } else if(rpncmd == "put") { + s2 = rpn_pop(); + if (!rpn_error) + { + s = rpn_pop(); + if (!rpn_error) + db_put(rpn_db, s, s2); + } + } else if(rpncmd == "get") { + s = rpn_pop(); + if (!rpn_error) + rpn_push(db_get(rpn_db, s)); + } else if(rpncmd == "dbpush") { + s = rpn_pop(); + if(!rpn_error) + { + i = stof(db_get(rpn_db, "stack.pointer")); + db_put(rpn_db, "stack.pointer", ftos(i+1)); + db_put(rpn_db, strcat("stack.", ftos(i)), s); + } + if(!i) + db_put(rpn_db, "stack.pos", "0"); + } else if(rpncmd == "dbpop") { + i = stof(db_get(rpn_db, "stack.pointer")); + if(i) + { + s = ftos(i-1); + db_put(rpn_db, "stack.pointer", s); + rpn_push(db_get(rpn_db, strcat("stack.", s))); + j = stof(db_get(rpn_db, "stack.pos")); + if(j >= i) + db_put(rpn_db, "stack.pos", ftos(i-2)); + } else { + rpn_error = 1; + print("rpn: database underflow\n"); + } + } else if(rpncmd == "dbget") { + + i = stof(db_get(rpn_db, "stack.pointer")); + if(i) + { + rpn_push(db_get(rpn_db, strcat("stack.", ftos(i-1)))); + } else { + rpn_error = 1; + print("rpn: database empty\n"); + } + } else if(rpncmd == "dblen") { + rpn_push(db_get(rpn_db, "stack.pointer")); + } else if(rpncmd == "dbclr") { + db_close(rpn_db); + rpn_db = db_create(); + db_put(rpn_db, "stack.pointer", "0"); + db_put(rpn_db, "stack.pos", "-1"); + } else if(rpncmd == "dbsave") { + s = rpn_pop(); + if(!rpn_error) + db_save(rpn_db, s); + } else if(rpncmd == "dbload") { + s = rpn_pop(); + if(!rpn_error) + { + db_close(rpn_db); + rpn_db = db_load(s); + } + } else if(rpncmd == "dbins") { + s = rpn_pop(); + if(!rpn_error) + //if(rpn_sp > 0) + { + j = stof(db_get(rpn_db, "stack.pointer")); + i = stof(db_get(rpn_db, "stack.pos")); + + if(i < 0) + { + i = 0; + db_put(rpn_db, "stack.pos", "0"); + } + + db_put(rpn_db, "stack.pointer", ftos(j+1)); + for(--j; j >= i; --j) + { + db_put(rpn_db, strcat("stack.", ftos(j+1)), + db_get(rpn_db, (strcat("stack.", ftos(j)))) + ); + } + db_put(rpn_db, strcat("stack.", ftos(i)), s); + } + } else if(rpncmd == "dbext") { + j = stof(db_get(rpn_db, "stack.pointer")); + i = stof(db_get(rpn_db, "stack.pos")); + if(!j) + { + rpn_error = TRUE; + print("rpn: empty database\n"); + } else { + --j; + rpn_push(db_get(rpn_db, strcat("stack.", ftos(i)))); + db_put(rpn_db, "stack.pointer", ftos(j)); + if(i == j) + { + db_put(rpn_db, "stack.pos", ftos(j-1)); + } else { + while(i < j) + { + db_put(rpn_db, strcat("stack.", ftos(i)), + db_get(rpn_db, (strcat("stack.", ftos(i+1)))) + ); + ++i; + } + } + } + } else if(rpncmd == "dbread") { + s = db_get(rpn_db, "stack.pos"); + if(stof(s) >= 0) + { + rpn_push(db_get(rpn_db, strcat("stack.", s))); + } else { + rpn_error = 1; + print("rpn: empty database\n"); + } + } else if(rpncmd == "dbat") { + rpn_push(db_get(rpn_db, "stack.pos")); + } else if(rpncmd == "dbmov") { + j = stof(db_get(rpn_db, "stack.pointer")); + i = stof(db_get(rpn_db, "stack.pos")); + i += rpn_popf(); + if(!rpn_error) + { + if(i < 0 || i >= j) + { + print("rpn: database cursor out of bounds\n"); + rpn_error = TRUE; + } + if(!rpn_error) + { + db_put(rpn_db, "stack.pos", ftos(i)); + } + } + } else if(rpncmd == "dbgoto") { + s = rpn_pop(); + j = stof(db_get(rpn_db, "stack.pointer")); + if(!j) + { + rpn_error = TRUE; + print("rpn: empty database, cannot move cursor\n"); + } + if(!rpn_error) + { + if(s == "end") + i = stof(db_get(rpn_db, "stack.pointer"))-1; + else if(s == "beg") + i = 0; + else + i = stof(s); + + j = stof(db_get(rpn_db, "stack.pointer")); + if(i < 0 || i >= j) + { + print("rpn: database cursor destination out of bounds\n"); + rpn_error = TRUE; + } + if(!rpn_error) + { + db_put(rpn_db, "stack.pos", ftos(i)); + } + } + } else if(rpncmd == "union") { + // s s2 union + s2 = rpn_pop(); + s = rpn_get(); + f = tokenize_console(s); + f2 = tokenize_console(strcat(s, " ", s2)); + // tokens 0..(f-1) represent s + // tokens f..f2 represent s2 + // UNION: add all tokens to s that are in s2 but not in s + s = ""; + for(i = 0; i < f; ++i) + s = strcat(s, " ", argv(i)); + for(i = f; i < f2; ++i) { + for(j = 0; j < f; ++j) + if(argv(i) == argv(j)) + goto skip_union; + s = strcat(s, " ", argv(i)); + :skip_union + } + if(substring(s, 0, 1) == " ") + s = substring(s, 1, 99999); + rpn_set(s); + tokenize_console(command); + } else if(rpncmd == "intersection") { + // s s2 intersection + s2 = rpn_pop(); + s = rpn_get(); + f = tokenize_console(s); + f2 = tokenize_console(strcat(s, " ", s2)); + // tokens 0..(f-1) represent s + // tokens f..f2 represent s2 + // INTERSECTION: keep only the tokens from s that are also in s2 + s = ""; + for(i = 0; i < f; ++i) { + for(j = f; j < f2; ++j) + if(argv(i) == argv(j)) + { + s = strcat(s, " ", argv(i)); + break; + } + } + if(substring(s, 0, 1) == " ") + s = substring(s, 1, 99999); + rpn_set(s); + tokenize_console(command); + } else if(rpncmd == "difference") { + // s s2 difference + s2 = rpn_pop(); + s = rpn_get(); + f = tokenize_console(s); + f2 = tokenize_console(strcat(s, " ", s2)); + // tokens 0..(f-1) represent s + // tokens f..f2 represent s2 + // DIFFERENCE: keep only the tokens from s that are not in s2 + s = ""; + for(i = 0; i < f; ++i) { + for(j = f; j < f2; ++j) + if(argv(i) == argv(j)) + goto skip_difference; + s = strcat(s, " ", argv(i)); + :skip_difference + } + if(substring(s, 0, 1) == " ") + s = substring(s, 1, 99999); + rpn_set(s); + tokenize_console(command); + } else if(rpncmd == "shuffle") { + // s shuffle + s = rpn_get(); + f = tokenize_console(s); + + for(i = 0; i < f - 1; ++i) { + // move a random item from i..f-1 to position i + s = ""; + f2 = floor(random() * (f - i) + i); + for(j = 0; j < i; ++j) + s = strcat(s, " ", argv(j)); + s = strcat(s, " ", argv(f2)); + for(j = i; j < f; ++j) + if(j != f2) + s = strcat(s, " ", argv(j)); + f = tokenize_console(s); + } + + if(substring(s, 0, 1) == " ") + s = substring(s, 1, 99999); + rpn_set(s); + tokenize_console(command); + } else if(rpncmd == "fexists_assert") { + s = rpn_pop(); + if(!rpn_error) + { + if (!fexists(s)) + { + print("rpn: ERROR: ", s, " does not exist!\n"); + rpn_error = TRUE; + } + } + } else if(rpncmd == "fexists") { + s = rpn_get(); + if(!rpn_error) + { + if (fexists(s)) + rpn_setf(1); + else + rpn_setf(0); + } + } else if(rpncmd == "localtime") { + rpn_set(strftime(TRUE, rpn_get())); + } else if(rpncmd == "gmtime") { + rpn_set(strftime(FALSE, rpn_get())); + } else if(rpncmd == "time") { + rpn_pushf(time); + } else if(rpncmd == "digest") { + s = rpn_pop(); + rpn_set(digest_hex(s, rpn_get())); + } else if(rpncmd == "sprintf1s") { + s = rpn_pop(); + rpn_set(sprintf(s, rpn_get())); + } else { + rpn_push(cvar_string(rpncmd)); + } + if(rpn_error) + break; + } + while(rpn_sp > 0) + { + s = rpn_pop(); + print("rpn: still on stack: ", s, "\n"); + } + } + + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " rpn EXPRESSION...\n")); + print(" Operator description (x: string, s: set, f: float):\n"); + print(" x pop -----------------------------> : removes the top\n"); + print(" x dup -----------------------------> x x : duplicates the top\n"); + print(" x x exch --------------------------> x x : swap the top two\n"); + print(" /cvarname load --------------------> x : loads a cvar\n"); + print(" /cvarname x def -------------------> : writes to a cvar\n"); + print(" f f add|sub|mul|div|mod|max|min ---> f : adds/... two numbers\n"); + print(" f f eq|ne|gt|ge|lt|le -------------> f : compares two numbers\n"); + print(" f neg|abs|sgn|rand|floor|ceil------> f : negates/... a number\n"); + print(" f f f bound -----------------------> f : bounds the middle number\n"); + print(" f1 f2 b when ----------------------> f : f1 if b, f2 otherwise\n"); + print(" s s union|intersection|difference -> s : set operations\n"); + print(" s shuffle -------------------------> s : randomly arrange elements\n"); + print(" /key /value put -------------------> : set a database key\n"); + print(" /key get --------------------------> s : get a database value\n"); + print(" x dbpush --------------------------> : pushes the top onto the database\n"); + print(" dbpop|dbget -----------------------> x : removes/reads DB's top\n"); + print(" dblen|dbat ------------------------> f : gets the DB's size/cursor pos\n"); + print(" dbclr -----------------------------> : clear the DB\n"); + print(" s dbsave|dbload--------------------> : save/load the DB to/from a file\n"); + print(" x dbins ---------------------------> : moves the top into the DB\n"); + print(" dbext|dbread ----------------------> x : extract/get from the DB's cursor\n"); + print(" f dbmov|dbgoto --------------------> : move or set the DB's cursor\n"); + print(" s localtime -----------------------> s : formats the current local time\n"); + print(" s gmtime --------------------------> s : formats the current UTC time\n"); + print(" time ------------------------------> f : seconds since VM start\n"); + print(" s /MD4 digest ---------------------> s : MD4 digest\n"); + print(" s /SHA256 digest ------------------> s : SHA256 digest\n"); + print(" s /formatstring sprintf1s ---------> s : sprintf with 1 string (pad, cut)\n"); + print(" Set operations operate on 'such''strings'.\n"); + print(" Unknown tokens insert their cvar value.\n"); + return; + } + } +} \ No newline at end of file diff --git a/qcsrc/common/command/rpn.qh b/qcsrc/common/command/rpn.qh new file mode 100644 index 0000000000..6ffc5e1cb4 --- /dev/null +++ b/qcsrc/common/command/rpn.qh @@ -0,0 +1,10 @@ +// ========================================================= +// Declarations for RPN command code, written by divVerent +// Last updated: December 28th, 2011 +// ========================================================= + +#define MAX_RPN_STACK 16 +float rpn_db; +float rpn_error; +float rpn_sp; +string rpn_stack[MAX_RPN_STACK]; \ No newline at end of file diff --git a/qcsrc/common/command/shared_defs.qh b/qcsrc/common/command/shared_defs.qh new file mode 100644 index 0000000000..f06ee3239d --- /dev/null +++ b/qcsrc/common/command/shared_defs.qh @@ -0,0 +1,8 @@ +// ========================================================= +// Shared declarations for all commands, written by Samual +// Last updated: December 13th, 2011 +// ========================================================= + +// identifiers for subfunction requests by the command code structure +#define CMD_REQUEST_COMMAND 1 +#define CMD_REQUEST_USAGE 2 \ No newline at end of file diff --git a/qcsrc/common/constants.qh b/qcsrc/common/constants.qh index 50abe9875e..7532b3f50b 100644 --- a/qcsrc/common/constants.qh +++ b/qcsrc/common/constants.qh @@ -23,25 +23,6 @@ // Revision 22: hook shot origin #define CSQC_REVISION 22 -// probably put these in common/ -// so server/ and client/ can be synced better -const float GAME_DEATHMATCH = 1; -const float GAME_TEAM_DEATHMATCH = 2; -const float GAME_DOMINATION = 3; -const float GAME_CTF = 4; -const float GAME_RUNEMATCH = 5; -const float GAME_LMS = 6; -const float GAME_ARENA = 7; -const float GAME_KEYHUNT = 8; -const float GAME_ASSAULT = 9; -const float GAME_ONSLAUGHT = 10; -const float GAME_RACE = 11; -const float GAME_NEXBALL = 12; -const float GAME_CTS = 13; -const float GAME_CA = 14; -const float GAME_FREEZETAG = 15; -const float GAME_KEEPAWAY = 16; - const float AS_STRING = 1; const float AS_INT = 2; const float AS_FLOAT_TRUNCATED = 2; @@ -55,15 +36,16 @@ const float TE_CSQC_NEXGUNBEAMPARTICLE = 104; const float TE_CSQC_LIGHTNINGARC = 105; const float TE_CSQC_TEAMNAGGER = 106; const float TE_CSQC_PINGPLREPORT = 107; -const float TE_CSQC_VOTE = 108; -const float TE_CSQC_VOTERESET = 109; const float TE_CSQC_ANNOUNCE = 110; const float TE_CSQC_TARGET_MUSIC = 111; -const float TE_CSQC_NOTIFY = 112; -const float TE_CSQC_WEAPONCOMPLAIN = 113; -const float TE_CSQC_CAMPINGRIFLE_SCOPE = 115; +const float TE_CSQC_KILLNOTIFY = 112; +const float TE_CSQC_KILLCENTERPRINT = 113; +const float TE_CSQC_CENTERPRINT_GENERIC = 114; +const float TE_CSQC_WEAPONCOMPLAIN = 115; const float TE_CSQC_NEX_SCOPE = 116; -const float TE_CSQC_CR_MAXBULLETS = 117; +const float TE_CSQC_MINELAYER_MAXMINES = 117; +const float TE_CSQC_HAGAR_MAXROCKETS = 118; +const float TE_CSQC_VEHICLESETUP = 119; const float RACE_NET_CHECKPOINT_HIT_QUALIFYING = 0; // byte checkpoint, short time, short recordtime, string recordholder const float RACE_NET_CHECKPOINT_CLEAR = 1; @@ -80,9 +62,6 @@ const float RACE_NET_SERVER_RANKINGS = 11; const float RACE_NET_SERVER_STATUS = 12; const float RANKINGS_CNT = 15; -const float CSQC_KILLNOTIFY = 0; -const float CSQC_CENTERPRINT = 1; - const float ENT_CLIENT = 0; const float ENT_CLIENT_DEAD = 1; const float ENT_CLIENT_ENTCS = 2; @@ -114,12 +93,18 @@ const float ENT_CLIENT_HOOK = 27; const float ENT_CLIENT_LGBEAM = 28; const float ENT_CLIENT_GAUNTLET = 29; const float ENT_CLIENT_ACCURACY = 30; +const float ENT_CLIENT_SHOWNAMES = 31; +const float ENT_CLIENT_WARPZONE_TELEPORTED = 32; +const float ENT_CLIENT_MODEL = 33; const float ENT_CLIENT_TURRET = 40; +const float ENT_CLIENT_AUXILIARYXHAIR = 50; +const float ENT_CLIENT_VEHICLE = 60; const float SPRITERULE_DEFAULT = 0; const float SPRITERULE_TEAMPLAY = 1; +const float RADARICON_NONE = 0; const float RADARICON_FLAG = 1; const float RADARICON_FLAGCARRIER = 1; const float RADARICON_HERE = 1; // TODO make these 3 and 4, and make images for them @@ -131,151 +116,7 @@ const float RADARICON_GENERATOR = 1; const float RADARICON_OBJECTIVE = 1; const float RADARICON_DOMPOINT = 1; const float RADARICON_POWERUP = 1; - -/////////////////////////// -// key constants - -// -// these are the key numbers that should be passed to Key_Event -// -const float K_TAB = 9; -const float K_ENTER = 13; -const float K_ESCAPE = 27; -const float K_SPACE = 32; - -// normal keys should be passed as lowercased ascii - -const float K_BACKSPACE = 127; -const float K_UPARROW = 128; -const float K_DOWNARROW = 129; -const float K_LEFTARROW = 130; -const float K_RIGHTARROW = 131; - -const float K_ALT = 132; -const float K_CTRL = 133; -const float K_SHIFT = 134; - -const float K_F1 = 135; -const float K_F2 = 136; -const float K_F3 = 137; -const float K_F4 = 138; -const float K_F5 = 139; -const float K_F6 = 140; -const float K_F7 = 141; -const float K_F8 = 142; -const float K_F9 = 143; -const float K_F10 = 144; -const float K_F11 = 145; -const float K_F12 = 146; - -const float K_INS = 147; -const float K_DEL = 148; -const float K_PGDN = 149; -const float K_PGUP = 150; -const float K_HOME = 151; -const float K_END = 152; - -const float K_NUMLOCK = 154; -const float K_CAPSLOCK = 155; -const float K_SCROLLOCK = 156; - -const float K_KP_0 = 157; -const float K_KP_INS = K_KP_0; -const float K_KP_1 = 158; -const float K_KP_END = K_KP_1; -const float K_KP_2 = 159; -const float K_KP_DOWNARROW = K_KP_2; -const float K_KP_3 = 160; -const float K_KP_PGDN = K_KP_3; -const float K_KP_4 = 161; -const float K_KP_LEFTARROW = K_KP_4; -const float K_KP_5 = 162; -const float K_KP_6 = 163; -const float K_KP_RIGHTARROW = K_KP_6; -const float K_KP_7 = 164; -const float K_KP_HOME = K_KP_7; -const float K_KP_8 = 165; -const float K_KP_UPARROW = K_KP_8; -const float K_KP_9 = 166; -const float K_KP_PGUP = K_KP_9; -const float K_KP_PERIOD = 167; -const float K_KP_DEL = K_KP_PERIOD; -const float K_KP_DIVIDE = 168; -const float K_KP_SLASH = K_KP_DIVIDE; -const float K_KP_MULTIPLY = 169; -const float K_KP_MINUS = 170; -const float K_KP_PLUS = 171; -const float K_KP_ENTER = 172; -const float K_KP_EQUALS = 173; - -const float K_PAUSE = 255; - -// -// joystick buttons -// -const float K_JOY1 = 768; -const float K_JOY2 = 769; -const float K_JOY3 = 770; -const float K_JOY4 = 771; - -// -// aux keys are for multi-buttoned joysticks to generate so they can use -// the normal binding process -// -const float K_AUX1 = 772; -const float K_AUX2 = 773; -const float K_AUX3 = 774; -const float K_AUX4 = 775; -const float K_AUX5 = 776; -const float K_AUX6 = 777; -const float K_AUX7 = 778; -const float K_AUX8 = 779; -const float K_AUX9 = 780; -const float K_AUX10 = 781; -const float K_AUX11 = 782; -const float K_AUX12 = 783; -const float K_AUX13 = 784; -const float K_AUX14 = 785; -const float K_AUX15 = 786; -const float K_AUX16 = 787; -const float K_AUX17 = 788; -const float K_AUX18 = 789; -const float K_AUX19 = 790; -const float K_AUX20 = 791; -const float K_AUX21 = 792; -const float K_AUX22 = 793; -const float K_AUX23 = 794; -const float K_AUX24 = 795; -const float K_AUX25 = 796; -const float K_AUX26 = 797; -const float K_AUX27 = 798; -const float K_AUX28 = 799; -const float K_AUX29 = 800; -const float K_AUX30 = 801; -const float K_AUX31 = 802; -const float K_AUX32 = 803; - -// -// mouse buttons generate virtual keys -// -const float K_MOUSE1 = 512; -const float K_MOUSE2 = 513; -const float K_MOUSE3 = 514; -const float K_MWHEELUP = 515; -const float K_MWHEELDOWN = 516; -const float K_MOUSE4 = 517; -const float K_MOUSE5 = 518; -const float K_MOUSE6 = 519; -const float K_MOUSE7 = 520; -const float K_MOUSE8 = 521; -const float K_MOUSE9 = 522; -const float K_MOUSE10 = 523; -const float K_MOUSE11 = 524; -const float K_MOUSE12 = 525; -const float K_MOUSE13 = 526; -const float K_MOUSE14 = 527; -const float K_MOUSE15 = 528; -const float K_MOUSE16 = 529; +const float RADARICON_TAGGED = 1; /////////////////////////// // keys pressed @@ -309,11 +150,17 @@ const float STAT_FUEL = 44; const float STAT_NB_METERSTART = 45; const float STAT_SHOTORG = 46; // compressShotOrigin const float STAT_LEADLIMIT = 47; -const float STAT_BULLETS_LOADED = 48; -const float STAT_NEX_CHARGE = 49; -const float STAT_LAST_PICKUP = 50; -const float STAT_HUD = 51; -const float STAT_NEX_CHARGEPOOL = 52; +const float STAT_WEAPON_CLIPLOAD = 48; +const float STAT_WEAPON_CLIPSIZE = 49; +const float STAT_NEX_CHARGE = 50; +const float STAT_LAST_PICKUP = 51; +const float STAT_HUD = 52; +const float STAT_NEX_CHARGEPOOL = 53; +const float STAT_HIT_TIME = 54; +const float STAT_TYPEHIT_TIME = 55; +const float STAT_LAYED_MINES = 56; +const float STAT_HAGAR_LOAD = 57; +const float STAT_SWITCHINGWEAPON = 58; // see DP source, quakedef.h const float STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW = 222; @@ -326,9 +173,13 @@ const float CTF_STATE_DEFEND = 2; const float CTF_STATE_COMMANDER = 3; const float HUD_NORMAL = 0; -const float HUD_SPIDERBOT = 10; -const float HUD_WAKIZASHI = 11; -const float HUD_RAPTOR = 12; +const float HUD_VEHICLE_FIRST = 10; +const float HUD_SPIDERBOT = 10; +const float HUD_WAKIZASHI = 11; +const float HUD_RAPTOR = 12; +const float HUD_BUMBLEBEE = 13; +const float HUD_VEHICLE_LAST = 13; + const vector eX = '1 0 0'; const vector eY = '0 1 0'; const vector eZ = '0 0 1'; @@ -341,6 +192,9 @@ const float STAT_VEHICLESTAT_RELOAD1 = 64; const float STAT_VEHICLESTAT_AMMO2 = 65; const float STAT_VEHICLESTAT_RELOAD2 = 66; +const float STAT_SECRETS_TOTAL = 70; +const float STAT_SECRETS_FOUND = 71; + // mod stats (1xx) const float STAT_REDALIVE = 100; const float STAT_BLUEALIVE = 101; @@ -351,11 +205,15 @@ const float STAT_PINKALIVE = 103; const float STAT_FROZEN = 104; const float STAT_REVIVE_PROGRESS = 105; -//const float STAT_SPIDERBOT_AIM 53 // compressShotOrigin -//const float STAT_SPIDERBOT_TARGET 54 // compressShotOrigin - +const float STAT_DOM_TOTAL_PPS = 100; +const float STAT_DOM_PPS_RED = 101; +const float STAT_DOM_PPS_BLUE = 102; +const float STAT_DOM_PPS_PINK = 103; +const float STAT_DOM_PPS_YELLOW = 104; +//const float STAT_SPIDERBOT_AIM 53 // compressShotOrigin +//const float STAT_SPIDERBOT_TARGET 54 // compressShotOrigin // moved that here so the client knows the max. // # of maps, I'll use arrays for them :P @@ -409,51 +267,44 @@ const float STAT_REVIVE_PROGRESS = 105; #define SP_SCORE 3 // game mode specific indices are not in common/, but in server/scores_rules.qc! -// this assignment must match menu/xonotic/dialog_settings_misc.c! -float CHAN_AUTO = 0; - // on world: announcers, ... INFO - // on players: item pickup ITEMS - // on entities: UNUSED - // on csqc: announcers INFO -float CHAN_WEAPON = 1; // Weapon fire - // on world: UNUSED - // on players: weapon firing WEAPONS - // on entities: turret firing WEAPONS - // on csqc: UNUSED -float CHAN_VOICE = 2; // Voice/Radio - // on world: UNUSED - // on players: voice VOICE - // on entities: ambient AMBIENT - // on csqc: background music BGM -float CHAN_TRIGGER = 3; // Triggers/Items - // on world: UNUSED - // on players: item pickup ITEMS - // on entities: platforms moving etc. ITEMS - // on csqc: platforms moving etc. ITEMS -float CHAN_PROJECTILE = 4; // Projectiles - // on world: UNUSED - // on players: projectiles hitting player SHOTS - // on entities: projectiles SHOTS - // on csqc: projectile sounds SHOTS -float CHAN_WEAPON2 = 5; // Nex fire (separated as it is a very long sound) - // on world: UNUSED - // on players: weapon firing WEAPONS - // on entities: turret firing WEAPONS - // on csqc: UNUSED -float CHAN_PAIN = 6; // Pain - // on world: UNUSED - // on players: pain PAIN - // on entities: projectiles flying SHOTS - // on csqc: player pain PAIN -float CHAN_PLAYER = 7; // Player body - // on world: UNUSED - // on players: player sounds PLAYER - // on entities: player sounds PLAYER - // on csqc: UNUSED +#ifdef COMPAT_XON010_CHANNELS +float CH_INFO = 0; // only on world and csqc +float CH_TRIGGER = 0; // only on players; compat: FALSELY CONTROLLED BY "Info" +float CH_WEAPON_A = 1; // only on players and entities +float CH_WEAPON_SINGLE = 5; // only on players and entities +float CH_VOICE = 2; // only on players +float CH_BGM_SINGLE = 2; // only on csqc; compat: FALSELY CONTROLLED BY "Voice" +float CH_AMBIENT = 2; // only on csqc; compat: FALSELY CONTROLLED BY "Voice" +float CH_TRIGGER_SINGLE = 3; // only on players, entities, csqc +float CH_SHOTS = 4; // only on players, entities, csqc +float CH_SHOTS_SINGLE = 4; // only on players, entities, csqc +float CH_WEAPON_B = 5; // only on players and entities +float CH_PAIN = 6; // only on players and csqc +float CH_PAIN_SINGLE = 6; // only on players and csqc +float CH_PLAYER = 7; // only on players and entities +float CH_TUBA = 5; // only on csqc +#else +float CH_INFO = 0; +float CH_TRIGGER = -3; +float CH_WEAPON_A = -1; +float CH_WEAPON_SINGLE = 1; +float CH_VOICE = -2; +float CH_BGM_SINGLE = 8; +float CH_AMBIENT = -9; +float CH_TRIGGER_SINGLE = 3; +float CH_SHOTS = -4; +float CH_SHOTS_SINGLE = 4; +float CH_WEAPON_B = -1; +float CH_PAIN = -6; +float CH_PAIN_SINGLE = 6; +float CH_PLAYER = -7; +float CH_TUBA = 5; +#endif float ATTN_NONE = 0; float ATTN_MIN = 0.015625; float ATTN_NORM = 0.5; +float ATTN_LARGE = 1; float ATTN_IDLE = 2; float ATTN_STATIC = 3; float ATTN_MAX = 3.984375; @@ -486,6 +337,13 @@ float PROJECTILE_FIREBALL = 21; float PROJECTILE_FIREMINE = 22; float PROJECTILE_BULLET_GLOWING_TRACER = 23; +float PROJECTILE_RAPTORCANNON = 24; +float PROJECTILE_RAPTORBOMB = 25; +float PROJECTILE_RAPTORBOMBLET = 26; +float PROJECTILE_SPIDERROCKET = 27; +float PROJECTILE_WAKIROCKET = 28; +float PROJECTILE_WAKICANNON = 29; + float SPECIES_HUMAN = 0; float SPECIES_ROBOT_SOLID = 1; float SPECIES_ALIEN = 2; @@ -515,18 +373,22 @@ float DEATH_MIRRORDAMAGE = 10014; float DEATH_TOUCHEXPLODE = 10015; float DEATH_CHEAT = 10016; float DEATH_FIRE = 10017; -float DEATH_TURRET = 10020; float DEATH_QUIET = 10021; -float DEATH_HEADSHOT = 10022; -float DEATH_SBMINIGUN = 10030; -float DEATH_SBROCKET = 10031; -float DEATH_SBCRUSH = 10032; -float DEATH_SBBLOWUP = 10033; - -float DEATH_WAKIGUN = 10040; -float DEATH_WAKIROCKET = 10041; -float DEATH_WAKIBLOWUP = 10042; +float DEATH_VHFIRST = 10030; +float DEATH_VHCRUSH = 10030; +float DEATH_SBMINIGUN = 10031; +float DEATH_SBROCKET = 10032; +float DEATH_SBBLOWUP = 10033; +float DEATH_WAKIGUN = 10034; +float DEATH_WAKIROCKET = 10035; +float DEATH_WAKIBLOWUP = 10036; +float DEATH_RAPTOR_CANNON = 10037; +float DEATH_RAPTOR_BOMB = 10038; +float DEATH_RAPTOR_BOMB_SPLIT = 10039; +float DEATH_RAPTOR_DEATH = 10040; +float DEATH_VHLAST = 10040; +#define DEATH_ISVEHICLE(t) ((t) >= DEATH_VHFIRST && (t) <= DEATH_VHLAST) float DEATH_GENERIC = 10050; @@ -534,16 +396,31 @@ float DEATH_WEAPON = 10100; float DEATH_CUSTOM = 10300; +float DEATH_TURRET = 10500; +float DEATH_TURRET_EWHEEL = 10501; +float DEATH_TURRET_FLAC = 10502; +float DEATH_TURRET_MACHINEGUN = 10503; +float DEATH_TURRET_WALKER_GUN = 10504; +float DEATH_TURRET_WALKER_MEELE = 10505; +float DEATH_TURRET_WALKER_ROCKET = 10506; +float DEATH_TURRET_HELLION = 10507; +float DEATH_TURRET_HK = 10508; +float DEATH_TURRET_MLRS = 10509; +float DEATH_TURRET_PLASMA = 10510; +float DEATH_TURRET_PHASER = 10511; +float DEATH_TURRET_TESLA = 10512; +float DEATH_TURRET_LAST = 10512; float DEATH_WEAPONMASK = 0xFF; float DEATH_HITTYPEMASK = 0x1F00; // which is WAY below 10000 used for normal deaths float HITTYPE_SECONDARY = 0x100; -float HITTYPE_SPLASH = 0x200; +float HITTYPE_SPLASH = 0x200; // automatically set by RadiusDamage float HITTYPE_BOUNCE = 0x400; -float HITTYPE_HEADSHOT = 0x800; +float HITTYPE_HEADSHOT = 0x800; // automatically set by Damage (if headshotbonus is set) float HITTYPE_RESERVED = 0x1000; // unused yet // macros to access these +#define DEATH_ISTURRET(t) ((t) >= DEATH_TURRET && (t) <= DEATH_TURRET_LAST) #define DEATH_ISSPECIAL(t) ((t) >= DEATH_SPECIAL_START) #define DEATH_WEAPONOFWEAPONDEATH(t) ((t) & DEATH_WEAPONMASK) #define DEATH_ISWEAPON(t,w) (!DEATH_ISSPECIAL(t) && DEATH_WEAPONOFWEAPONDEATH(t) == (w)) @@ -556,9 +433,6 @@ float HITTYPE_RESERVED = 0x1000; // unused yet #define FRAGS_PLAYER_NONSOLID -616 // we can use this frags value for both -//misc. stuff -#define NEWLINES "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" - // water levels float WATERLEVEL_NONE = 0; float WATERLEVEL_WETFEET = 1; @@ -567,6 +441,19 @@ float WATERLEVEL_SUBMERGED = 3; float MAX_SHOT_DISTANCE = 32768; +//centerprint ID list +float CPID_TEAMCHANGE = 1; +float CPID_CTF_CAPTURESHIELD = 2; +float CPID_MINSTA_FINDAMMO = 3; +float CPID_NIX_WPNCHANGE = 4; +float CPID_DISCONNECT_IDLING = 5; +float CPID_ROUND_STARTING = 6; +float CPID_GAME_STARTING = 7; +float CPID_TIMEOUT_COUNTDOWN = 8; +float CPID_MOTD = 9; +float CPID_KH_MSG = 10; +float CPID_PREVENT_JOIN = 11; + // CSQC centerprint/notify message types float MSG_SUICIDE = 0; float MSG_KILL = 1; @@ -577,38 +464,38 @@ float MSG_INFO = 5; float MSG_KA = 6; float MSG_RACE = 10; -float KILL_TEAM_RED = 10301; -float KILL_TEAM_BLUE = 10302; -float KILL_TEAM_SPREE = 10303; -float KILL_FIRST_BLOOD = 10304; -float KILL_FIRST_VICTIM = 10305; -float KILL_TYPEFRAG = 10306; -float KILL_TYPEFRAGGED = 10307; -float KILL_FRAG = 10308; -float KILL_FRAGGED = 10309; -float KILL_SPREE = 10310; -float KILL_END_SPREE = 10311; -float KILL_SPREE_3 = 10312; -float KILL_SPREE_5 = 10313; -float KILL_SPREE_10 = 10314; -float KILL_SPREE_15 = 10315; -float KILL_SPREE_20 = 10316; -float KILL_SPREE_25 = 10317; -float KILL_SPREE_30 = 10318; - -float INFO_GOTFLAG = 10319; -float INFO_PICKUPFLAG = 10320; -float INFO_LOSTFLAG = 10321; -float INFO_RETURNFLAG = 10322; -float INFO_CAPTUREFLAG = 10323; - -float KA_PICKUPBALL = 10350; -float KA_DROPBALL = 10351; - -float RACE_SERVER_RECORD = 10400; -float RACE_NEW_TIME = 10401; -float RACE_NEW_RANK = 10402; -float RACE_FAIL = 10403; +float KILL_TEAM_RED = 12001; +float KILL_TEAM_BLUE = 12002; +float KILL_TEAM_SPREE = 12003; +float KILL_FIRST_BLOOD = 12004; +float KILL_FIRST_VICTIM = 12005; +float KILL_TYPEFRAG = 12006; +float KILL_TYPEFRAGGED = 12007; +float KILL_FRAG = 12008; +float KILL_FRAGGED = 12009; +float KILL_SPREE = 12010; +float KILL_END_SPREE = 12011; +float KILL_SPREE_3 = 12012; +float KILL_SPREE_5 = 12013; +float KILL_SPREE_10 = 12014; +float KILL_SPREE_15 = 12015; +float KILL_SPREE_20 = 12016; +float KILL_SPREE_25 = 12017; +float KILL_SPREE_30 = 12018; + +float INFO_GOTFLAG = 13001; +float INFO_PICKUPFLAG = 13002; +float INFO_LOSTFLAG = 13003; +float INFO_RETURNFLAG = 13004; +float INFO_CAPTUREFLAG = 13005; + +float KA_PICKUPBALL = 14001; +float KA_DROPBALL = 14002; + +float RACE_SERVER_RECORD = 15001; +float RACE_NEW_TIME = 15002; +float RACE_NEW_RANK = 15003; +float RACE_FAIL = 15004; // weapon requests float WR_SETUP = 1; // (SVQC) setup weapon data @@ -622,7 +509,9 @@ float WR_KILLMESSAGE = 8; // (CSQC) sets w_deathtypestring or leaves it alone float WR_RELOAD = 9; // (SVQC) does not need to do anything float WR_RESETPLAYER = 10; // (SVQC) does not need to do anything float WR_IMPACTEFFECT = 11; // (CSQC) impact effect - +float WR_SWITCHABLE = 12; // (CSQC) impact effect +float WR_PLAYERDEATH = 13; // (SVQC) does not need to do anything +float WR_GONETHINK = 14; // (SVQC) logic to run every frame, also if no longer having the weapon as long as the switch away has not been performed float HUD_PANEL_WEAPONS = 0; float HUD_PANEL_AMMO = 1; @@ -639,7 +528,9 @@ float HUD_PANEL_PRESSEDKEYS = 11; float HUD_PANEL_CHAT = 12; float HUD_PANEL_ENGINEINFO = 13; float HUD_PANEL_INFOMESSAGES = 14; -float HUD_PANEL_NUM = 15; // always last panel id + 1, please increment when adding a new panel +float HUD_PANEL_PHYSICS = 15; +float HUD_PANEL_CENTERPRINT = 16; +float HUD_PANEL_NUM = 17; // always last panel id + 1, please increment when adding a new panel string HUD_PANELNAME_WEAPONS = "weapons"; string HUD_PANELNAME_AMMO = "ammo"; @@ -656,8 +547,43 @@ string HUD_PANELNAME_PRESSEDKEYS = "pressedkeys"; string HUD_PANELNAME_CHAT = "chat"; string HUD_PANELNAME_ENGINEINFO = "engineinfo"; string HUD_PANELNAME_INFOMESSAGES = "infomessages"; +string HUD_PANELNAME_PHYSICS = "physics"; +string HUD_PANELNAME_CENTERPRINT = "centerprint"; float HUD_MENU_ENABLE = 0; #define SERVERFLAG_ALLOW_FULLBRIGHT 1 #define SERVERFLAG_TEAMPLAY 2 +#define SERVERFLAG_PLAYERSTATS 4 + +var vector autocvar_sv_player_maxs = '16 16 45'; +var vector autocvar_sv_player_mins = '-16 -16 -24'; +var vector autocvar_sv_player_viewoffset = '0 0 20'; +var vector autocvar_sv_player_crouch_maxs = '16 16 25'; +var vector autocvar_sv_player_crouch_mins = '-16 -16 -24'; +var vector autocvar_sv_player_crouch_viewoffset = '0 0 20'; +noref var vector autocvar_sv_player_headsize = '24 24 12'; + +#define PL_VIEW_OFS autocvar_sv_player_viewoffset +#define PL_MIN autocvar_sv_player_mins +#define PL_MAX autocvar_sv_player_maxs +#define PL_CROUCH_VIEW_OFS autocvar_sv_player_crouch_viewoffset +#define PL_CROUCH_MIN autocvar_sv_player_crouch_mins +#define PL_CROUCH_MAX autocvar_sv_player_crouch_maxs +#define PL_HEAD autocvar_sv_player_headsize + +// helpers +#define PL_VIEW_OFS_z autocvar_sv_player_viewoffset_z +#define PL_MIN_z autocvar_sv_player_mins_z +#define PL_MAX_z autocvar_sv_player_maxs_z +#define PL_CROUCH_VIEW_OFS_z autocvar_sv_player_crouch_viewoffset_z +#define PL_CROUCH_MIN_z autocvar_sv_player_mins_z +#define PL_HEAD_x autocvar_sv_player_headsize_x +#define PL_HEAD_y autocvar_sv_player_headsize_y +#define PL_HEAD_z autocvar_sv_player_headsize_z + +// spawnpoint prios +#define SPAWN_PRIO_NEAR_TEAMMATE_FOUND 200 +#define SPAWN_PRIO_NEAR_TEAMMATE_SAMETEAM 100 +#define SPAWN_PRIO_RACE_PREVIOUS_SPAWN 50 +#define SPAWN_PRIO_GOOD_DISTANCE 10 diff --git a/qcsrc/common/csqcmodel_settings.qh b/qcsrc/common/csqcmodel_settings.qh new file mode 100644 index 0000000000..bdeab298eb --- /dev/null +++ b/qcsrc/common/csqcmodel_settings.qh @@ -0,0 +1,84 @@ +// define this if svqc code wants to use .frame2 and .lerpfrac +#define CSQCMODEL_HAVE_TWO_FRAMES + +// don't define this ever +//#define CSQCMODEL_SUPPORT_GETTAGINFO_BEFORE_DRAW + +// a hack for Xonotic +#ifdef CSQC +# define TAG_ENTITY_NAME tag_networkentity +# define TAG_ENTITY_TYPE float +.float tag_networkentity; +#else +# define TAG_ENTITY_NAME tag_entity +# define TAG_ENTITY_TYPE entity +#endif + +// add properties you want networked to CSQC here +#define CSQCMODEL_EXTRAPROPERTIES \ + CSQCMODEL_PROPERTY(1, float, ReadShort, WriteShort, colormap) \ + CSQCMODEL_PROPERTY(2, float, ReadInt24_t, WriteInt24_t, effects) \ + CSQCMODEL_PROPERTY(4, float, ReadByte, WriteByte, modelflags) \ + CSQCMODEL_PROPERTY_SCALED(8, float, ReadByte, WriteByte, alpha, 254, -1, 254) \ + CSQCMODEL_PROPERTY(16, float, ReadByte, WriteByte, skin) \ + CSQCMODEL_PROPERTY(32, float, ReadApproxPastTime, WriteApproxPastTime, death_time) \ + CSQCMODEL_IF(!isplayer) \ + CSQCMODEL_PROPERTY(64, TAG_ENTITY_TYPE, ReadShort, WriteEntity, TAG_ENTITY_NAME) \ + CSQCMODEL_PROPERTY_SCALED(128, float, ReadByte, WriteByte, glowmod_x, 255, 0, 255) \ + CSQCMODEL_PROPERTY_SCALED(128, float, ReadByte, WriteByte, glowmod_y, 255, 0, 255) \ + CSQCMODEL_PROPERTY_SCALED(128, float, ReadByte, WriteByte, glowmod_z, 255, 0, 255) \ + CSQCMODEL_ENDIF +// TODO get rid of colormod/glowmod here, find good solution for nex charge glowmod hack; also get rid of some useless properties on non-players that only exist for CopyBody + +// add hook function calls here +#define CSQCMODEL_HOOK_PREUPDATE \ + CSQCModel_Hook_PreUpdate(isnew, isplayer, islocalplayer); +#define CSQCMODEL_HOOK_POSTUPDATE \ + CSQCModel_Hook_PostUpdate(isnew, isplayer, islocalplayer); +#define CSQCMODEL_HOOK_PREDRAW \ + CSQCModel_Hook_PreDraw(); +#define CSQCPLAYER_HOOK_POSTCAMERASETUP + +// force updates of player entities that often even if unchanged +#define CSQCPLAYER_FORCE_UPDATES 0.25 + +// mod must define: +//vector PL_MIN = ...; +//vector PL_MAX = ...; +//vector PL_VIEW_OFS = ...; +//vector PL_CROUCH_MIN = ...; +//vector PL_CROUCH_MAX = ...; +//vector PL_CROUCH_VIEW_OFS = ...; + +#ifdef SVQC +# ifdef NO_LEGACY_NETWORKING +# define CSQCMODEL_AUTOINIT() CSQCModel_LinkEntity() +# define CSQCMODEL_AUTOUPDATE() CSQCModel_CheckUpdate() +# else +.float iscsqcmodel; +float autocvar_sv_use_csqc_players; +# define CSQCMODEL_AUTOINIT() \ + if(autocvar_sv_use_csqc_players) \ + { \ + CSQCModel_LinkEntity(); \ + self.iscsqcmodel = 1; \ + } \ + else \ + self.iscsqcmodel = 0 +# define CSQCMODEL_AUTOUPDATE() \ + if(autocvar_sv_use_csqc_players && !self.iscsqcmodel) \ + { \ + CSQCModel_LinkEntity(); \ + self.iscsqcmodel = 1; \ + } \ + if(!autocvar_sv_use_csqc_players && self.iscsqcmodel) \ + { \ + CSQCModel_UnlinkEntity(); \ + self.iscsqcmodel = 0; \ + } \ + if(self.iscsqcmodel) \ + CSQCModel_CheckUpdate() +# endif +#endif + +#define CSQCMODEL_EF_RESPAWNGHOST EF_SELECTABLE diff --git a/qcsrc/common/explosion_equation.qc b/qcsrc/common/explosion_equation.qc new file mode 100644 index 0000000000..df71154be8 --- /dev/null +++ b/qcsrc/common/explosion_equation.qc @@ -0,0 +1,62 @@ +float explosion_calcpush_getmultiplier(vector explosion_v, vector target_v) +{ + float a; + a = explosion_v * (explosion_v - target_v); + + if(a <= 0) + // target is too fast to be hittable by this + return 0; + + a /= (explosion_v * explosion_v); + // we know we can divide by this, or above a would be == 0 + + return a; +} + +#if 0 +vector explosion_calcpush(vector explosion_v, float explosion_m, vector target_v, float target_m, float elasticity) +{ + // solution of the equations: + // v' = v + a vp // central hit + // m*v' + mp*vp' = m*v + mp*vp // conservation of momentum + // m*v'^2 + mp*vp'^2 = m*v^2 + mp*vp^2 // conservation of energy (ELASTIC hit) + // -> a = 0 // case 1: did not hit + // -> a = 2*mp*(vp^2 - vp.v) / ((m+mp) * vp^2) // case 2: did hit + // // non-elastic hits are somewhere between these two + + // this would be physically correct, but we don't do that + return explosion_v * explosion_calcpush_getmultiplier(explosion_v, target_v) * ( + (1 + elasticity) * ( + explosion_m + ) / ( + target_m + explosion_m + ) + ); // note: this factor is at least 0, at most 2 +} +#endif + +// simplified formula, tuned so that if the target has velocity 0, we get exactly the original force +vector damage_explosion_calcpush(vector explosion_f, vector target_v, float speedfactor) +{ + // if below 1, the formulas make no sense (and would cause superjumps) + if(speedfactor < 1) + return explosion_f; + +#if 0 + float m; + // find m so that + // speedfactor * (1 + e) * m / (1 + m) == 1 + m = 1 / ((1 + 0) * speedfactor - 1); + vector v; + v = explosion_calcpush(explosion_f * speedfactor, m, target_v, 1, 0); + // the factor we then get is: + // 1 + print(sprintf("MASS: %f\nv: %v -> %v\nENERGY BEFORE == %f + %f = %f\nENERGY AFTER >= %f\n", + m, + target_v, target_v + v, + target_v * target_v, m * explosion_f * speedfactor * explosion_f * speedfactor, target_v * target_v + m * explosion_f * speedfactor * explosion_f * speedfactor, + (target_v + v) * (target_v + v))); + return v; +#endif + return explosion_f * explosion_calcpush_getmultiplier(explosion_f * speedfactor, target_v); +} diff --git a/qcsrc/common/explosion_equation.qh b/qcsrc/common/explosion_equation.qh new file mode 100644 index 0000000000..c8630cdb19 --- /dev/null +++ b/qcsrc/common/explosion_equation.qh @@ -0,0 +1 @@ +vector damage_explosion_calcpush(vector explosion_f, vector target_v, float speedfactor); diff --git a/qcsrc/common/gamecommand.qc b/qcsrc/common/gamecommand.qc deleted file mode 100644 index 60c7199a65..0000000000 --- a/qcsrc/common/gamecommand.qc +++ /dev/null @@ -1,855 +0,0 @@ -#define MAX_RPN_STACK 16 -float rpn_db; -float rpn_error; -float rpn_sp; -string rpn_stack[MAX_RPN_STACK]; -string rpn_pop() { - if(rpn_sp > 0) { - --rpn_sp; - return rpn_stack[rpn_sp]; - } else { - print("rpn: stack underflow\n"); - rpn_error = TRUE; - return ""; - } -} -void rpn_push(string s) { - if(rpn_sp < MAX_RPN_STACK) { - rpn_stack[rpn_sp] = s; - ++rpn_sp; - } else { - print("rpn: stack overflow\n"); - rpn_error = TRUE; - } -} -string rpn_get() { - if(rpn_sp > 0) { - return rpn_stack[rpn_sp - 1]; - } else { - print("rpn: empty stack\n"); - rpn_error = TRUE; - return ""; - } -} -void rpn_set(string s) { - if(rpn_sp > 0) { - rpn_stack[rpn_sp - 1] = s; - } else { - print("rpn: empty stack\n"); - rpn_error = TRUE; - } -} -float rpn_getf() { return stof(rpn_get()); } -float rpn_popf() { return stof(rpn_pop()); } -void rpn_pushf(float f) { return rpn_push(ftos(f)); } -void rpn_setf(float f) { return rpn_set(ftos(f)); } - -#define NUM_MARKUPS 41 -float markup_init; -string markup_from[NUM_MARKUPS]; -string markup_to[NUM_MARKUPS]; -void GameCommand_MarkupInit() -{ - float i; - if (markup_init) - return; - markup_init = 1; - i = 0; - markup_from[i] = "&alien"; markup_to[i] = "\x12"; ++i; - markup_from[i] = "&:-)"; markup_to[i] = "\x13"; ++i; - markup_from[i] = "&:-("; markup_to[i] = "\x14"; ++i; - markup_from[i] = "&x-P"; markup_to[i] = "\x15"; ++i; - markup_from[i] = "&:-/"; markup_to[i] = "\x16"; ++i; - markup_from[i] = "&:-D"; markup_to[i] = "\x17"; ++i; - markup_from[i] = "&<<"; markup_to[i] = "\x18"; ++i; - markup_from[i] = "&>>"; markup_to[i] = "\x19"; ++i; - markup_from[i] = "&dot"; markup_to[i] = "\x1a"; ++i; - markup_from[i] = "&^_"; markup_to[i] = "\x1b"; ++i; - markup_from[i] = "&ysplat"; markup_to[i] = "\x1c"; ++i; - markup_from[i] = "&-]"; markup_to[i] = "\x1d"; ++i; - markup_from[i] = "&--"; markup_to[i] = "\x1e"; ++i; - markup_from[i] = "&[-"; markup_to[i] = "\x1f"; ++i; - markup_from[i] = "&s<"; markup_to[i] = "\x2c"; ++i; - markup_from[i] = "&s>"; markup_to[i] = "\x2e"; ++i; - markup_from[i] = "&<-"; markup_to[i] = "\x7f"; ++i; - markup_from[i] = "&[="; markup_to[i] = "\x80"; ++i; - markup_from[i] = "&=="; markup_to[i] = "\x81"; ++i; - markup_from[i] = "&=]"; markup_to[i] = "\x82"; ++i; - markup_from[i] = "&r!"; markup_to[i] = "\x84"; ++i; - markup_from[i] = "&|o|"; markup_to[i] = "\x85"; ++i; - markup_from[i] = "&|u|"; markup_to[i] = "\x86"; ++i; - markup_from[i] = "&|i|"; markup_to[i] = "\x87"; ++i; - markup_from[i] = "&|c|"; markup_to[i] = "\x88"; ++i; - markup_from[i] = "&[c]"; markup_to[i] = "\x89"; ++i; - markup_from[i] = "&[n]"; markup_to[i] = "\x8a"; ++i; - markup_from[i] = "&[]"; markup_to[i] = "\x8b"; ++i; - markup_from[i] = "&r?"; markup_to[i] = "\x8c"; ++i; - markup_from[i] = "&|>"; markup_to[i] = "\x8d"; ++i; - markup_from[i] = "&splat0"; markup_to[i] = "\x8e"; ++i; - markup_from[i] = "&splat1"; markup_to[i] = "\x8f"; ++i; - markup_from[i] = "&[["; markup_to[i] = "\x90"; ++i; - markup_from[i] = "&]]"; markup_to[i] = "\x91"; ++i; - markup_from[i] = "&splat2"; markup_to[i] = "\x9a"; ++i; - markup_from[i] = "&)("; markup_to[i] = "\x9b"; ++i; - markup_from[i] = "&splat3"; markup_to[i] = "\x9c"; ++i; - markup_from[i] = "&(."; markup_to[i] = "\x9d"; ++i; - markup_from[i] = "&.."; markup_to[i] = "\x9e"; ++i; - markup_from[i] = "&.)"; markup_to[i] = "\x9f"; ++i; - markup_from[i] = "&<|"; markup_to[i] = "\xff"; ++i; -} - -string GameCommand_Markup(string s2) -{ - float red, ccase, i, j; - string s, s3; - - GameCommand_MarkupInit(); - - s = ""; - - red = 0; - ccase = 0; - for(i = 0; i < strlen(s2); ++i) - { - for(j = 0; j < NUM_MARKUPS; ++j) - { - s3 = substring(s2, i, strlen(markup_from[j])); - if (s3 == markup_from[j]) - { - s = strcat(s, markup_to[j]); - i += strlen(markup_from[j]) - 1; - break; - } - } - - if(j == NUM_MARKUPS) - { - if(substring(s2, i, 2) == "&&") - { - s = strcat(s, strconv(ccase, red, red, "&")); - ++i; - } - else if(substring(s2, i, 2) == "&d") - { - red = 2; - ccase = 0; - ++i; - } - else if(substring(s2, i, 2) == "&a") - { - red = 2; - ccase = 2; - ++i; - } - else if(substring(s2, i, 2) == "&n") - { - red = 0; - ccase = 0; - ++i; - } - else - s = strcat(s, strconv(ccase, red, red, substring(s2, i, 1))); - } - } - - return s; -} - -float GameCommand_Generic(string command) -{ - float argc; - float i, j, f, n; - vector rgb; - string s, s2, c; - argc = tokenize_console(command); - if(argv(0) == "help") - { - print(" rpn EXPRESSION... - a RPN calculator.\n"); - print(" Operator description (x: string, s: set, f: float):\n"); - print(" x pop -----------------------------> : removes the top\n"); - print(" x dup -----------------------------> x x : duplicates the top\n"); - print(" x x exch --------------------------> x x : swap the top two\n"); - print(" /cvarname load --------------------> x : loads a cvar\n"); - print(" /cvarname x def -------------------> : writes to a cvar\n"); - print(" f f add|sub|mul|div|mod|max|min ---> f : adds/... two numbers\n"); - print(" f f eq|ne|gt|ge|lt|le -------------> f : compares two numbers\n"); - print(" f neg|abs|sgn|rand|floor|ceil------> f : negates/... a number\n"); - print(" f f f bound -----------------------> f : bounds the middle number\n"); - print(" f1 f2 b when ----------------------> f : f1 if b, f2 otherwise\n"); - print(" s s union|intersection|difference -> s : set operations\n"); - print(" s shuffle -------------------------> s : randomly arrange elements\n"); - print(" /key /value put -------------------> : set a database key\n"); - print(" /key get --------------------------> s : get a database value\n"); - print(" x dbpush --------------------------> : pushes the top onto the database\n"); - print(" dbpop|dbget -----------------------> x : removes/reads DB's top\n"); - print(" dblen|dbat ------------------------> f : gets the DB's size/cursor pos\n"); - print(" dbclr -----------------------------> : clear the DB\n"); - print(" s dbsave|dbload--------------------> : save/load the DB to/from a file\n"); - print(" x dbins ---------------------------> : moves the top into the DB\n"); - print(" dbext|dbread ----------------------> x : extract/get from the DB's cursor\n"); - print(" f dbmov|dbgoto --------------------> : move or set the DB's cursor\n"); - print(" s localtime -----------------------> s : formats the current local time\n"); - print(" s gmtime --------------------------> s : formats the current UTC time\n"); - print(" time ------------------------------> f : seconds since VM start\n"); - print(" Set operations operate on 'such''strings'.\n"); - print(" Unknown tokens insert their cvar value.\n"); - print(" maplist add map\n"); - print(" maplist remove map\n"); - print(" maplist shuffle\n"); - print(" maplist cleanup\n"); - print(" maplist maplist\n"); - print(" maplist lsmaps\n"); - print(" maplist lsnewmaps\n"); - print(" addtolist variable addedvalue\n"); - print(" records\n"); - print(" rankings (map argument optional)\n"); - return TRUE; - } - - if(argv(0) == "maplist") - { - if(argv(1) == "add" && argc == 3) - { - f = fopen(strcat("maps/", argv(2), ".bsp"), FILE_READ); - if(f != -1) - fclose(f); - else { - print("maplist: ERROR: ", argv(2), " does not exist!\n"); - return TRUE; - } - if(cvar_string("g_maplist") == "") - cvar_set("g_maplist", argv(2)); - else - cvar_set("g_maplist", strcat(argv(2), " ", cvar_string("g_maplist"))); - return TRUE; - } - else if(argv(1) == "remove" && argc == 3) - { - s = argv(2); - n = tokenizebyseparator(cvar_string("g_maplist"), " "); - s2 = ""; - for(i = 0; i < n; ++i) - if(argv(i) != s) - s2 = strcat(s2, " ", argv(i)); - s2 = substring(s2, 1, strlen(s2) - 1); - cvar_set("g_maplist", s2); - return TRUE; - } - else if(argv(1) == "shuffle" && argc == 2) - { - cvar_set("g_maplist", shufflewords(cvar_string("g_maplist"))); - return TRUE; - } - else if(argv(1) == "cleanup") - { - MapInfo_Enumerate(); - MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0); - n = tokenizebyseparator(cvar_string("g_maplist"), " "); - s2 = ""; - for(i = 0; i < n; ++i) - if(MapInfo_CheckMap(argv(i))) - s2 = strcat(s2, " ", argv(i)); - s2 = substring(s2, 1, strlen(s2) - 1); - cvar_set("g_maplist", s2); - return TRUE; - } - else if(argv(1) == "maplist") { - print(maplist_reply); - return TRUE; - } - else if(argv(1) == "lsmaps") { - print(lsmaps_reply); - return TRUE; - } - else if(argv(1) == "lsnewmaps") { - print(lsnewmaps_reply); - return TRUE; - } - } - else if(argc >= 3 && argv(0) == "red") - { - s = substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2)); - localcmd(strcat(argv(1), " ", GameCommand_Markup(s))); - return TRUE; - } - else if(argc >= 3 && crc16(0, argv(0)) == 38566 && crc16(0, strcat(argv(0), argv(0), argv(0))) == 59830) - { - // other test case - s = strconv(2, 0, 0, substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2))); - - n = floor(random() * 6 + 2); - - s2 = ""; - for(i = 0; i < n; ++i) - { - s2 = strcat(s2, "AH"); - } - - if(random() < 0.1) - s2 = strcat(substring(s2, 1, strlen(s2) - 1), "A"); - - if(s == "") - s = s2; - else - if(random() < 0.8) - s = strcat(s, " ", s2); - else - s = strcat(s2, " ", s); - - s2 = substring(s, strlen(s) - 2, 2); - if(s2 == "AH" || s2 == "AY") - s = strcat(s, "))"); - else - s = strcat(s, " ))"); - - if(random() < 0.1) - s = substring(s, 0, strlen(s) - 1); - - if(random() < 0.1) - s = strconv(1, 0, 0, s); - - localcmd(strcat(argv(1), " ", s)); - - return TRUE; - } - else if(argc >= 3 && crc16(0, argv(0)) == 3826 && crc16(0, strcat(argv(0), argv(0), argv(0))) == 55790) - { - // test case for terrencehill's color codes - s = strdecolorize(substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2))); - s2 = ""; - - n = strlen(s); - j = ((6 * max(1, floor(strlen(s)/32 + random() * 2 - 1))) / n) * (1 - 2 * (random() > 0.5)); - f = random() * 6; - - for(i = 0; i < n; ++i) - { - c = substring(s, i, 1); - - if(c == ";") - c = ":"; - else if(c == "^") - { - c = "^^"; - if(substring(s, i+1, 1) == "^") - ++i; - } - - if(c != " ") - { - rgb = hsl_to_rgb('1 0 0' * (j * i + f) + '0 1 .5'); - c = strcat(rgb_to_hexcolor(rgb), c); - } - s2 = strcat(s2, c); - } - - localcmd(strcat(argv(1), " ", s2)); - - return TRUE; - } - else if(argv(0) == "rpn") - { - if(!rpn_db) - { - rpn_db = db_create(); - db_put(rpn_db, "stack.pointer", "0"); - db_put(rpn_db, "stack.pos", "-1"); - } - if(argc >= 2) - { - float rpnpos; - string rpncmd; - float f2, f3; - rpn_sp = 0; - rpn_error = FALSE; - for(rpnpos = 1; rpnpos < argc; ++rpnpos) - { - rpncmd = argv(rpnpos); - f = strlen(rpncmd); - if(rpncmd == "") { - } else if(stof(substring(rpncmd, 0, 1)) > 0) { - rpn_push(rpncmd); - } else if(substring(rpncmd, 0, 1) == "0") { - rpn_push(rpncmd); - } else if(f >= 2 && substring(rpncmd, 0, 1) == "+") { - rpn_push(rpncmd); - } else if(f >= 2 && substring(rpncmd, 0, 1) == "-") { - rpn_push(rpncmd); - } else if(f >= 2 && substring(rpncmd, 0, 1) == "/") { - rpn_push(substring(rpncmd, 1, strlen(rpncmd) - 1)); - } else if(rpncmd == "clear") { - rpn_sp = 0; - } else if(rpncmd == "def" || rpncmd == "=") { - s = rpn_pop(); - s2 = rpn_pop(); - - if(s2 != "") - { -#ifdef MENUQC - registercvar(s2, "", 0); -#else - registercvar(s2, ""); -#endif - if(!rpn_error) // don't change cvars if a stack error had happened! - cvar_set(s2, s); - } - else - { - print("rpn: empty cvar name for 'def'\n"); - rpn_error = TRUE; - } - } else if(rpncmd == "defs" || rpncmd == "@") { - s = ""; - i = rpn_popf(); - j = (i == 0); - while(rpn_sp > 1 && (j || i > 0)) - { - s = strcat("/", rpn_pop(), " ", s); - --i; - } - s2 = rpn_pop(); - if(s2 != "") - { -#ifdef MENUQC - registercvar(s2, "", 0); -#else - registercvar(s2, ""); -#endif - if(!rpn_error) // don't change cvars if a stack error had happened! - cvar_set(s2, s); - } - else - { - print("rpn: empty cvar name for 'defs'\n"); - rpn_error = TRUE; - } - } else if(rpncmd == "load") { -#ifdef SVQC - rpn_set(cvar_string_builtin(rpn_get())); // cvar name comes from user -#else - rpn_set(cvar_string(rpn_get())); -#endif - } else if(rpncmd == "exch") { - s = rpn_pop(); - s2 = rpn_get(); - rpn_set(s); - rpn_push(s2); - } else if(rpncmd == "dup") { - rpn_push(rpn_get()); - } else if(rpncmd == "pop") { - rpn_pop(); - } else if(rpncmd == "add" || rpncmd == "+") { - f = rpn_popf(); - rpn_setf(rpn_getf() + f); - } else if(rpncmd == "sub" || rpncmd == "-") { - f = rpn_popf(); - rpn_setf(rpn_getf() - f); - } else if(rpncmd == "mul" || rpncmd == "*") { - f = rpn_popf(); - rpn_setf(rpn_getf() * f); - } else if(rpncmd == "div" || rpncmd == "/") { - f = rpn_popf(); - rpn_setf(rpn_getf() / f); - } else if(rpncmd == "mod" || rpncmd == "%") { - f = rpn_popf(); - f2 = rpn_getf(); - rpn_setf(f2 - f * floor(f2 / f)); - } else if(rpncmd == "abs") { - rpn_setf(fabs(rpn_getf())); - } else if(rpncmd == "sgn") { - f = rpn_getf(); - if(f < 0) - rpn_set("-1"); - else if(f > 0) - rpn_set("1"); - else - rpn_set("0"); - } else if(rpncmd == "neg" || rpncmd == "~") { - rpn_setf(-rpn_getf()); - } else if(rpncmd == "floor" || rpncmd == "f") { - rpn_setf(floor(rpn_getf())); - } else if(rpncmd == "ceil" || rpncmd == "c") { - rpn_setf(ceil(rpn_getf())); - } else if(rpncmd == "max") { - f = rpn_popf(); - f2 = rpn_getf(); - rpn_setf(max(f2, f)); - } else if(rpncmd == "min") { - f = rpn_popf(); - f2 = rpn_getf(); - rpn_setf(min(f2, f)); - } else if(rpncmd == "bound") { - f = rpn_popf(); - f2 = rpn_popf(); - f3 = rpn_getf(); - rpn_setf(bound(f3, f2, f)); - } else if(rpncmd == "when") { - f = rpn_popf(); - f2 = rpn_popf(); - f3 = rpn_getf(); - if(f) - rpn_setf(f3); - else - rpn_setf(f2); - } else if(rpncmd == ">" || rpncmd == "gt") { - f = rpn_popf(); - rpn_setf(rpn_getf() > f); - } else if(rpncmd == "<" || rpncmd == "lt") { - f = rpn_popf(); - rpn_setf(rpn_getf() < f); - } else if(rpncmd == "==" || rpncmd == "eq") { - f = rpn_popf(); - rpn_setf(rpn_getf() == f); - } else if(rpncmd == ">=" || rpncmd == "ge") { - f = rpn_popf(); - rpn_setf(rpn_getf() >= f); - } else if(rpncmd == "<=" || rpncmd == "le") { - f = rpn_popf(); - rpn_setf(rpn_getf() <= f); - } else if(rpncmd == "!=" || rpncmd == "ne") { - f = rpn_popf(); - rpn_setf(rpn_getf() != f); - } else if(rpncmd == "rand") { - rpn_setf(ceil(random() * rpn_getf()) - 1); - } else if(rpncmd == "crc16") { - rpn_setf(crc16(FALSE, rpn_get())); - } else if(rpncmd == "put") { - s2 = rpn_pop(); - if (!rpn_error) - { - s = rpn_pop(); - if (!rpn_error) - db_put(rpn_db, s, s2); - } - } else if(rpncmd == "get") { - s = rpn_pop(); - if (!rpn_error) - rpn_push(db_get(rpn_db, s)); - } else if(rpncmd == "dbpush") { - s = rpn_pop(); - if(!rpn_error) - { - i = stof(db_get(rpn_db, "stack.pointer")); - db_put(rpn_db, "stack.pointer", ftos(i+1)); - db_put(rpn_db, strcat("stack.", ftos(i)), s); - } - if(!i) - db_put(rpn_db, "stack.pos", "0"); - } else if(rpncmd == "dbpop") { - i = stof(db_get(rpn_db, "stack.pointer")); - if(i) - { - s = ftos(i-1); - db_put(rpn_db, "stack.pointer", s); - rpn_push(db_get(rpn_db, strcat("stack.", s))); - j = stof(db_get(rpn_db, "stack.pos")); - if(j >= i) - db_put(rpn_db, "stack.pos", ftos(i-2)); - } else { - rpn_error = 1; - print("rpn: database underflow\n"); - } - } else if(rpncmd == "dbget") { - - i = stof(db_get(rpn_db, "stack.pointer")); - if(i) - { - rpn_push(db_get(rpn_db, strcat("stack.", ftos(i-1)))); - } else { - rpn_error = 1; - print("rpn: database empty\n"); - } - } else if(rpncmd == "dblen") { - rpn_push(db_get(rpn_db, "stack.pointer")); - } else if(rpncmd == "dbclr") { - db_close(rpn_db); - rpn_db = db_create(); - db_put(rpn_db, "stack.pointer", "0"); - db_put(rpn_db, "stack.pos", "-1"); - } else if(rpncmd == "dbsave") { - s = rpn_pop(); - if(!rpn_error) - db_save(rpn_db, s); - } else if(rpncmd == "dbload") { - s = rpn_pop(); - if(!rpn_error) - { - db_close(rpn_db); - rpn_db = db_load(s); - } - } else if(rpncmd == "dbins") { - s = rpn_pop(); - if(!rpn_error) - //if(rpn_sp > 0) - { - j = stof(db_get(rpn_db, "stack.pointer")); - i = stof(db_get(rpn_db, "stack.pos")); - - if(i < 0) - { - i = 0; - db_put(rpn_db, "stack.pos", "0"); - } - - db_put(rpn_db, "stack.pointer", ftos(j+1)); - for(--j; j >= i; --j) - { - db_put(rpn_db, strcat("stack.", ftos(j+1)), - db_get(rpn_db, (strcat("stack.", ftos(j)))) - ); - } - db_put(rpn_db, strcat("stack.", ftos(i)), s); - } - } else if(rpncmd == "dbext") { - j = stof(db_get(rpn_db, "stack.pointer")); - i = stof(db_get(rpn_db, "stack.pos")); - if(!j) - { - rpn_error = TRUE; - print("rpn: empty database\n"); - } else { - --j; - rpn_push(db_get(rpn_db, strcat("stack.", ftos(i)))); - db_put(rpn_db, "stack.pointer", ftos(j)); - if(i == j) - { - db_put(rpn_db, "stack.pos", ftos(j-1)); - } else { - while(i < j) - { - db_put(rpn_db, strcat("stack.", ftos(i)), - db_get(rpn_db, (strcat("stack.", ftos(i+1)))) - ); - ++i; - } - } - } - } else if(rpncmd == "dbread") { - s = db_get(rpn_db, "stack.pos"); - if(stof(s) >= 0) - { - rpn_push(db_get(rpn_db, strcat("stack.", s))); - } else { - rpn_error = 1; - print("rpn: empty database\n"); - } - } else if(rpncmd == "dbat") { - rpn_push(db_get(rpn_db, "stack.pos")); - } else if(rpncmd == "dbmov") { - j = stof(db_get(rpn_db, "stack.pointer")); - i = stof(db_get(rpn_db, "stack.pos")); - i += rpn_popf(); - if(!rpn_error) - { - if(i < 0 || i >= j) - { - print("rpn: database cursor out of bounds\n"); - rpn_error = TRUE; - } - if(!rpn_error) - { - db_put(rpn_db, "stack.pos", ftos(i)); - } - } - } else if(rpncmd == "dbgoto") { - s = rpn_pop(); - j = stof(db_get(rpn_db, "stack.pointer")); - if(!j) - { - rpn_error = TRUE; - print("rpn: empty database, cannot move cursor\n"); - } - if(!rpn_error) - { - if(s == "end") - i = stof(db_get(rpn_db, "stack.pointer"))-1; - else if(s == "beg") - i = 0; - else - i = stof(s); - - j = stof(db_get(rpn_db, "stack.pointer")); - if(i < 0 || i >= j) - { - print("rpn: database cursor destination out of bounds\n"); - rpn_error = TRUE; - } - if(!rpn_error) - { - db_put(rpn_db, "stack.pos", ftos(i)); - } - } - } else if(rpncmd == "union") { - // s s2 union - s2 = rpn_pop(); - s = rpn_get(); - f = tokenize_console(s); - f2 = tokenize_console(strcat(s, " ", s2)); - // tokens 0..(f-1) represent s - // tokens f..f2 represent s2 - // UNION: add all tokens to s that are in s2 but not in s - s = ""; - for(i = 0; i < f; ++i) - s = strcat(s, " ", argv(i)); - for(i = f; i < f2; ++i) { - for(j = 0; j < f; ++j) - if(argv(i) == argv(j)) - goto skip_union; - s = strcat(s, " ", argv(i)); -:skip_union - } - if(substring(s, 0, 1) == " ") - s = substring(s, 1, 99999); - rpn_set(s); - tokenize_console(command); - } else if(rpncmd == "intersection") { - // s s2 intersection - s2 = rpn_pop(); - s = rpn_get(); - f = tokenize_console(s); - f2 = tokenize_console(strcat(s, " ", s2)); - // tokens 0..(f-1) represent s - // tokens f..f2 represent s2 - // INTERSECTION: keep only the tokens from s that are also in s2 - s = ""; - for(i = 0; i < f; ++i) { - for(j = f; j < f2; ++j) - if(argv(i) == argv(j)) - { - s = strcat(s, " ", argv(i)); - break; - } - } - if(substring(s, 0, 1) == " ") - s = substring(s, 1, 99999); - rpn_set(s); - tokenize_console(command); - } else if(rpncmd == "difference") { - // s s2 difference - s2 = rpn_pop(); - s = rpn_get(); - f = tokenize_console(s); - f2 = tokenize_console(strcat(s, " ", s2)); - // tokens 0..(f-1) represent s - // tokens f..f2 represent s2 - // DIFFERENCE: keep only the tokens from s that are not in s2 - s = ""; - for(i = 0; i < f; ++i) { - for(j = f; j < f2; ++j) - if(argv(i) == argv(j)) - goto skip_difference; - s = strcat(s, " ", argv(i)); -:skip_difference - } - if(substring(s, 0, 1) == " ") - s = substring(s, 1, 99999); - rpn_set(s); - tokenize_console(command); - } else if(rpncmd == "shuffle") { - // s shuffle - s = rpn_get(); - f = tokenize_console(s); - - for(i = 0; i < f - 1; ++i) { - // move a random item from i..f-1 to position i - s = ""; - f2 = floor(random() * (f - i) + i); - for(j = 0; j < i; ++j) - s = strcat(s, " ", argv(j)); - s = strcat(s, " ", argv(f2)); - for(j = i; j < f; ++j) - if(j != f2) - s = strcat(s, " ", argv(j)); - f = tokenize_console(s); - } - - if(substring(s, 0, 1) == " ") - s = substring(s, 1, 99999); - rpn_set(s); - tokenize_console(command); - } else if(rpncmd == "fexists_assert") { - s = rpn_pop(); - if(!rpn_error) - { - f = fopen(s, FILE_READ); - if(f != -1) - fclose(f); - else { - print("rpn: ERROR: ", s, " does not exist!\n"); - rpn_error = TRUE; - } - } - } else if(rpncmd == "fexists") { - s = rpn_get(); - if(!rpn_error) - { - f = fopen(s, FILE_READ); - if(f != -1) { - fclose(f); - rpn_setf(1); - } else { - rpn_setf(0); - } - } - } else if(rpncmd == "localtime") { - rpn_set(strftime(TRUE, rpn_get())); - } else if(rpncmd == "gmtime") { - rpn_set(strftime(FALSE, rpn_get())); - } else if(rpncmd == "time") { - rpn_pushf(time); - } else { - rpn_push(cvar_string(rpncmd)); - } - if(rpn_error) - break; - } - while(rpn_sp > 0) - { - s = rpn_pop(); - print("rpn: still on stack: ", s, "\n"); - } - return TRUE; - } - } else if(argv(0) == "addtolist") { - if(argc >= 2) - { - s = argv(1); - s2 = argv(2); - if(cvar_string(s) == "") - cvar_set(s, s2); - else { - n = tokenizebyseparator(cvar_string(s), " "); - for(i = 0; i < n; ++i) - if(argv(i) == s2) - return TRUE; // already in list - cvar_set(s, strcat(s2, " ", cvar_string(s))); - } - } - return TRUE; - } - else if(argv(0) == "records") { - print(records_reply); - return TRUE; - } - else if(argv(0) == "ladder") { - print(ladder_reply); - return TRUE; - } - else if(argv(0) == "rankings") { - print(rankings_reply); - return TRUE; -#ifdef MENUQC - } else if(argv(0) == "cp") { - if(argc >= 2) - { - s = argv(1); - for(i = 2; i < argc; ++i) - s = strcat(s, " ", argv(i)); - centerprint(unescape(s)); - } - return TRUE; -#endif - } - - return FALSE; -} diff --git a/qcsrc/common/if-this-file-errors-scroll-up-and-fix-the-warnings.fteqccfail b/qcsrc/common/if-this-file-errors-scroll-up-and-fix-the-warnings.fteqccfail new file mode 100644 index 0000000000..e69de29bb2 diff --git a/qcsrc/common/items.qc b/qcsrc/common/items.qc index 5387c05aae..3ddf8099f5 100644 --- a/qcsrc/common/items.qc +++ b/qcsrc/common/items.qc @@ -19,6 +19,18 @@ void register_weapon(float id, float(float) func, float ammotype, float i, float e.model2 = strzone(strcat("wpn-", e.mdl)); e.impulse = i; e.bot_pickupbasevalue = pickupbasevalue; + if(ammotype & IT_SHELLS) + e.ammo_field = ammo_shells; + else if(ammotype & IT_NAILS) + e.ammo_field = ammo_nails; + else if(ammotype & IT_ROCKETS) + e.ammo_field = ammo_rockets; + else if(ammotype & IT_CELLS) + e.ammo_field = ammo_cells; + else if(ammotype & IT_FUEL) + e.ammo_field = ammo_fuel; + else + e.ammo_field = ammo_batteries; } float w_null(float dummy) { diff --git a/qcsrc/common/items.qh b/qcsrc/common/items.qh index 64d7abd644..c98ff786b9 100644 --- a/qcsrc/common/items.qh +++ b/qcsrc/common/items.qh @@ -2,13 +2,14 @@ float BOT_PICKUP_RATING_LOW = 2500; float BOT_PICKUP_RATING_MID = 5000; float BOT_PICKUP_RATING_HIGH = 10000; -float WEP_TYPE_OTHER = 0x00; // e.g: Hook, Port-o-launch, etc -float WEP_TYPE_SPLASH = 0x01; -float WEP_TYPE_HITSCAN = 0x02; -float WEP_TYPEMASK = 0x0F; -float WEP_FLAG_CANCLIMB = 0x10; -float WEP_FLAG_NORMAL = 0x20; -float WEP_FLAG_HIDDEN = 0x40; +float WEP_TYPE_OTHER = 0x00; // e.g: Hook, Port-o-launch, etc +float WEP_TYPE_SPLASH = 0x01; +float WEP_TYPE_HITSCAN = 0x02; +float WEP_TYPEMASK = 0x0F; +float WEP_FLAG_CANCLIMB = 0x10; +float WEP_FLAG_NORMAL = 0x20; +float WEP_FLAG_HIDDEN = 0x40; +float WEP_FLAG_RELOADABLE = 0x80; float IT_UNLIMITED_WEAPON_AMMO = 1; // when this bit is set, using a weapon does not reduce ammo. Checkpoints can give this powerup. @@ -60,6 +61,14 @@ string W_FixWeaponOrder(string order, float complete); string W_NameWeaponOrder(string order); string W_NumberWeaponOrder(string order); +// ammo types +.float ammo_shells; +.float ammo_nails; +.float ammo_rockets; +.float ammo_cells; +.float ammo_fuel; +.float ammo_batteries; // dummy + // entity properties of weaponinfo: .float weapon; // WEP_... .float weapons; // WEPBIT_... @@ -73,8 +82,7 @@ string W_NumberWeaponOrder(string order); .float impulse; // weapon impulse .float bot_pickupbasevalue; // bot weapon priority .string model2; // wpn- sprite name - - +..float ammo_field; // main ammo field // dynamic weapon adding float w_null(float dummy); diff --git a/qcsrc/common/mapinfo.qc b/qcsrc/common/mapinfo.qc index 35a827f900..1b32c9d1d5 100644 --- a/qcsrc/common/mapinfo.qc +++ b/qcsrc/common/mapinfo.qc @@ -49,6 +49,7 @@ void MapInfo_Cache_Store() // now store all the stuff bufstr_set(_MapInfo_Cache_Buf_IndexToMapData, i, MapInfo_Map_bspname); bufstr_set(_MapInfo_Cache_Buf_IndexToMapData, ++i, MapInfo_Map_title); + bufstr_set(_MapInfo_Cache_Buf_IndexToMapData, ++i, MapInfo_Map_titlestring); bufstr_set(_MapInfo_Cache_Buf_IndexToMapData, ++i, MapInfo_Map_description); bufstr_set(_MapInfo_Cache_Buf_IndexToMapData, ++i, MapInfo_Map_author); bufstr_set(_MapInfo_Cache_Buf_IndexToMapData, ++i, ftos(MapInfo_Map_supportedGametypes)); @@ -71,11 +72,13 @@ float MapInfo_Cache_Retrieve(string map) // now retrieve all the stuff MapInfo_Map_bspname = bufstr_get(_MapInfo_Cache_Buf_IndexToMapData, i); MapInfo_Map_title = bufstr_get(_MapInfo_Cache_Buf_IndexToMapData, ++i); + MapInfo_Map_titlestring = bufstr_get(_MapInfo_Cache_Buf_IndexToMapData, ++i); MapInfo_Map_description = bufstr_get(_MapInfo_Cache_Buf_IndexToMapData, ++i); MapInfo_Map_author = bufstr_get(_MapInfo_Cache_Buf_IndexToMapData, ++i); MapInfo_Map_supportedGametypes = stof(bufstr_get(_MapInfo_Cache_Buf_IndexToMapData, ++i)); MapInfo_Map_supportedFeatures = stof(bufstr_get(_MapInfo_Cache_Buf_IndexToMapData, ++i)); MapInfo_Map_flags = stof(bufstr_get(_MapInfo_Cache_Buf_IndexToMapData, ++i)); + return 1; } @@ -324,6 +327,10 @@ float _MapInfo_Generate(string pFilename) // 0: failure, 1: ok ent, 2: ok bsp { } else if(startsWith(v, "weapon_")) MapInfo_Map_supportedFeatures |= MAPINFO_FEATURE_WEAPONS; + else if(startsWith(v, "turret_")) + MapInfo_Map_supportedFeatures |= MAPINFO_FEATURE_TURRETS; + else if(startsWith(v, "vehicle_")) + MapInfo_Map_supportedFeatures |= MAPINFO_FEATURE_VEHICLES; else if(v == "target_music" || v == "trigger_music") _MapInfo_Map_worldspawn_music = string_null; // don't use regular BGM } @@ -379,6 +386,7 @@ float _MapInfo_Generate(string pFilename) // 0: failure, 1: ok ent, 2: ok bsp void _MapInfo_Map_Reset() { MapInfo_Map_title = "<TITLE>"; + MapInfo_Map_titlestring = "<TITLE>"; MapInfo_Map_description = "<DESCRIPTION>"; MapInfo_Map_author = "<AUTHOR>"; MapInfo_Map_supportedGametypes = 0; @@ -409,7 +417,10 @@ string _MapInfo_GetDefault(float t) case MAPINFO_TYPE_NEXBALL: return "5 20 0"; case MAPINFO_TYPE_CTS: return "20 0 0"; case MAPINFO_TYPE_FREEZETAG: return "10 20 0"; - case MAPINFO_TYPE_KEEPAWAY: return "30 20 0"; + // NOTE: DO NOT ADD ANY MORE GAME TYPES HERE + // THIS IS JUST LEGACY SUPPORT FOR NEXUIZ MAPS + // ONLY ADD NEW STUFF TO _MapInfo_GetDefaultEx + // THIS FUNCTION WILL EVENTUALLY BE REMOVED default: return ""; } } @@ -461,11 +472,11 @@ void _MapInfo_Map_ApplyGametype(string s, float pWantedType, float pThisType, fl { sa = car(s); if(sa != "") - if(cvar("g_ctf_win_mode") < 2) - cvar_set("fraglimit", sa); + cvar_set("fraglimit", sa); s = cdr(s); } + /* keepaway wuz here if(pWantedType == MAPINFO_TYPE_KEEPAWAY) { sa = car(s); @@ -473,7 +484,8 @@ void _MapInfo_Map_ApplyGametype(string s, float pWantedType, float pThisType, fl cvar_set("fraglimit", sa); s = cdr(s); } - + */ + // rc = timelimit timelimit_qualification laps laps_teamplay if(pWantedType == MAPINFO_TYPE_RACE) { @@ -522,26 +534,11 @@ void _MapInfo_Map_ApplyGametype(string s, float pWantedType, float pThisType, fl string _MapInfo_GetDefaultEx(float t) { - switch(t) - { - case MAPINFO_TYPE_DEATHMATCH: return "timelimit=20 pointlimit=30 leadlimit=0"; - case MAPINFO_TYPE_TEAM_DEATHMATCH: return "timelimit=20 pointlimit=50 teams=2 leadlimit=0"; - case MAPINFO_TYPE_DOMINATION: return "timelimit=20 pointlimit=200 teams=2 leadlimit=0"; - case MAPINFO_TYPE_CTF: return "timelimit=20 pointlimit=300 caplimit=10 leadlimit=0"; - case MAPINFO_TYPE_RUNEMATCH: return "timelimit=20 pointlimit=200 leadlimit=0"; - case MAPINFO_TYPE_LMS: return "timelimit=20 lives=9 leadlimit=0"; - case MAPINFO_TYPE_ARENA: return "timelimit=20 pointlimit=10 leadlimit=0"; - case MAPINFO_TYPE_CA: return "timelimit=20 pointlimit=10 leadlimit=0"; - case MAPINFO_TYPE_KEYHUNT: return "timelimit=20 pointlimit=1000 teams=3 leadlimit=0"; - case MAPINFO_TYPE_ASSAULT: return "timelimit=20"; - case MAPINFO_TYPE_RACE: return "timelimit=20 qualifying_timelimit=5 laplimit=7 teamlaplimit=15 leadlimit=0"; - case MAPINFO_TYPE_ONSLAUGHT: return "timelimit=20"; - case MAPINFO_TYPE_NEXBALL: return "timelimit=20 pointlimit=5 leadlimit=0"; - case MAPINFO_TYPE_CTS: return "timelimit=20 skill=-1"; - case MAPINFO_TYPE_FREEZETAG: return "timelimit=20 pointlimit=10 teams=2 leadlimit=0"; - case MAPINFO_TYPE_KEEPAWAY: return "timelimit=20 pointlimit=30"; - default: return ""; - } + entity e; + for(e = MapInfo_Type_first; e; e = e.enemy) + if(t == e.weapons) + return e.model2; + return ""; } void _MapInfo_Map_ApplyGametypeEx(string s, float pWantedType, float pThisType) @@ -549,7 +546,6 @@ void _MapInfo_Map_ApplyGametypeEx(string s, float pWantedType, float pThisType) string sa, k, v; float p; string fraglimit_normal; - string fraglimit_caps; string fraglimit_teams; MapInfo_Map_supportedGametypes |= pThisType; @@ -567,7 +563,6 @@ void _MapInfo_Map_ApplyGametypeEx(string s, float pWantedType, float pThisType) cvar_set("g_race_qualifying_timelimit", cvar_defstring("g_race_qualifying_timelimit")); fraglimit_normal = string_null; - fraglimit_caps = string_null; fraglimit_teams = string_null; s = strcat(_MapInfo_GetDefaultEx(pWantedType), " ", s); @@ -599,14 +594,10 @@ void _MapInfo_Map_ApplyGametypeEx(string s, float pWantedType, float pThisType) { cvar_set("leadlimit", v); } - else if(k == "pointlimit" || k == "fraglimit" || k == "lives" || k == "laplimit") + else if(k == "pointlimit" || k == "fraglimit" || k == "lives" || k == "laplimit" || k == "caplimit") { fraglimit_normal = v; } - else if(k == "caplimit") - { - fraglimit_caps = v; - } else if(k == "teampointlimit" || k == "teamlaplimit") { fraglimit_teams = v; @@ -631,12 +622,7 @@ void _MapInfo_Map_ApplyGametypeEx(string s, float pWantedType, float pThisType) } } - if(pWantedType == MAPINFO_TYPE_CTF && cvar("g_ctf_win_mode") < 2) - { - if(fraglimit_caps) - cvar_set("fraglimit", fraglimit_caps); - } - else if(pWantedType == MAPINFO_TYPE_RACE && cvar("g_race_teams") >= 2) + if(pWantedType == MAPINFO_TYPE_RACE && cvar("g_race_teams") >= 2) { if(fraglimit_teams) cvar_set("fraglimit", fraglimit_teams); @@ -650,46 +636,33 @@ void _MapInfo_Map_ApplyGametypeEx(string s, float pWantedType, float pThisType) float MapInfo_Type_FromString(string t) { - if (t == "dm") return MAPINFO_TYPE_DEATHMATCH; - else if(t == "tdm") return MAPINFO_TYPE_TEAM_DEATHMATCH; - else if(t == "dom") return MAPINFO_TYPE_DOMINATION; - else if(t == "ctf") return MAPINFO_TYPE_CTF; - else if(t == "rune") return MAPINFO_TYPE_RUNEMATCH; - else if(t == "lms") return MAPINFO_TYPE_LMS; - else if(t == "arena") return MAPINFO_TYPE_ARENA; - else if(t == "ca") return MAPINFO_TYPE_CA; - else if(t == "kh") return MAPINFO_TYPE_KEYHUNT; - else if(t == "as") return MAPINFO_TYPE_ASSAULT; - else if(t == "ons") return MAPINFO_TYPE_ONSLAUGHT; - else if(t == "rc") return MAPINFO_TYPE_RACE; - else if(t == "nexball") return MAPINFO_TYPE_NEXBALL; - else if(t == "cts") return MAPINFO_TYPE_CTS; - else if(t == "freezetag") return MAPINFO_TYPE_FREEZETAG; - else if(t == "keepaway") return MAPINFO_TYPE_KEEPAWAY; - else if(t == "all") return MAPINFO_TYPE_ALL; - else return 0; + entity e; + if(t == "all") + return MAPINFO_TYPE_ALL; + for(e = MapInfo_Type_first; e; e = e.enemy) + if(t == e.mdl) + return e.weapons; + return 0; } string MapInfo_Type_ToString(float t) { - if (t == MAPINFO_TYPE_DEATHMATCH) return "dm"; - else if(t == MAPINFO_TYPE_TEAM_DEATHMATCH) return "tdm"; - else if(t == MAPINFO_TYPE_DOMINATION) return "dom"; - else if(t == MAPINFO_TYPE_CTF) return "ctf"; - else if(t == MAPINFO_TYPE_RUNEMATCH) return "rune"; - else if(t == MAPINFO_TYPE_LMS) return "lms"; - else if(t == MAPINFO_TYPE_ARENA) return "arena"; - else if(t == MAPINFO_TYPE_CA) return "ca"; - else if(t == MAPINFO_TYPE_KEYHUNT) return "kh"; - else if(t == MAPINFO_TYPE_ASSAULT) return "as"; - else if(t == MAPINFO_TYPE_ONSLAUGHT) return "ons"; - else if(t == MAPINFO_TYPE_RACE) return "rc"; - else if(t == MAPINFO_TYPE_NEXBALL) return "nexball"; - else if(t == MAPINFO_TYPE_CTS) return "cts"; - else if(t == MAPINFO_TYPE_FREEZETAG) return "freezetag"; - else if(t == MAPINFO_TYPE_KEEPAWAY) return "keepaway"; - else if(t == MAPINFO_TYPE_ALL) return "all"; - else return ""; + entity e; + if(t == MAPINFO_TYPE_ALL) + return "all"; + for(e = MapInfo_Type_first; e; e = e.enemy) + if(t == e.weapons) + return e.mdl; + return ""; +} + +string MapInfo_Type_ToText(float t) +{ + entity e; + for(e = MapInfo_Type_first; e; e = e.enemy) + if(t == e.weapons) + return e.message; + return _("@!#%'n Tuba Throwing"); } void _MapInfo_Parse_Settemp(string pFilename, string acl, float type, string s, float recurse) @@ -792,12 +765,37 @@ void _MapInfo_Parse_Settemp(string pFilename, string acl, float type, string s, } } +float MapInfo_isRedundant(string fn, string t) +{ + // normalize file name + fn = strreplace("_", "-", fn); + + // normalize visible title + t = strreplace(": ", "-", t); + t = strreplace(":", "-", t); + t = strreplace(" ", "-", t); + t = strreplace("_", "-", t); + t = strreplace("'", "-", t); + + if(!strcasecmp(fn, t)) + return TRUE; + + // we allow the visible title to have punctuation the file name does + // not, but not vice versa + t = strreplace("-", "", t); + + if(!strcasecmp(fn, t)) + return TRUE; + + return FALSE; +} + // load info about a map by name into the MapInfo_Map_* globals -float MapInfo_Get_ByName(string pFilename, float pAllowGenerate, float pGametypeToSet) +float MapInfo_Get_ByName_NoFallbacks(string pFilename, float pAllowGenerate, float pGametypeToSet) { string fn; string s, t; - float fh, fh2; + float fh; float r, f, n, i, p; string acl; @@ -863,6 +861,14 @@ float MapInfo_Get_ByName(string pFilename, float pAllowGenerate, float pGametype fputs(fh, "has weapons\n"); else fputs(fh, "// uncomment this if you added weapon pickups: has weapons\n"); + if(MapInfo_Map_supportedFeatures & MAPINFO_FEATURE_TURRETS) + fputs(fh, "has turrets\n"); + else + fputs(fh, "// uncomment this if you added turrets: has turrets\n"); + if(MapInfo_Map_supportedFeatures & MAPINFO_FEATURE_VEHICLES) + fputs(fh, "has weapons\n"); + else + fputs(fh, "// uncomment this if you added vehicles: has vehicles\n"); if(MapInfo_Map_flags & MAPINFO_FLAG_FRUSTRATING) fputs(fh, "frustrating\n"); @@ -870,12 +876,8 @@ float MapInfo_Get_ByName(string pFilename, float pAllowGenerate, float pGametype if(MapInfo_Map_supportedGametypes & i) fputs(fh, sprintf("gametype %s // defaults: %s\n", MapInfo_Type_ToString(i), _MapInfo_GetDefaultEx(i))); - fh2 = fopen(strcat("scripts/", pFilename, ".arena"), FILE_READ); - if(fh2 >= 0) - { - fclose(fh2); + if(fexists(strcat("scripts/", pFilename, ".arena"))) fputs(fh, "settemp_for_type all sv_q3acompat_machineshotgunswap 1\n"); - } fputs(fh, "// optional: fog density red green blue alpha mindist maxdist\n"); fputs(fh, "// optional: settemp_for_type (all|gametypename) cvarname value\n"); @@ -925,6 +927,8 @@ float MapInfo_Get_ByName(string pFilename, float pAllowGenerate, float pGametype { t = car(s); s = cdr(s); if (t == "weapons") MapInfo_Map_supportedFeatures |= MAPINFO_FEATURE_WEAPONS; + else if(t == "turrets") MapInfo_Map_supportedFeatures |= MAPINFO_FEATURE_TURRETS; + else if(t == "vehicles") MapInfo_Map_supportedFeatures |= MAPINFO_FEATURE_VEHICLES; else if(t == "new_toys") MapInfo_Map_supportedFeatures |= MAPINFO_FEATURE_WEAPONS; else dprint("Map ", pFilename, " supports unknown feature ", t, ", ignored\n"); @@ -945,6 +949,7 @@ float MapInfo_Get_ByName(string pFilename, float pAllowGenerate, float pGametype { t = car(s); s = cdr(s); f = MapInfo_Type_FromString(t); + print("Map ", pFilename, " contains the legacy 'type' keyword which is deprecated and will be removed in the future. Please migrate the mapinfo file to 'gametype'.\n"); if(f) _MapInfo_Map_ApplyGametype (s, pGametypeToSet, f, TRUE); else @@ -1044,6 +1049,31 @@ float MapInfo_Get_ByName(string pFilename, float pAllowGenerate, float pGametype } fclose(fh); + if(MapInfo_Map_title == "<TITLE>") + MapInfo_Map_titlestring = MapInfo_Map_bspname; + else if(MapInfo_isRedundant(MapInfo_Map_bspname, MapInfo_Map_title)) + MapInfo_Map_titlestring = MapInfo_Map_title; + else + MapInfo_Map_titlestring = sprintf(_("%s: %s"), MapInfo_Map_bspname, MapInfo_Map_title); + + MapInfo_Cache_Store(); + if(MapInfo_Map_supportedGametypes != 0) + return r; + dprint("Map ", pFilename, " supports no game types, ignored\n"); + return 0; +} +float MapInfo_Get_ByName(string pFilename, float pAllowGenerate, float pGametypeToSet) +{ + float r = MapInfo_Get_ByName_NoFallbacks(pFilename, pAllowGenerate, pGametypeToSet); + + if(cvar("g_tdm_on_dm_maps")) + { + // if this is set, all DM maps support TDM too + if not(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_TEAM_DEATHMATCH) + if(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_DEATHMATCH) + _MapInfo_Map_ApplyGametypeEx ("", pGametypeToSet, MAPINFO_TYPE_TEAM_DEATHMATCH); + } + if(pGametypeToSet) { if(!(MapInfo_Map_supportedGametypes & pGametypeToSet)) @@ -1054,11 +1084,7 @@ float MapInfo_Get_ByName(string pFilename, float pAllowGenerate, float pGametype } } - MapInfo_Cache_Store(); - if(MapInfo_Map_supportedGametypes != 0) - return r; - dprint("Map ", pFilename, " supports no game types, ignored\n"); - return 0; + return r; } float MapInfo_FindName(string s) @@ -1126,38 +1152,16 @@ float MapInfo_CurrentFeatures() float MapInfo_CurrentGametype() { - if(cvar("g_domination")) - return MAPINFO_TYPE_DOMINATION; - else if(cvar("g_ctf")) - return MAPINFO_TYPE_CTF; - else if(cvar("g_runematch")) - return MAPINFO_TYPE_RUNEMATCH; - else if(cvar("g_tdm")) - return MAPINFO_TYPE_TEAM_DEATHMATCH; - else if(cvar("g_assault")) - return MAPINFO_TYPE_ASSAULT; - else if(cvar("g_lms")) - return MAPINFO_TYPE_LMS; - else if(cvar("g_arena")) - return MAPINFO_TYPE_ARENA; - else if(cvar("g_ca")) - return MAPINFO_TYPE_CA; - else if(cvar("g_keyhunt")) - return MAPINFO_TYPE_KEYHUNT; - else if(cvar("g_onslaught")) - return MAPINFO_TYPE_ONSLAUGHT; - else if(cvar("g_race")) - return MAPINFO_TYPE_RACE; - else if(cvar("g_nexball")) - return MAPINFO_TYPE_NEXBALL; - else if(cvar("g_cts")) - return MAPINFO_TYPE_CTS; - else if(cvar("g_freezetag")) - return MAPINFO_TYPE_FREEZETAG; - else if(cvar("g_keepaway")) - return MAPINFO_TYPE_KEEPAWAY; - else - return MAPINFO_TYPE_DEATHMATCH; + float prev; + entity e; + prev = cvar("gamecfg"); + for(e = MapInfo_Type_first; e; e = e.enemy) + if(cvar(e.netname)) + if(prev != e.weapons) + return e.weapons; + if(prev) + return prev; + return MAPINFO_TYPE_DEATHMATCH; } float _MapInfo_CheckMap(string s) // returns 0 if the map can't be played with the current settings, 1 otherwise @@ -1179,52 +1183,14 @@ float MapInfo_CheckMap(string s) // returns 0 if the map can't be played with th return r; } -string MapInfo_GetGameTypeCvar(float t) -{ - switch(t) - { - case MAPINFO_TYPE_DEATHMATCH: return "g_dm"; - case MAPINFO_TYPE_TEAM_DEATHMATCH: return "g_tdm"; - case MAPINFO_TYPE_DOMINATION: return "g_domination"; - case MAPINFO_TYPE_CTF: return "g_ctf"; - case MAPINFO_TYPE_RUNEMATCH: return "g_runematch"; - case MAPINFO_TYPE_LMS: return "g_lms"; - case MAPINFO_TYPE_ARENA: return "g_arena"; - case MAPINFO_TYPE_CA: return "g_ca"; - case MAPINFO_TYPE_KEYHUNT: return "g_kh"; - case MAPINFO_TYPE_ASSAULT: return "g_assault"; - case MAPINFO_TYPE_ONSLAUGHT: return "g_onslaught"; - case MAPINFO_TYPE_RACE: return "g_race"; - case MAPINFO_TYPE_NEXBALL: return "g_nexball"; - case MAPINFO_TYPE_FREEZETAG: return "g_freezetag"; - case MAPINFO_TYPE_CTS: return "g_cts"; - case MAPINFO_TYPE_KEEPAWAY: return "g_keepaway"; - default: return ""; - } -} - void MapInfo_SwitchGameType(float t) { - cvar_set("gamecfg", "0"); - cvar_set("g_dm", (t == MAPINFO_TYPE_DEATHMATCH) ? "1" : "0"); - cvar_set("g_tdm", (t == MAPINFO_TYPE_TEAM_DEATHMATCH) ? "1" : "0"); - cvar_set("g_domination", (t == MAPINFO_TYPE_DOMINATION) ? "1" : "0"); - cvar_set("g_ctf", (t == MAPINFO_TYPE_CTF) ? "1" : "0"); - cvar_set("g_runematch", (t == MAPINFO_TYPE_RUNEMATCH) ? "1" : "0"); - cvar_set("g_lms", (t == MAPINFO_TYPE_LMS) ? "1" : "0"); - cvar_set("g_arena", (t == MAPINFO_TYPE_ARENA) ? "1" : "0"); - cvar_set("g_ca", (t == MAPINFO_TYPE_CA) ? "1" : "0"); - cvar_set("g_keyhunt", (t == MAPINFO_TYPE_KEYHUNT) ? "1" : "0"); - cvar_set("g_assault", (t == MAPINFO_TYPE_ASSAULT) ? "1" : "0"); - cvar_set("g_onslaught", (t == MAPINFO_TYPE_ONSLAUGHT) ? "1" : "0"); - cvar_set("g_race", (t == MAPINFO_TYPE_RACE) ? "1" : "0"); - cvar_set("g_nexball", (t == MAPINFO_TYPE_NEXBALL) ? "1" : "0"); - cvar_set("g_cts", (t == MAPINFO_TYPE_CTS) ? "1" : "0"); - cvar_set("g_freezetag", (t == MAPINFO_TYPE_FREEZETAG) ? "1" : "0"); - cvar_set("g_keepaway", (t == MAPINFO_TYPE_KEEPAWAY) ? "1" : "0"); + entity e; + for(e = MapInfo_Type_first; e; e = e.enemy) + cvar_set(e.netname, (t == e.weapons) ? "1" : "0"); } -void MapInfo_LoadMap(string s) +void MapInfo_LoadMap(string s, float reinit) { MapInfo_Map_supportedGametypes = 0; // we shouldn't need this, as LoadMapSettings already fixes the gametype @@ -1233,7 +1199,12 @@ void MapInfo_LoadMap(string s) // print("EMERGENCY: can't play the selected map in the given game mode. Falling back to DM.\n"); // MapInfo_SwitchGameType(MAPINFO_TYPE_DEATHMATCH); //} - localcmd(strcat("\nsettemp_restore\nchangelevel ", s, "\n")); + + cvar_settemp_restore(); + if(reinit) + localcmd(strcat("\nmap ", s, "\n")); + else + localcmd(strcat("\nchangelevel ", s, "\n")); } string MapInfo_ListAllowedMaps(float pRequiredFlags, float pForbiddenFlags) @@ -1251,16 +1222,53 @@ string MapInfo_ListAllowedMaps(float pRequiredFlags, float pForbiddenFlags) return substring(out, 1, strlen(out) - 1); } +string MapInfo_ListAllAllowedMaps(float pRequiredFlags, float pForbiddenFlags) +{ + string out; + float i; + + // to make absolutely sure: + MapInfo_Enumerate(); + MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, pRequiredFlags, pForbiddenFlags, 0); + + out = ""; + for(i = 0; i < MapInfo_count; ++i) + out = strcat(out, " ", _MapInfo_GlobItem(MapInfo_FilterList_Lookup(i))); + + MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), pRequiredFlags, pForbiddenFlags, 0); + + return substring(out, 1, strlen(out) - 1); +} + +void MapInfo_LoadMapSettings_SaveGameType(float t) +{ + MapInfo_SwitchGameType(t); + cvar_set("gamecfg", ftos(t)); + MapInfo_LoadedGametype = t; +} + void MapInfo_LoadMapSettings(string s) // to be called from worldspawn { - float t, t0; + float t; + + t = MapInfo_CurrentGametype(); + MapInfo_LoadMapSettings_SaveGameType(t); + if(!_MapInfo_CheckMap(s)) // with underscore, it keeps temps { + if(cvar("g_mapinfo_allow_unsupported_modes_and_let_stuff_break")) + { + print("EMERGENCY: can't play the selected map in the given game mode. Working with only the override settings.\n"); + _MapInfo_Map_ApplyGametypeEx("", t, t); + return; // do not call Get_ByName! + } + if(MapInfo_Map_supportedGametypes == 0) { print("Mapinfo system is not functional at all. Assuming deathmatch.\n"); MapInfo_Map_supportedGametypes = MAPINFO_TYPE_DEATHMATCH; - _MapInfo_Map_ApplyGametypeEx("", t0, t0); + MapInfo_LoadMapSettings_SaveGameType(MAPINFO_TYPE_DEATHMATCH); + _MapInfo_Map_ApplyGametypeEx("", MAPINFO_TYPE_DEATHMATCH, MAPINFO_TYPE_DEATHMATCH); return; // do not call Get_ByName! } @@ -1270,29 +1278,19 @@ void MapInfo_LoadMapSettings(string s) // to be called from worldspawn t *= 2; MapInfo_Map_supportedGametypes = floor(MapInfo_Map_supportedGametypes / 2); } + // t is now a supported mode! - t0 = MapInfo_CurrentGametype(); - if(cvar("g_mapinfo_allow_unsupported_modes_and_let_stuff_break")) - { - print("EMERGENCY: can't play the selected map in the given game mode. Working with only the override settings.\n"); - cvar_settemp_restore(); - _MapInfo_Map_ApplyGametypeEx("", t0, t0); - return; // do not call Get_ByName! - } - else - { - print("EMERGENCY: can't play the selected map in the given game mode. Falling back to a supported mode.\n"); - MapInfo_SwitchGameType(t); - } + print("EMERGENCY: can't play the selected map in the given game mode. Falling back to a supported mode.\n"); + MapInfo_LoadMapSettings_SaveGameType(t); } - cvar_settemp_restore(); - MapInfo_Get_ByName(s, 1, MapInfo_CurrentGametype()); + MapInfo_Get_ByName(s, 1, t); } void MapInfo_ClearTemps() { MapInfo_Map_bspname = string_null; MapInfo_Map_title = string_null; + MapInfo_Map_titlestring = string_null; MapInfo_Map_description = string_null; MapInfo_Map_author = string_null; MapInfo_Map_clientstuff = string_null; diff --git a/qcsrc/common/mapinfo.qh b/qcsrc/common/mapinfo.qh index 12026689b8..e47a28369f 100644 --- a/qcsrc/common/mapinfo.qh +++ b/qcsrc/common/mapinfo.qh @@ -1,22 +1,89 @@ -float MAPINFO_TYPE_DEATHMATCH = 1; -float MAPINFO_TYPE_LMS = 2; -float MAPINFO_TYPE_ARENA = 4; -float MAPINFO_TYPE_RUNEMATCH = 8; -float MAPINFO_TYPE_RACE = 16; -float MAPINFO_TYPE_CTS = 32; -float MAPINFO_TYPE_TEAM_DEATHMATCH = 64; -float MAPINFO_TYPE_CTF = 128; -float MAPINFO_TYPE_CA = 256; -float MAPINFO_TYPE_DOMINATION = 512; -float MAPINFO_TYPE_KEYHUNT = 1024; -float MAPINFO_TYPE_ASSAULT = 2048; -float MAPINFO_TYPE_ONSLAUGHT = 4096; -float MAPINFO_TYPE_NEXBALL = 8192; -float MAPINFO_TYPE_FREEZETAG = 16384; -float MAPINFO_TYPE_KEEPAWAY = 32768; -float MAPINFO_TYPE_ALL = 65535; // this has to include all above bits +var float MAPINFO_TYPE_ALL = 0; +entity MapInfo_Type_first; +entity MapInfo_Type_last; +.entity enemy; // internal next pointer + +.float weapons; // game type ID +.string netname; // game type name as in cvar (with g_ prefix) +.string mdl; // game type short name +.string message; // human readable name +.string model2; // game type defaults + +#define REGISTER_GAMETYPE(hname,sname,g_name,NAME,defaults) \ + var float MAPINFO_TYPE_##NAME; \ + var entity MapInfo_Type##g_name; \ + void RegisterGametypes_##g_name() \ + { \ + MAPINFO_TYPE_##NAME = MAPINFO_TYPE_ALL + 1; \ + MAPINFO_TYPE_ALL |= MAPINFO_TYPE_##NAME; \ + MapInfo_Type##g_name = spawn(); \ + MapInfo_Type##g_name.weapons = MAPINFO_TYPE_##NAME; \ + MapInfo_Type##g_name.netname = #g_name; \ + MapInfo_Type##g_name.mdl = #sname; \ + MapInfo_Type##g_name.message = hname; \ + MapInfo_Type##g_name.model2 = defaults; \ + if(!MapInfo_Type_first) \ + MapInfo_Type_first = MapInfo_Type##g_name; \ + if(MapInfo_Type_last) \ + MapInfo_Type_last.enemy = MapInfo_Type##g_name; \ + MapInfo_Type_last = MapInfo_Type##g_name; \ + } \ + ACCUMULATE_FUNCTION(RegisterGametypes, RegisterGametypes_##g_name) + +#define IS_GAMETYPE(NAME) \ + (MapInfo_LoadedGametype == MAPINFO_TYPE_##NAME) + +REGISTER_GAMETYPE(_("Deathmatch"),dm,g_dm,DEATHMATCH,"timelimit=20 pointlimit=30 leadlimit=0") +#define g_dm IS_GAMETYPE(DEATHMATCH) + +REGISTER_GAMETYPE(_("Last Man Standing"),lms,g_lms,LMS,"timelimit=20 lives=9 leadlimit=0") +#define g_lms IS_GAMETYPE(LMS) + +REGISTER_GAMETYPE(_("Arena"),arena,g_arena,ARENA,"timelimit=20 pointlimit=10 leadlimit=0") +#define g_arena IS_GAMETYPE(ARENA) + +REGISTER_GAMETYPE(_("Runematch"),rune,g_runematch,RUNEMATCH,"timelimit=20 pointlimit=200 leadlimit=0") +#define g_runematch IS_GAMETYPE(RUNEMATCH) + +REGISTER_GAMETYPE(_("Race"),rc,g_race,RACE,"timelimit=20 qualifying_timelimit=5 laplimit=7 teamlaplimit=15 leadlimit=0") +#define g_race IS_GAMETYPE(RACE) + +REGISTER_GAMETYPE(_("Race CTS"),cts,g_cts,CTS,"timelimit=20 skill=-1") +#define g_cts IS_GAMETYPE(CTS) + +REGISTER_GAMETYPE(_("Team Deathmatch"),tdm,g_tdm,TEAM_DEATHMATCH,"timelimit=20 pointlimit=50 teams=2 leadlimit=0") +#define g_tdm IS_GAMETYPE(TEAM_DEATHMATCH) + +REGISTER_GAMETYPE(_("Capture the Flag"),ctf,g_ctf,CTF,"timelimit=20 caplimit=10 leadlimit=0") +#define g_ctf IS_GAMETYPE(CTF) + +REGISTER_GAMETYPE(_("Clan Arena"),ca,g_ca,CA,"timelimit=20 pointlimit=10 leadlimit=0") +#define g_ca IS_GAMETYPE(CA) + +REGISTER_GAMETYPE(_("Domination"),dom,g_domination,DOMINATION,"timelimit=20 pointlimit=200 teams=2 leadlimit=0") +#define g_domination IS_GAMETYPE(DOMINATION) + +REGISTER_GAMETYPE(_("Key Hunt"),kh,g_keyhunt,KEYHUNT,"timelimit=20 pointlimit=1000 teams=3 leadlimit=0") +#define g_keyhunt IS_GAMETYPE(KEYHUNT) + +REGISTER_GAMETYPE(_("Assault"),as,g_assault,ASSAULT,"timelimit=20") +#define g_assault IS_GAMETYPE(ASSAULT) + +REGISTER_GAMETYPE(_("Onslaught"),ons,g_onslaught,ONSLAUGHT,"timelimit=20") +#define g_onslaught IS_GAMETYPE(ONSLAUGHT) + +REGISTER_GAMETYPE(_("Nexball"),nexball,g_nexball,NEXBALL,"timelimit=20 pointlimit=5 leadlimit=0") +#define g_nexball IS_GAMETYPE(NEXBALL) + +REGISTER_GAMETYPE(_("Freeze Tag"),freezetag,g_freezetag,FREEZETAG,"timelimit=20 pointlimit=10 teams=2 leadlimit=0") +#define g_freezetag IS_GAMETYPE(FREEZETAG) + +REGISTER_GAMETYPE(_("Keepaway"),keepaway,g_keepaway,KEEPAWAY,"timelimit=20 pointlimit=30") +#define g_keepaway IS_GAMETYPE(KEEPAWAY) float MAPINFO_FEATURE_WEAPONS = 1; // not defined for minstagib-only maps +float MAPINFO_FEATURE_VEHICLES = 2; +float MAPINFO_FEATURE_TURRETS = 4; float MAPINFO_FLAG_HIDDEN = 1; // not in lsmaps/menu/vcall/etc., can just be changed to manually float MAPINFO_FLAG_FORBIDDEN = 2; // don't even allow the map by a cvar setting that allows hidden maps @@ -27,6 +94,7 @@ float MapInfo_count; // info about a map that MapInfo loads string MapInfo_Map_bspname; string MapInfo_Map_title; +string MapInfo_Map_titlestring; // either bspname: title or just title, depending on whether bspname is redundant string MapInfo_Map_description; string MapInfo_Map_author; string MapInfo_Map_clientstuff; // not in cache, only for map load @@ -64,19 +132,22 @@ string MapInfo_FixName(string s); // play a map float MapInfo_CheckMap(string s); // returns 0 if the map can't be played with the current settings -void MapInfo_LoadMap(string s); +void MapInfo_LoadMap(string s, float reinit); // list all maps for the current game type string MapInfo_ListAllowedMaps(float pFlagsRequired, float pFlagsForbidden); +// list all allowed maps (for any game type) +string MapInfo_ListAllAllowedMaps(float pFlagsRequired, float pFlagsForbidden); // gets a gametype from a string float MapInfo_Type_FromString(string t); string MapInfo_Type_ToString(float t); -string MapInfo_GetGameTypeCvar(float t); +string MapInfo_Type_ToText(float t); void MapInfo_SwitchGameType(float t); // to be called from worldspawn to set up cvars void MapInfo_LoadMapSettings(string s); +float MapInfo_LoadedGametype; // game type that was active during map load void MapInfo_Cache_Destroy(); // disable caching void MapInfo_Cache_Create(); // enable caching @@ -87,4 +158,4 @@ void MapInfo_ClearTemps(); // call this when done with mapinfo for this frame void MapInfo_Shutdown(); // call this in the shutdown handler #define MAPINFO_SETTEMP_ACL_USER cvar_string("g_mapinfo_settemp_acl") -#define MAPINFO_SETTEMP_ACL_SYSTEM "-g_mapinfo_* -rcon_* -settemp_* -_* -g_ban* +*" +#define MAPINFO_SETTEMP_ACL_SYSTEM "-g_mapinfo_* -rcon_* -_* -g_ban* +*" diff --git a/qcsrc/common/urllib.qc b/qcsrc/common/urllib.qc new file mode 100644 index 0000000000..1bc0650273 --- /dev/null +++ b/qcsrc/common/urllib.qc @@ -0,0 +1,382 @@ +// files +.float url_fh; +#define URL_FH_CURL -1 +#define URL_FH_STDOUT -2 + +// URLs +.string url_url; +.float url_wbuf; +.float url_wbufpos; +.float url_rbuf; +.float url_rbufpos; +.float url_id; +.url_ready_func url_ready; +.entity url_ready_pass; + +entity url_fromid[NUM_URL_ID]; +float autocvar__urllib_nextslot; + +float url_URI_Get_Callback(float id, float status, string data) +{ + if(id < MIN_URL_ID) + return 0; + id -= MIN_URL_ID; + if(id >= NUM_URL_ID) + return 0; + entity e; + e = url_fromid[id]; + if(!e) + return 0; + if(e.url_rbuf >= 0 || e.url_wbuf >= 0) + { + print(sprintf("WARNING: handle %d (%s) has already received data?!?\n", id + NUM_URL_ID, e.url_url)); + return 0; + } + + // whatever happens, we will remove the URL from the list of IDs + url_fromid[id] = world; + + // if we get here, we MUST have both buffers cleared + if(e.url_rbuf != -1 || e.url_wbuf != -1 || e.url_fh != URL_FH_CURL) + error("url_URI_Get_Callback: not a request waiting for data"); + + if(status == 0) + { + // WE GOT DATA! + float n, i; + n = tokenizebyseparator(data, "\n"); + e.url_rbuf = buf_create(); + if(e.url_rbuf < 0) + { + print("url_URI_Get_Callback: out of memory in buf_create\n"); + e.url_ready(e, e.url_ready_pass, URL_READY_ERROR); + strunzone(e.url_url); + remove(e); + return 1; + } + e.url_rbufpos = 0; + if(e.url_rbuf < 0) + { + print("url_URI_Get_Callback: out of memory in buf_create\n"); + e.url_ready(e, e.url_ready_pass, URL_READY_ERROR); + strunzone(e.url_url); + remove(e); + return 1; + } + for(i = 0; i < n; ++i) + bufstr_set(e.url_rbuf, i, argv(i)); + e.url_ready(e, e.url_ready_pass, URL_READY_CANREAD); + return 1; + } + else + { + // an ERROR + e.url_ready(e, e.url_ready_pass, -fabs(status)); + strunzone(e.url_url); + remove(e); + return 1; + } +} + +void url_single_fopen(string url, float mode, url_ready_func rdy, entity pass) +{ + entity e; + float i; + if(strstrofs(url, "://", 0) >= 0) + { + switch(mode) + { + case FILE_WRITE: + case FILE_APPEND: + // collect data to a stringbuffer for a POST request + // attempts to close will result in a reading handle + + // create a writing end that does nothing yet + e = spawn(); + e.classname = "url_single_fopen_file"; + e.url_url = strzone(url); + e.url_fh = URL_FH_CURL; + e.url_wbuf = buf_create(); + if(e.url_wbuf < 0) + { + print("url_single_fopen: out of memory in buf_create\n"); + rdy(e, pass, URL_READY_ERROR); + strunzone(e.url_url); + remove(e); + return; + } + e.url_wbufpos = 0; + e.url_rbuf = -1; + e.url_ready = rdy; + e.url_ready_pass = pass; + rdy(e, pass, URL_READY_CANWRITE); + break; + + case FILE_READ: + // read data only + + // get slot for HTTP request + for(i = autocvar__urllib_nextslot; i < NUM_URL_ID; ++i) + if(url_fromid[i] == world) + break; + if(i >= NUM_URL_ID) + { + for(i = 0; i < autocvar__urllib_nextslot; ++i) + if(url_fromid[i] == world) + break; + if(i >= autocvar__urllib_nextslot) + { + print("url_single_fopen: too many concurrent requests\n"); + rdy(world, pass, URL_READY_ERROR); + return; + } + } + + // GET the data + if(!crypto_uri_postbuf(url, i + MIN_URL_ID, string_null, string_null, -1, 0)) + { + print("url_single_fopen: failure in crypto_uri_postbuf\n"); + rdy(world, pass, URL_READY_ERROR); + return; + } + + // Make a dummy handle object (no buffers at + // all). Wait for data to come from the + // server, then call the callback + e = spawn(); + e.classname = "url_single_fopen_file"; + e.url_url = strzone(url); + e.url_fh = URL_FH_CURL; + e.url_rbuf = -1; + e.url_wbuf = -1; + e.url_ready = rdy; + e.url_ready_pass = pass; + e.url_id = i; + url_fromid[i] = e; + + // make sure this slot won't be reused quickly even on map change + cvar_set("_urllib_nextslot", ftos(mod(i + 1, NUM_URL_ID))); + break; + } + } + else if(url == "-") + { + switch(mode) + { + case FILE_WRITE: + case FILE_APPEND: + e = spawn(); + e.classname = "url_single_fopen_stdout"; + e.url_fh = URL_FH_STDOUT; + e.url_ready = rdy; + e.url_ready_pass = pass; + rdy(e, pass, URL_READY_CANWRITE); + break; + case FILE_READ: + print("url_single_fopen: cannot open '-' for reading\n"); + rdy(world, pass, URL_READY_ERROR); + break; + } + } + else + { + float fh; + fh = fopen(url, mode); + if(fh < 0) + { + rdy(world, pass, URL_READY_ERROR); + return; + } + else + { + e = spawn(); + e.classname = "url_single_fopen_file"; + e.url_fh = fh; + e.url_ready = rdy; + e.url_ready_pass = pass; + if(mode == FILE_READ) + rdy(e, pass, URL_READY_CANREAD); + else + rdy(e, pass, URL_READY_CANWRITE); + } + } +} + +// close a file +void url_fclose(entity e) +{ + float i; + + if(e.url_fh == URL_FH_CURL) + { + if(e.url_rbuf == -1 || e.url_wbuf != -1) // not(post GET/POST request) + if(e.url_rbuf != -1 || e.url_wbuf == -1) // not(pre POST request) + error("url_fclose: not closable in current state"); + + // closing an URL! + if(e.url_wbuf >= 0) + { + // we are closing the write end (HTTP POST request) + + // get slot for HTTP request + for(i = autocvar__urllib_nextslot; i < NUM_URL_ID; ++i) + if(url_fromid[i] == world) + break; + if(i >= NUM_URL_ID) + { + for(i = 0; i < autocvar__urllib_nextslot; ++i) + if(url_fromid[i] == world) + break; + if(i >= autocvar__urllib_nextslot) + { + print("url_fclose: too many concurrent requests\n"); + e.url_ready(e,e.url_ready_pass, URL_READY_ERROR); + buf_del(e.url_wbuf); + strunzone(e.url_url); + remove(e); + return; + } + } + + // POST the data + if(!crypto_uri_postbuf(e.url_url, i + MIN_URL_ID, "text/plain", "", e.url_wbuf, 0)) + { + print("url_fclose: failure in crypto_uri_postbuf\n"); + e.url_ready(e, e.url_ready_pass, URL_READY_ERROR); + buf_del(e.url_wbuf); + strunzone(e.url_url); + remove(e); + return; + } + + // delete write end. File handle is now in unusable + // state. Wait for data to come from the server, then + // call the callback + buf_del(e.url_wbuf); + e.url_wbuf = -1; + e.url_id = i; + url_fromid[i] = e; + + // make sure this slot won't be reused quickly even on map change + cvar_set("_urllib_nextslot", ftos(mod(i + 1, NUM_URL_ID))); + } + else + { + // we have READ all data, just close + e.url_ready(e, e.url_ready_pass, URL_READY_CLOSED); + buf_del(e.url_rbuf); + strunzone(e.url_url); + remove(e); + } + } + else if(e.url_fh == URL_FH_STDOUT) + { + e.url_ready(e, e.url_ready_pass, URL_READY_CLOSED); // closing creates no reading handle + remove(e); + } + else + { + // file + fclose(e.url_fh); + e.url_ready(e, e.url_ready_pass, URL_READY_CLOSED); // closing creates no reading handle + remove(e); + } +} + +// with \n (blame FRIK_FILE) +string url_fgets(entity e) +{ + if(e.url_fh == URL_FH_CURL) + { + if(e.url_rbuf == -1) + error("url_fgets: not readable in current state"); + // curl + string s; + s = bufstr_get(e.url_rbuf, e.url_rbufpos); + e.url_rbufpos += 1; + return s; + } + else if(e.url_fh == URL_FH_STDOUT) + { + // stdout + return string_null; + } + else + { + // file + return fgets(e.url_fh); + } +} + +// without \n (blame FRIK_FILE) +void url_fputs(entity e, string s) +{ + if(e.url_fh == URL_FH_CURL) + { + if(e.url_wbuf == -1) + error("url_fputs: not writable in current state"); + // curl + bufstr_set(e.url_wbuf, e.url_wbufpos, s); + e.url_wbufpos += 1; + } + else if(e.url_fh == URL_FH_STDOUT) + { + // stdout + print(s); + } + else + { + // file + fputs(e.url_fh, s); + } +} + +// multi URL object, tries URLs separated by space in sequence +void url_multi_ready(entity fh, entity me, float status) +{ + float n; + if(status == URL_READY_ERROR || status < 0) + { + if(status == -422) // Unprocessable Entity + { + print("uri_multi_ready: got HTTP error 422, data is in unusable format - not continuing\n"); + me.url_ready(fh, me.url_ready_pass, status); + strunzone(me.url_url); + remove(me); + return; + } + me.cnt += 1; + n = tokenize_console(me.url_url); + if(n <= me.cnt) + { + me.url_ready(fh, me.url_ready_pass, status); + strunzone(me.url_url); + remove(me); + return; + } + url_single_fopen(argv(me.cnt), me.lip, url_multi_ready, me); + return; + } + me.url_ready(fh, me.url_ready_pass, status); +} +void url_multi_fopen(string url, float mode, url_ready_func rdy, entity pass) +{ + float n; + n = tokenize_console(url); + if(n <= 0) + { + print("url_multi_fopen: need at least one URL\n"); + rdy(world, pass, URL_READY_ERROR); + return; + } + + entity me; + me = spawn(); + me.classname = "url_multi"; + me.url_url = strzone(url); + me.cnt = 0; + me.lip = mode; + me.url_ready = rdy; + me.url_ready_pass = pass; + url_single_fopen(argv(0), mode, url_multi_ready, me); +} diff --git a/qcsrc/common/urllib.qh b/qcsrc/common/urllib.qh new file mode 100644 index 0000000000..f92178b2f6 --- /dev/null +++ b/qcsrc/common/urllib.qh @@ -0,0 +1,18 @@ +float URL_READY_ERROR = -1; +float URL_READY_CLOSED = 0; +float URL_READY_CANWRITE = 1; +float URL_READY_CANREAD = 2; +// errors: -1, or negative HTTP status code +typedef void(entity handle, entity pass, float status) url_ready_func; + +void url_single_fopen(string url, float mode, url_ready_func rdy, entity pass); +void url_fclose(entity e); +string url_fgets(entity e); +void url_fputs(entity e, string s); + +// returns true if handled +float url_URI_Get_Callback(float id, float status, string data); +#define MIN_URL_ID 128 +#define NUM_URL_ID 64 + +void url_multi_fopen(string url, float mode, url_ready_func rdy, entity pass); diff --git a/qcsrc/common/util-pre.qh b/qcsrc/common/util-pre.qh index bc086e4a9a..5a22d3612d 100644 --- a/qcsrc/common/util-pre.qh +++ b/qcsrc/common/util-pre.qh @@ -1,2 +1,8 @@ #pragma flag enable subscope #pragma flag enable lo + +#ifndef NOCOMPAT +//# define WORKAROUND_XON010 +//# define COMPAT_XON010_CHANNELS +# define COMPAT_XON050_ENGINE +#endif diff --git a/qcsrc/common/util.qc b/qcsrc/common/util.qc index 1bfbca6ae1..57e6531132 100644 --- a/qcsrc/common/util.qc +++ b/qcsrc/common/util.qc @@ -39,10 +39,20 @@ void wordwrap_sprint(string s, float l) #endif #endif +#ifndef SVQC +string draw_UseSkinFor(string pic) +{ + if(substring(pic, 0, 1) == "/") + return substring(pic, 1, strlen(pic)-1); + else + return strcat(draw_currentSkin, "/", pic); +} +#endif + string unescape(string in) { - local float i, len; - local string str, s; + float i, len; + string str, s; // but it doesn't seem to be necessary in my tests at least in = strzone(in); @@ -72,8 +82,8 @@ string unescape(string in) void wordwrap_cb(string s, float l, void(string) callback) { - local string c; - local float lleft, i, j, wlen; + string c; + float lleft, i, j, wlen; s = strzone(s); lleft = l; @@ -195,21 +205,21 @@ vector colormapPaletteColor(float c, float isPants) { switch(c) { - case 0: return '0.800000 0.800000 0.800000'; - case 1: return '0.600000 0.400000 0.000000'; + case 0: return '1.000000 1.000000 1.000000'; + case 1: return '1.000000 0.333333 0.000000'; case 2: return '0.000000 1.000000 0.501961'; case 3: return '0.000000 1.000000 0.000000'; case 4: return '1.000000 0.000000 0.000000'; - case 5: return '0.000000 0.658824 1.000000'; + case 5: return '0.000000 0.666667 1.000000'; case 6: return '0.000000 1.000000 1.000000'; case 7: return '0.501961 1.000000 0.000000'; case 8: return '0.501961 0.000000 1.000000'; case 9: return '1.000000 0.000000 1.000000'; case 10: return '1.000000 0.000000 0.501961'; - case 11: return '0.600000 0.600000 0.600000'; + case 11: return '0.000000 0.000000 1.000000'; case 12: return '1.000000 1.000000 0.000000'; - case 13: return '0.000000 0.313725 1.000000'; - case 14: return '1.000000 0.501961 0.000000'; + case 13: return '0.000000 0.333333 1.000000'; + case 14: return '1.000000 0.666667 0.000000'; case 15: if(isPants) return @@ -236,6 +246,16 @@ string fstrunzone(string s) return sc; } +float fexists(string f) +{ + float fh; + fh = fopen(f, FILE_READ); + if (fh < 0) + return FALSE; + fclose(fh); + return TRUE; +} + // Databases (hash tables) #define DB_BUCKETS 8192 void db_save(float db, string pFilename) @@ -360,7 +380,10 @@ float buf_load(string pFilename) return -1; fh = fopen(pFilename, FILE_READ); if(fh < 0) - return buf; + { + buf_del(buf); + return -1; + } i = 0; while((l = fgets(fh))) { @@ -383,27 +406,6 @@ void buf_save(float buf, string pFilename) fclose(fh); } -string GametypeNameFromType(float g) -{ - if (g == GAME_DEATHMATCH) return "dm"; - else if (g == GAME_TEAM_DEATHMATCH) return "tdm"; - else if (g == GAME_DOMINATION) return "dom"; - else if (g == GAME_CTF) return "ctf"; - else if (g == GAME_RUNEMATCH) return "rune"; - else if (g == GAME_LMS) return "lms"; - else if (g == GAME_ARENA) return "arena"; - else if (g == GAME_CA) return "ca"; - else if (g == GAME_KEYHUNT) return "kh"; - else if (g == GAME_ONSLAUGHT) return "ons"; - else if (g == GAME_ASSAULT) return "as"; - else if (g == GAME_RACE) return "rc"; - else if (g == GAME_NEXBALL) return "nexball"; - else if (g == GAME_CTS) return "cts"; - else if (g == GAME_FREEZETAG) return "freezetag"; - else if (g == GAME_KEEPAWAY) return "ka"; - return "dm"; -} - string mmsss(float tenths) { float minutes; @@ -510,31 +512,31 @@ float invertLengthLog(float x) vector decompressShortVector(float data) { vector out; - float pitch, yaw, len; + float p, y, len; if(data == 0) return '0 0 0'; - pitch = (data & 0xF000) / 0x1000; - yaw = (data & 0x0F80) / 0x80; - len = (data & 0x007F); + p = (data & 0xF000) / 0x1000; + y = (data & 0x0F80) / 0x80; + len = (data & 0x007F); - //print("\ndecompress: pitch ", ftos(pitch)); print("yaw ", ftos(yaw)); print("len ", ftos(len), "\n"); + //print("\ndecompress: p ", ftos(p)); print("y ", ftos(y)); print("len ", ftos(len), "\n"); - if(pitch == 0) + if(p == 0) { out_x = 0; out_y = 0; - if(yaw == 31) + if(y == 31) out_z = -1; else out_z = +1; } else { - yaw = .19634954084936207740 * yaw; - pitch = .19634954084936207740 * pitch - 1.57079632679489661922; - out_x = cos(yaw) * cos(pitch); - out_y = sin(yaw) * cos(pitch); - out_z = -sin(pitch); + y = .19634954084936207740 * y; + p = .19634954084936207740 * p - 1.57079632679489661922; + out_x = cos(y) * cos(p); + out_y = sin(y) * cos(p); + out_z = -sin(p); } //print("decompressed: ", vtos(out), "\n"); @@ -545,7 +547,7 @@ vector decompressShortVector(float data) float compressShortVector(vector vec) { vector ang; - float pitch, yaw, len; + float p, y, len; if(vlen(vec) == 0) return 0; //print("compress: ", vtos(vec), "\n"); @@ -557,21 +559,21 @@ float compressShortVector(vector vec) error("BOGUS vectoangles"); //print("angles: ", vtos(ang), "\n"); - pitch = floor(0.5 + (ang_x + 90) * 16 / 180) & 15; // -90..90 to 0..14 - if(pitch == 0) + p = floor(0.5 + (ang_x + 90) * 16 / 180) & 15; // -90..90 to 0..14 + if(p == 0) { if(vec_z < 0) - yaw = 31; + y = 31; else - yaw = 30; + y = 30; } else - yaw = floor(0.5 + ang_y * 32 / 360) & 31; // 0..360 to 0..32 + y = floor(0.5 + ang_y * 32 / 360) & 31; // 0..360 to 0..32 len = invertLengthLog(vlen(vec)); - //print("compressed: pitch ", ftos(pitch)); print("yaw ", ftos(yaw)); print("len ", ftos(len), "\n"); + //print("compressed: p ", ftos(p)); print("y ", ftos(y)); print("len ", ftos(len), "\n"); - return (pitch * 0x1000) + (yaw * 0x80) + len; + return (p * 0x1000) + (y * 0x80) + len; } void compressShortVector_init() @@ -850,45 +852,49 @@ void get_mi_min_max_texcoords(float mode) } #endif -#ifdef CSQC -void cvar_settemp(string pKey, string pValue) -{ - error("cvar_settemp called from CSQC - use cvar_clientsettemp instead!"); -} -void cvar_settemp_restore() -{ - error("cvar_settemp_restore called from CSQC - use cvar_clientsettemp instead!"); -} -#else -void cvar_settemp(string pKey, string pValue) +float cvar_settemp(string tmp_cvar, string tmp_value) { - float i; - string settemp_var; - if(cvar_string(pKey) == pValue) - return; - i = cvar("settemp_idx"); - cvar_set("settemp_idx", ftos(i+1)); - settemp_var = strcat("_settemp_x", ftos(i)); -#ifdef MENUQC - registercvar(settemp_var, "", 0); -#else - registercvar(settemp_var, ""); -#endif - cvar_set("settemp_list", strcat("1 ", pKey, " ", settemp_var, " ", cvar_string("settemp_list"))); - cvar_set(settemp_var, cvar_string(pKey)); - cvar_set(pKey, pValue); + float created_saved_value; + entity e; + + if not(tmp_cvar || tmp_value) + { + dprint("Error: Invalid usage of cvar_settemp(string, string); !\n"); + return FALSE; + } + + for(e = world; (e = find(e, classname, "saved_cvar_value")); ) + if(e.netname == tmp_cvar) + goto saved; // skip creation + + // creating a new entity to keep track of this cvar + e = spawn(); + e.classname = "saved_cvar_value"; + e.netname = strzone(tmp_cvar); + e.message = strzone(cvar_string(tmp_cvar)); + created_saved_value = TRUE; + + // an entity for this cvar already exists + :saved + + // update the cvar to the value given + cvar_set(tmp_cvar, tmp_value); + + return created_saved_value; } -void cvar_settemp_restore() +float cvar_settemp_restore() { - // undo what cvar_settemp did - float n, i; - n = tokenize_console(cvar_string("settemp_list")); - for(i = 0; i < n - 3; i += 3) - cvar_set(argv(i + 1), cvar_string(argv(i + 2))); - cvar_set("settemp_list", "0"); + float i; + entity e; + while((e = find(world, classname, "saved_cvar_value"))) + { + cvar_set(e.netname, e.message); + remove(e); + } + + return i; } -#endif float almost_equals(float a, float b) { @@ -1061,8 +1067,8 @@ vector rgb_to_hsv(vector rgb) float mi, ma; vector hsv; - mi = min3(rgb_x, rgb_y, rgb_z); - ma = max3(rgb_x, rgb_y, rgb_z); + mi = min(rgb_x, rgb_y, rgb_z); + ma = max(rgb_x, rgb_y, rgb_z); hsv_x = rgb_mi_ma_to_hue(rgb, mi, ma); hsv_z = ma; @@ -1085,8 +1091,8 @@ vector rgb_to_hsl(vector rgb) float mi, ma; vector hsl; - mi = min3(rgb_x, rgb_y, rgb_z); - ma = max3(rgb_x, rgb_y, rgb_z); + mi = min(rgb_x, rgb_y, rgb_z); + ma = max(rgb_x, rgb_y, rgb_z); hsl_x = rgb_mi_ma_to_hue(rgb, mi, ma); @@ -1130,21 +1136,16 @@ string rgb_to_hexcolor(vector rgb) } // requires that m2>m1 in all coordinates, and that m4>m3 -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;}; +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;} // requires the same, but is a stronger condition -float boxinsidebox(vector smins, vector smaxs, vector bmins, vector bmaxs) {return smins_x >= bmins_x && smaxs_x <= bmaxs_x && smins_y >= bmins_y && smaxs_y <= bmaxs_y && smins_z >= bmins_z && smaxs_z <= bmaxs_z;}; +float boxinsidebox(vector smins, vector smaxs, vector bmins, vector bmaxs) {return smins_x >= bmins_x && smaxs_x <= bmaxs_x && smins_y >= bmins_y && smaxs_y <= bmaxs_y && smins_z >= bmins_z && smaxs_z <= bmaxs_z;} #ifndef MENUQC #endif float textLengthUpToWidth(string theText, float maxWidth, vector theSize, textLengthUpToWidth_widthFunction_t w) { - float ICanHasKallerz; - - // detect color codes support in the width function - ICanHasKallerz = (w("^7", theSize) == 0); - // STOP. // The following function is SLOW. // For your safety and for the protection of those around you... @@ -1168,7 +1169,7 @@ float textLengthUpToWidth(string theText, float maxWidth, vector theSize, textLe } while(left < right - 1); - if(ICanHasKallerz) + if(w("^7", theSize) == 0) // detect color codes support in the width function { // NOTE: when color codes are involved, this binary search is, // mathematically, BROKEN. However, it is obviously guaranteed to @@ -1209,11 +1210,6 @@ float textLengthUpToWidth(string theText, float maxWidth, vector theSize, textLe float textLengthUpToLength(string theText, float maxWidth, textLengthUpToLength_lenFunction_t w) { - float ICanHasKallerz; - - // detect color codes support in the width function - ICanHasKallerz = (w("^7") == 0); - // STOP. // The following function is SLOW. // For your safety and for the protection of those around you... @@ -1237,7 +1233,7 @@ float textLengthUpToLength(string theText, float maxWidth, textLengthUpToLength_ } while(left < right - 1); - if(ICanHasKallerz) + if(w("^7") == 0) // detect color codes support in the width function { // NOTE: when color codes are involved, this binary search is, // mathematically, BROKEN. However, it is obviously guaranteed to @@ -1276,6 +1272,42 @@ float textLengthUpToLength(string theText, float maxWidth, textLengthUpToLength_ return left; } +string find_last_color_code(string s) +{ + float start, len, i, carets; + start = strstrofs(s, "^", 0); + if (start == -1) // no caret found + return ""; + len = strlen(s)-1; + for(i = len; i >= start; --i) + { + if(substring(s, i, 1) != "^") + continue; + + carets = 1; + while (i-carets >= start && substring(s, i-carets, 1) == "^") + ++carets; + + // check if carets aren't all escaped + if (carets == 1 || mod(carets, 2) == 1) // first check is just an optimization + { + if(i+1 <= len) + if(strstrofs("0123456789", substring(s, i+1, 1), 0) >= 0) + return substring(s, i, 2); + + if(i+4 <= len) + if(substring(s, i+1, 1) == "x") + if(strstrofs("0123456789abcdefABCDEF", substring(s, i+2, 1), 0) >= 0) + if(strstrofs("0123456789abcdefABCDEF", substring(s, i+3, 1), 0) >= 0) + if(strstrofs("0123456789abcdefABCDEF", substring(s, i+4, 1), 0) >= 0) + return substring(s, i, 5); + } + i -= carets; // this also skips one char before the carets + } + + return ""; +} + string getWrappedLine(float w, vector theFontSize, textLengthUpToWidth_widthFunction_t tw) { float cantake; @@ -1283,6 +1315,12 @@ string getWrappedLine(float w, vector theFontSize, textLengthUpToWidth_widthFunc string s; s = getWrappedLine_remaining; + + if(w <= 0) + { + getWrappedLine_remaining = string_null; + return s; // the line has no size ANYWAY, nothing would be displayed. + } cantake = textLengthUpToWidth(s, w, theFontSize, tw); if(cantake > 0 && cantake < strlen(s)) @@ -1295,6 +1333,8 @@ string getWrappedLine(float w, vector theFontSize, textLengthUpToWidth_widthFunc getWrappedLine_remaining = substring(s, cantake, strlen(s) - cantake); if(getWrappedLine_remaining == "") getWrappedLine_remaining = string_null; + else if (tw("^7", theFontSize) == 0) + getWrappedLine_remaining = strcat(find_last_color_code(substring(s, 0, cantake)), getWrappedLine_remaining); return substring(s, 0, cantake); } else @@ -1302,6 +1342,8 @@ string getWrappedLine(float w, vector theFontSize, textLengthUpToWidth_widthFunc getWrappedLine_remaining = substring(s, take + 1, strlen(s) - take); if(getWrappedLine_remaining == "") getWrappedLine_remaining = string_null; + else if (tw("^7", theFontSize) == 0) + getWrappedLine_remaining = strcat(find_last_color_code(substring(s, 0, take)), getWrappedLine_remaining); return substring(s, 0, take); } } @@ -1319,6 +1361,12 @@ string getWrappedLineLen(float w, textLengthUpToLength_lenFunction_t tw) string s; s = getWrappedLine_remaining; + + if(w <= 0) + { + getWrappedLine_remaining = string_null; + return s; // the line has no size ANYWAY, nothing would be displayed. + } cantake = textLengthUpToLength(s, w, tw); if(cantake > 0 && cantake < strlen(s)) @@ -1331,6 +1379,8 @@ string getWrappedLineLen(float w, textLengthUpToLength_lenFunction_t tw) getWrappedLine_remaining = substring(s, cantake, strlen(s) - cantake); if(getWrappedLine_remaining == "") getWrappedLine_remaining = string_null; + else if (tw("^7") == 0) + getWrappedLine_remaining = strcat(find_last_color_code(substring(s, 0, cantake)), getWrappedLine_remaining); return substring(s, 0, cantake); } else @@ -1338,6 +1388,8 @@ string getWrappedLineLen(float w, textLengthUpToLength_lenFunction_t tw) getWrappedLine_remaining = substring(s, take + 1, strlen(s) - take); if(getWrappedLine_remaining == "") getWrappedLine_remaining = string_null; + else if (tw("^7") == 0) + getWrappedLine_remaining = strcat(find_last_color_code(substring(s, 0, take)), getWrappedLine_remaining); return substring(s, 0, take); } } @@ -1364,18 +1416,22 @@ string textShortenToLength(string theText, float maxWidth, textLengthUpToLength_ return strcat(substring(theText, 0, textLengthUpToLength(theText, maxWidth - tw("..."), tw)), "..."); } -float isGametypeInFilter(float gt, float tp, string pattern) +float isGametypeInFilter(float gt, float tp, float ts, string pattern) { - string subpattern, subpattern2, subpattern3; - subpattern = strcat(",", GametypeNameFromType(gt), ","); + string subpattern, subpattern2, subpattern3, subpattern4; + subpattern = strcat(",", MapInfo_Type_ToString(gt), ","); if(tp) subpattern2 = ",teams,"; else subpattern2 = ",noteams,"; - if(gt == GAME_RACE || gt == GAME_CTS) - subpattern3 = ",race,"; + if(ts) + subpattern3 = ",teamspawns,"; + else + subpattern3 = ",noteamspawns,"; + if(gt == MAPINFO_TYPE_RACE || gt == MAPINFO_TYPE_CTS) + subpattern4 = ",race,"; else - subpattern3 = string_null; + subpattern4 = string_null; if(substring(pattern, 0, 1) == "-") { @@ -1384,7 +1440,9 @@ float isGametypeInFilter(float gt, float tp, string pattern) return 0; if(strstrofs(strcat(",", pattern, ","), subpattern2, 0) >= 0) return 0; - if(subpattern3 && strstrofs(strcat(",", pattern, ","), subpattern3, 0) >= 0) + if(strstrofs(strcat(",", pattern, ","), subpattern3, 0) >= 0) + return 0; + if(subpattern4 && strstrofs(strcat(",", pattern, ","), subpattern4, 0) >= 0) return 0; } else @@ -1393,7 +1451,8 @@ float isGametypeInFilter(float gt, float tp, string pattern) pattern = substring(pattern, 1, strlen(pattern) - 1); if(strstrofs(strcat(",", pattern, ","), subpattern, 0) < 0) if(strstrofs(strcat(",", pattern, ","), subpattern2, 0) < 0) - if((!subpattern3) || strstrofs(strcat(",", pattern, ","), subpattern3, 0) < 0) + if(strstrofs(strcat(",", pattern, ","), subpattern3, 0) < 0) + if((!subpattern4) || strstrofs(strcat(",", pattern, ","), subpattern4, 0) < 0) return 0; } return 1; @@ -1514,12 +1573,6 @@ vector solve_quadratic(float a, float b, float c) // ax^2 + bx + c = 0 return v; } - -float _unacceptable_compiler_bug_1_a(float b, float c) { return b == c; } -float _unacceptable_compiler_bug_1_b() { return 1; } -float _unacceptable_compiler_bug_1_c(float d) { return 2 * d; } -float _unacceptable_compiler_bug_1_d() { return 1; } - void check_unacceptable_compiler_bugs() { if(cvar("_allow_unacceptable_compiler_bugs")) @@ -1697,11 +1750,11 @@ float ReadInt24_t() return v; } #else -void WriteInt24_t(float dest, float val) +void WriteInt24_t(float dst, float val) { float v; - WriteShort(dest, (v = floor(val / 256))); - WriteByte(dest, val - v * 256); // 0..255 + WriteShort(dst, (v = floor(val / 256))); + WriteByte(dst, val - v * 256); // 0..255 } #endif #endif @@ -1979,3 +2032,183 @@ float u8_strsize(string s) } return l; } + +// translation helpers +string language_filename(string s) +{ + string fn; + float fh; + fn = prvm_language; + if(fn == "" || fn == "dump") + return s; + fn = strcat(s, ".", fn); + if((fh = fopen(fn, FILE_READ)) >= 0) + { + fclose(fh); + return fn; + } + return s; +} +string CTX(string s) +{ + float p = strstrofs(s, "^", 0); + if(p < 0) + return s; + return substring(s, p+1, -1); +} + +// x-encoding (encoding as zero length invisible string) +const string XENCODE_2 = "xX"; +const string XENCODE_22 = "0123456789abcdefABCDEF"; +string xencode(float f) +{ + float a, b, c, d; + d = mod(f, 22); f = floor(f / 22); + c = mod(f, 22); f = floor(f / 22); + b = mod(f, 22); f = floor(f / 22); + a = mod(f, 2); // f = floor(f / 2); + return strcat( + "^", + substring(XENCODE_2, a, 1), + substring(XENCODE_22, b, 1), + substring(XENCODE_22, c, 1), + substring(XENCODE_22, d, 1) + ); +} +float xdecode(string s) +{ + float a, b, c, d; + if(substring(s, 0, 1) != "^") + return -1; + if(strlen(s) < 5) + return -1; + a = strstrofs(XENCODE_2, substring(s, 1, 1), 0); + b = strstrofs(XENCODE_22, substring(s, 2, 1), 0); + c = strstrofs(XENCODE_22, substring(s, 3, 1), 0); + d = strstrofs(XENCODE_22, substring(s, 4, 1), 0); + if(a < 0 || b < 0 || c < 0 || d < 0) + return -1; + return ((a * 22 + b) * 22 + c) * 22 + d; +} + +float lowestbit(float f) +{ + f &~= f * 2; + f &~= f * 4; + f &~= f * 16; + f &~= f * 256; + f &~= f * 65536; + return f; +} + +/* +string strlimitedlen(string input, string truncation, float strip_colors, float limit) +{ + if(strlen((strip_colors ? strdecolorize(input) : input)) <= limit) + return input; + else + return strcat(substring(input, 0, (strlen(input) - strlen(truncation))), truncation); +}*/ + +// escape the string to make it safe for consoles +string MakeConsoleSafe(string input) +{ + input = strreplace("\n", "", input); + input = strreplace("\\", "\\\\", input); + input = strreplace("$", "$$", input); + input = strreplace("\"", "\\\"", input); + return input; +} + +#ifndef MENUQC +// get true/false value of a string with multiple different inputs +float InterpretBoolean(string input) +{ + switch(strtolower(input)) + { + case "yes": + case "true": + case "on": + return TRUE; + + case "no": + case "false": + case "off": + return FALSE; + + default: return stof(input); + } +} +#endif + +#ifdef CSQC +entity ReadCSQCEntity() +{ + float f; + f = ReadShort(); + if(f == 0) + return world; + return findfloat(world, entnum, f); +} +#endif + +float shutdown_running; +#ifdef SVQC +void SV_Shutdown() +#endif +#ifdef CSQC +void CSQC_Shutdown() +#endif +#ifdef MENUQC +void m_shutdown() +#endif +{ + if(shutdown_running) + { + print("Recursive shutdown detected! Only restoring cvars...\n"); + } + else + { + shutdown_running = 1; + Shutdown(); + } + cvar_settemp_restore(); // this must be done LAST, but in any case +} + +#define APPROXPASTTIME_ACCURACY_REQUIREMENT 0.05 +#define APPROXPASTTIME_MAX (16384 * APPROXPASTTIME_ACCURACY_REQUIREMENT) +#define APPROXPASTTIME_RANGE (64 * APPROXPASTTIME_ACCURACY_REQUIREMENT) +// this will use the value: +// 128 +// accuracy near zero is APPROXPASTTIME_MAX/(256*255) +// accuracy at x is 1/derivative, i.e. +// APPROXPASTTIME_MAX * (1 + 256 * (dt / APPROXPASTTIME_MAX))^2 / 65536 +#ifdef SVQC +void WriteApproxPastTime(float dst, float t) +{ + float dt = time - t; + + // warning: this is approximate; do not resend when you don't have to! + // be careful with sendflags here! + // we want: 0 -> 0.05, 1 -> 0.1, ..., 255 -> 12.75 + + // map to range... + dt = 256 * (dt / ((APPROXPASTTIME_MAX / 256) + dt)); + + // round... + dt = rint(bound(0, dt, 255)); + + WriteByte(dst, dt); +} +#endif +#ifdef CSQC +float ReadApproxPastTime() +{ + float dt = ReadByte(); + + // map from range...PPROXPASTTIME_MAX / 256 + dt = (APPROXPASTTIME_MAX / 256) * (dt / (256 - dt)); + + return servertime - dt; +} +#endif diff --git a/qcsrc/common/util.qh b/qcsrc/common/util.qh index 79b93d3ede..4b0526815d 100644 --- a/qcsrc/common/util.qh +++ b/qcsrc/common/util.qh @@ -20,9 +20,10 @@ void wordwrap_sprint(string s, float l); #endif void wordwrap_cb(string s, float l, void(string) callback) -float GameCommand_Generic(string cmd); -// returns TRUE if handled, FALSE otherwise -// uses tokenize on its argument! +#ifndef SVQC +string draw_currentSkin; +string draw_UseSkinFor(string pic); +#endif // iterative depth-first search, with fields that go "up", "down left" and "right" in a tree // for each element, funcPre is called first, then funcPre and funcPost for all its children, and funcPost last @@ -34,6 +35,8 @@ float median(float a, float b, float c); // works for up to 10 decimals! string ftos_decimals(float number, float decimals); +float fexists(string f); + vector colormapPaletteColor(float c, float isPants); // unzone the string, and return it as tempstring. Safe to be called on string_null @@ -57,7 +60,6 @@ void buf_save(float buf, string filename); float mod(float a, float b) { return a - (floor(a / b) * b); } #endif -string GametypeNameFromType(float g); #define TIME_TO_NTHS(t,n) floor((t) * (n) + 0.4) string mmsss(float t); string mmssss(float t); @@ -83,12 +85,13 @@ float CheckWireframeBox(entity forent, vector v0, vector dvx, vector dvy, vector #endif string fixPriorityList(string pl, float from, float to, float subtract, float complete); +string mapPriorityList(string order, string(string) mapfunc); string swapInPriorityList(string order, float i, float j); float cvar_value_issafe(string s); -void cvar_settemp(string pKey, string pValue); -void cvar_settemp_restore(); +float cvar_settemp(string pKey, string pValue); +float cvar_settemp_restore(); #ifndef MENUQC // modes: 0 = trust q3map2 (_mini images) @@ -142,7 +145,7 @@ string getWrappedLine_remaining; string getWrappedLine(float w, vector size, textLengthUpToWidth_widthFunction_t tw); string getWrappedLineLen(float w, textLengthUpToLength_lenFunction_t tw); -float isGametypeInFilter(float gt, float tp, string pattern); +float isGametypeInFilter(float gt, float tp, float ts, string pattern); typedef void(float i1, float i2, entity pass) swapfunc_t; // is only ever called for i1 < i2 typedef float(float i1, float i2, entity pass) comparefunc_t; // <0 for <, ==0 for ==, >0 for > (like strcmp) @@ -219,6 +222,8 @@ float get_model_parameters(string mod, float skn); // call with string_null to c switch(id) {\ case HUD_PANEL_ENGINEINFO: panel_name = HUD_PANELNAME_ENGINEINFO; break; \ case HUD_PANEL_INFOMESSAGES: panel_name = HUD_PANELNAME_INFOMESSAGES; break; \ + case HUD_PANEL_PHYSICS: panel_name = HUD_PANELNAME_PHYSICS; break; \ + case HUD_PANEL_CENTERPRINT: panel_name = HUD_PANELNAME_CENTERPRINT; break; \ } ENDS_WITH_CURLY_BRACE // Get name of specified panel id @@ -237,8 +242,8 @@ switch(id) { \ case HUD_PANEL_MODICONS: panel_name = HUD_PANELNAME_MODICONS; break; \ case HUD_PANEL_PRESSEDKEYS: panel_name = HUD_PANELNAME_PRESSEDKEYS; break; \ case HUD_PANEL_CHAT: panel_name = HUD_PANELNAME_CHAT; break; \ -}\ -HUD_Panel_GetName_Part2(id) + default: HUD_Panel_GetName_Part2(id)\ +} vector vec2(vector v); @@ -249,3 +254,46 @@ vector NearestPointOnBox(entity box, vector org); float vercmp(string v1, string v2); float u8_strsize(string s); + +// translation helpers +string prvm_language; +string language_filename(string s); +string CTX(string s); +#define ZCTX(s) strzone(CTX(s)) + +// x-encoding (encoding as zero length invisible string) +// encodes approx. 14 bits into 5 bytes of color code string +const float XENCODE_MAX = 21295; // 2*22*22*22-1 +const float XENCODE_LEN = 5; +string xencode(float f); +float xdecode(string s); + +#ifndef COMPAT_XON010_CHANNELS +#define sound(e,c,s,v,a) sound7(e,c,s,v,a,0,0) +#endif + +float lowestbit(float f); + +#ifdef CSQC +entity ReadCSQCEntity() +#endif + +#ifndef MENUQC +string strtolower(string s); +#endif + +string MakeConsoleSafe(string input); + +#ifndef MENUQC +float InterpretBoolean(string input); +#endif + +// generic shutdown handler +void Shutdown(); + +#ifdef SVQC +void WriteApproxPastTime(float dst, float t); +#endif +#ifdef CSQC +float ReadApproxPastTime(); +#endif diff --git a/qcsrc/csqcmodellib/cl_model.qc b/qcsrc/csqcmodellib/cl_model.qc new file mode 100644 index 0000000000..b77507bb65 --- /dev/null +++ b/qcsrc/csqcmodellib/cl_model.qc @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2011 Rudolf Polzer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +var float autocvar_cl_lerpanim_maxdelta_framegroups = 0.1; +var float autocvar_cl_nolerp = 0; + +.float csqcmodel_lerpfrac; +.float csqcmodel_lerpfrac2; +.float csqcmodel_lerpfractime; +.float csqcmodel_lerpfrac2time; + +void CSQCModel_InterpolateAnimation_PreNote(float sf) +{ +#ifdef CSQCMODEL_HAVE_TWO_FRAMES + if(sf & CSQCMODEL_PROPERTY_FRAME) + { + self.frame3 = self.frame; + self.frame3time = self.frame1time; + } + if(sf & CSQCMODEL_PROPERTY_FRAME2) + { + self.frame4 = self.frame2; + self.frame4time = self.frame2time; + } + if(sf & CSQCMODEL_PROPERTY_LERPFRAC) + { + self.csqcmodel_lerpfrac2 = self.csqcmodel_lerpfrac; + self.csqcmodel_lerpfrac2time = self.csqcmodel_lerpfractime; + self.lerpfrac = self.csqcmodel_lerpfrac; + } +#else + if(sf & CSQCMODEL_PROPERTY_FRAME) + { + self.frame2 = self.frame; + self.frame2time = self.frame1time; + } +#endif +} + +void CSQCModel_InterpolateAnimation_Note(float sf) +{ +#ifdef CSQCMODEL_HAVE_TWO_FRAMES + if(sf & CSQCMODEL_PROPERTY_FRAME) + { + self.frame1time = time; + } + if(sf & CSQCMODEL_PROPERTY_FRAME2) + { + self.frame2time = time; + } + if(sf & CSQCMODEL_PROPERTY_LERPFRAC) + { + self.csqcmodel_lerpfrac = self.lerpfrac; + self.csqcmodel_lerpfractime = time; + } +#else + if(sf & CSQCMODEL_PROPERTY_FRAME) + { + self.frame1time = time; + } +#endif +} + +void CSQCModel_InterpolateAnimation_Do() +{ +#ifdef CSQCMODEL_HAVE_TWO_FRAMES + if(autocvar_cl_nolerp || (autocvar_cl_lerpanim_maxdelta_framegroups == 0)) + { + self.lerpfrac = self.csqcmodel_lerpfrac; + self.lerpfrac3 = 0; + self.lerpfrac4 = 0; + } + else + { + float l13, l24, llf; + float l24_13; + + if(self.frame3time == 0) // if frame1/3 were not previously displayed, only frame1 can make sense + l13 = 1; + else + l13 = bound(0, (time - self.frame1time) / autocvar_cl_lerpanim_maxdelta_framegroups, 1); + + if(self.frame4time == 0) // if frame2/4 were not previously displayed, only frame2 can make sense + l24 = 1; + else + l24 = bound(0, (time - self.frame2time) / autocvar_cl_lerpanim_maxdelta_framegroups, 1); + + if(self.csqcmodel_lerpfrac2time == 0) // if there is no old lerpfrac (newly displayed model), only lerpfrac makes sense + llf = 1; + else + llf = bound(0, (time - self.csqcmodel_lerpfractime) / autocvar_cl_lerpanim_maxdelta_framegroups, 1); + + l24_13 = self.csqcmodel_lerpfrac * llf + self.csqcmodel_lerpfrac2 * (1 - llf); + + self.lerpfrac = l24 * l24_13; + self.lerpfrac4 = (1 - l24) * l24_13; + self.lerpfrac3 = (1 - l13) * (1 - l24_13); + + if(l24_13 == 0) // if frames 2/4 are not displayed, clear their frametime + { + self.frame2time = 0; + self.frame4time = 0; + } + + if(l24_13 == 1) // if frames 1/3 are not displayed, clear their frametime + { + self.frame1time = 0; + self.frame3time = 0; + } + } +#else + if(autocvar_cl_nolerp || (autocvar_cl_lerpanim_maxdelta_framegroups == 0)) + { + self.lerpfrac = 0; + } + else + { + self.lerpfrac = 1 - bound(0, (time - self.frame1time) / autocvar_cl_lerpanim_maxdelta_framegroups, 1); + } +#endif +} + +void CSQCModel_Draw() +{ + // some nice flags for CSQCMODEL_IF and the hooks + float isplayer = (self.entnum >= 1 && self.entnum <= maxclients); + float islocalplayer = (self.entnum == player_localnum + 1); + float isnolocalplayer = (isplayer && (self.entnum != player_localnum + 1)); + + // we don't do this for the local player as that one is already handled + // by CSQCPlayer_SetCamera() + if(!CSQCPlayer_IsLocalPlayer()) + InterpolateOrigin_Do(); + + // TODO csqcplayers: run prediction here too + CSQCModel_InterpolateAnimation_Do(); + + { CSQCMODEL_HOOK_PREDRAW } + + // inherit draw flags easily + entity root = self; + while(root.tag_entity) + root = root.tag_entity; + if(self != root) + { + self.renderflags &~= RF_EXTERNALMODEL | RF_VIEWMODEL; + self.renderflags |= (root.renderflags & (RF_EXTERNALMODEL | RF_VIEWMODEL)); + } + + // we're drawn, now teleporting is over + self.csqcmodel_teleported = 0; +} + +void CSQCModel_Read(float isnew) +{ + float sf; + sf = ReadShort(); + + // some nice flags for CSQCMODEL_IF and the hooks + float isplayer = (self.entnum >= 1 && self.entnum <= maxclients); + float islocalplayer = (self.entnum == player_localnum + 1); + float isnolocalplayer = (isplayer && (self.entnum != player_localnum + 1)); + + self.iflags |= IFLAG_ANGLES; // interpolate angles too + + { CSQCMODEL_HOOK_PREUPDATE } + + CSQCPlayer_PreUpdate(); + InterpolateOrigin_Undo(); + CSQCModel_InterpolateAnimation_PreNote(sf); + +#define CSQCMODEL_IF(cond) if(cond) { +#define CSQCMODEL_ENDIF } +#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \ + if(sf & flag) \ + self.f = r(); +#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) \ + if(sf & flag) \ + self.f = (r() + mi) / s; + ALLPROPERTIES +#undef CSQCMODEL_PROPERTY_SCALED +#undef CSQCMODEL_PROPERTY +#undef CSQCMODEL_ENDIF +#undef CSQCMODEL_IF + + if(sf & CSQCMODEL_PROPERTY_MODELINDEX) + setmodelindex(self, self.modelindex); // this retrieves the .model key and sets mins/maxs/absmin/absmax + + if(sf & CSQCMODEL_PROPERTY_TELEPORTED) + { + self.iflags |= IFLAG_TELEPORTED; + self.csqcmodel_teleported = 1; + } + + CSQCModel_InterpolateAnimation_Note(sf); + InterpolateOrigin_Note(); + CSQCPlayer_PostUpdate(); + + { CSQCMODEL_HOOK_POSTUPDATE } + +#ifdef CSQCMODEL_SUPPORT_GETTAGINFO_BEFORE_DRAW + InterpolateOrigin_Do(); + CSQCModel_InterpolateAnimation_Do(); +#endif + + // relink + setorigin(self, self.origin); + + // set obvious render flags +#ifdef COMPAT_XON050_ENGINE + if(self.entnum == player_localentnum || self.entnum == spectatee_status) +#else + if(self.entnum == player_localentnum) +#endif + self.renderflags |= RF_EXTERNALMODEL; + else + self.renderflags &~= RF_EXTERNALMODEL; + + // draw it + self.drawmask = MASK_NORMAL; + self.predraw = CSQCModel_Draw; +} + +entity CSQCModel_server2csqc(float pl) +{ + return findfloat(world, entnum, pl); // FIXME optimize this using an array +} diff --git a/qcsrc/csqcmodellib/cl_model.qh b/qcsrc/csqcmodellib/cl_model.qh new file mode 100644 index 0000000000..e8ea9012cb --- /dev/null +++ b/qcsrc/csqcmodellib/cl_model.qh @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2011 Rudolf Polzer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +void CSQCModel_Read(float isnew); + +#define CSQCMODEL_IF(cond) +#define CSQCMODEL_ENDIF +#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \ + .t f; +#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) CSQCMODEL_PROPERTY(flag,t,r,w,f) + ALLPROPERTIES +#undef CSQCMODEL_PROPERTY_SCALED +#undef CSQCMODEL_PROPERTY +#undef CSQCMODEL_ENDIF +#undef CSQCMODEL_IF + +entity CSQCModel_server2csqc(float pl); +.float csqcmodel_teleported; diff --git a/qcsrc/csqcmodellib/cl_player.qc b/qcsrc/csqcmodellib/cl_player.qc new file mode 100644 index 0000000000..dc9627d9e8 --- /dev/null +++ b/qcsrc/csqcmodellib/cl_player.qc @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2011 Rudolf Polzer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +var float autocvar_cl_predictionerrorcompensation = 0; + +// engine stuff +.float pmove_flags; +float pmove_onground; // weird engine flag we shouldn't really use but have to for now +#define PMF_JUMP_HELD 1 +#define PMF_DUCKED 4 +#define PMF_ONGROUND 8 +#define REFDEFFLAG_TELEPORTED 1 +#define REFDEFFLAG_JUMPING 2 + +entity csqcplayer; +vector csqcplayer_origin, csqcplayer_velocity; +float csqcplayer_sequence, player_pmflags; +float csqcplayer_moveframe; +vector csqcplayer_predictionerror; +float csqcplayer_predictionerrortime; + +vector CSQCPlayer_GetPredictionError() +{ + if(!autocvar_cl_predictionerrorcompensation) + return '0 0 0'; + if(time < csqcplayer_predictionerrortime) + return csqcplayer_predictionerror * (csqcplayer_predictionerrortime - time) * autocvar_cl_predictionerrorcompensation; + return '0 0 0'; +} + +void CSQCPlayer_SetPredictionError(vector v) +{ + if(!autocvar_cl_predictionerrorcompensation) + return; + csqcplayer_predictionerror = (csqcplayer_predictionerrortime - time) * autocvar_cl_predictionerrorcompensation * csqcplayer_predictionerror + v; + csqcplayer_predictionerrortime = time + 1.0 / autocvar_cl_predictionerrorcompensation; +} + +void CSQCPlayer_Unpredict() +{ + if(csqcplayer_status == CSQCPLAYERSTATUS_UNPREDICTED) + return; + if(csqcplayer_status != CSQCPLAYERSTATUS_PREDICTED) + error("Cannot unpredict in current status"); + self.origin = csqcplayer_origin; + self.velocity = csqcplayer_velocity; + csqcplayer_moveframe = csqcplayer_sequence+1; //+1 because the recieved frame has the move already done (server side) + self.pmove_flags = player_pmflags; +} + +void CSQCPlayer_SetMinsMaxs() +{ + if(self.pmove_flags & PMF_DUCKED) + { + self.mins = PL_CROUCH_MIN; + self.maxs = PL_CROUCH_MAX; + self.view_ofs = PL_CROUCH_VIEW_OFS; + } + else + { + self.mins = PL_MIN; + self.maxs = PL_MAX; + self.view_ofs = PL_VIEW_OFS; + } +} + +void CSQCPlayer_SavePrediction() +{ + player_pmflags = self.pmove_flags; + csqcplayer_origin = self.origin; + csqcplayer_velocity = self.velocity; + csqcplayer_sequence = servercommandframe; + csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED; +} + +void CSQCPlayer_PredictTo(float endframe) +{ + CSQCPlayer_Unpredict(); + CSQCPlayer_SetMinsMaxs(); + + csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED; + + // FIXME do we really NEED this? dead players have servercommandframe + // == 0 and thus won't predict + if (getstatf(STAT_HEALTH) <= 0) + { + csqcplayer_moveframe = clientcommandframe; + getinputstate(csqcplayer_moveframe-1); + print("the Weird code path got hit\n"); + return; + } + + if(csqcplayer_moveframe >= endframe) + { + getinputstate(csqcplayer_moveframe - 1); + } + else + { + do + { + if (!getinputstate(csqcplayer_moveframe)) + break; + runstandardplayerphysics(self); + CSQCPlayer_SetMinsMaxs(); + csqcplayer_moveframe++; + } + while(csqcplayer_moveframe < endframe); + } + + //add in anything that was applied after (for low packet rate protocols) + input_angles = view_angles; +} + +float CSQCPlayer_IsLocalPlayer() +{ + return (self == csqcplayer); +} + +void(entity e, float fl) V_CalcRefdef = #640; // DP_CSQC_V_CALCREFDEF + +void CSQCPlayer_SetCamera() +{ + vector v0; + v0 = pmove_vel; // TRICK: pmove_vel is set by the engine when we get here. No need to network velocity + + if(csqcplayer) + { + entity oldself; + oldself = self; + self = csqcplayer; + +#ifdef COMPAT_XON050_ENGINE + if(servercommandframe == 0 || clientcommandframe == 0 || !(checkextension("DP_CSQC_V_CALCREFDEF") || checkextension("DP_CSQC_V_CALCREFDEF_WIP1"))) +#else + if(servercommandframe == 0 || clientcommandframe == 0) +#endif + { + InterpolateOrigin_Do(); + self.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT); + + // get crouch state from the server + if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS_z) + self.pmove_flags &~= PMF_DUCKED; + else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS_z) + self.pmove_flags |= PMF_DUCKED; + + // get onground state from the server + if(pmove_onground) + self.pmove_flags |= PMF_ONGROUND; + else + self.pmove_flags &~= PMF_ONGROUND; + + CSQCPlayer_SetMinsMaxs(); + + // override it back just in case + self.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT); + + // set velocity + self.velocity = v0; + } + else + { + if(csqcplayer_status == CSQCPLAYERSTATUS_FROMSERVER) + { + vector o, v; + o = self.origin; + csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED; + CSQCPlayer_PredictTo(servercommandframe + 1); + CSQCPlayer_SetPredictionError(o - self.origin); + self.origin = o; + self.velocity = v0; + + // get crouch state from the server + if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS_z) + self.pmove_flags &~= PMF_DUCKED; + else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS_z) + self.pmove_flags |= PMF_DUCKED; + + // get onground state from the server + if(pmove_onground) + self.pmove_flags |= PMF_ONGROUND; + else + self.pmove_flags &~= PMF_ONGROUND; + + CSQCPlayer_SavePrediction(); + } + CSQCPlayer_PredictTo(clientcommandframe + 1); + + CSQCPlayer_SetMinsMaxs(); + + self.angles_y = input_angles_y; + } + + // relink + setorigin(self, self.origin); + + self = oldself; + } + + entity view; +#ifdef COMPAT_XON050_ENGINE + view = CSQCModel_server2csqc((spectatee_status > 0) ? spectatee_status : player_localentnum); +#else + view = CSQCModel_server2csqc(player_localentnum); +#endif + + if(view && view != csqcplayer) + { + entity oldself = self; + self = view; + InterpolateOrigin_Do(); + self.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT); + self = oldself; + } + +#ifdef COMPAT_XON050_ENGINE + if(view && !(checkextension("DP_CSQC_V_CALCREFDEF") || checkextension("DP_CSQC_V_CALCREFDEF_WIP1"))) + { + // legacy code, not totally correct, but good enough for not having V_CalcRefdef + setproperty(VF_ORIGIN, view.origin + '0 0 1' * getstati(STAT_VIEWHEIGHT)); + setproperty(VF_ANGLES, view_angles); + } + else +#endif + if(view) + { + var float refdefflags = 0; + + if(view.csqcmodel_teleported) + refdefflags |= REFDEFFLAG_TELEPORTED; + + if(input_buttons & 4) + refdefflags |= REFDEFFLAG_JUMPING; + + // note: these two only work in WIP2, but are harmless in WIP1 + if(getstati(STAT_HEALTH) <= 0) + refdefflags |= REFDEFFLAG_DEAD; + + if(intermission) + refdefflags |= REFDEFFLAG_INTERMISSION; + + V_CalcRefdef(view, refdefflags); + } + else + { + // FIXME by CSQC spec we have to do this: + // but it breaks chase cam + /* + setproperty(VF_ORIGIN, pmove_org + '0 0 1' * getstati(STAT_VIEWHEIGHT)); + setproperty(VF_ANGLES, view_angles); + */ + } + + { CSQCPLAYER_HOOK_POSTCAMERASETUP } +} + +void CSQCPlayer_Remove() +{ + csqcplayer = world; + cvar_settemp("cl_movement_replay", "1"); +} + +float CSQCPlayer_PreUpdate() +{ + if(self != csqcplayer) + return 0; + if(csqcplayer_status != CSQCPLAYERSTATUS_FROMSERVER) + CSQCPlayer_Unpredict(); + return 1; +} + +float CSQCPlayer_PostUpdate() +{ + if(self.entnum != player_localnum + 1) + return 0; + csqcplayer = self; + csqcplayer_status = CSQCPLAYERSTATUS_FROMSERVER; + cvar_settemp("cl_movement_replay", "0"); + self.entremove = CSQCPlayer_Remove; + return 1; +} diff --git a/qcsrc/csqcmodellib/cl_player.qh b/qcsrc/csqcmodellib/cl_player.qh new file mode 100644 index 0000000000..0eecabed88 --- /dev/null +++ b/qcsrc/csqcmodellib/cl_player.qh @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2011 Rudolf Polzer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +float csqcplayer_status; +#define CSQCPLAYERSTATUS_UNPREDICTED 0 +#define CSQCPLAYERSTATUS_FROMSERVER 1 +#define CSQCPLAYERSTATUS_PREDICTED 2 + +void CSQCPlayer_SetCamera(); +float CSQCPlayer_PreUpdate(); +float CSQCPlayer_PostUpdate(); +float CSQCPlayer_IsLocalPlayer(); diff --git a/qcsrc/csqcmodellib/common.qh b/qcsrc/csqcmodellib/common.qh new file mode 100644 index 0000000000..587645cd4f --- /dev/null +++ b/qcsrc/csqcmodellib/common.qh @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2011 Rudolf Polzer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +noref string csqcmodel_license = "\ +Copyright (c) 2011 Rudolf Polzer\ +\ +Permission is hereby granted, free of charge, to any person obtaining a copy\ +of this software and associated documentation files (the \"Software\"), to\ +deal in the Software without restriction, including without limitation the\ +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\ +sell copies of the Software, and to permit persons to whom the Software is\ +furnished to do so, subject to the following conditions:\ +\ +The above copyright notice and this permission notice shall be included in\ +all copies or substantial portions of the Software.\ +\ +THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\ +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\ +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\ +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\ +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\ +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\ +IN THE SOFTWARE.\ +"; + +.vector glowmod; +.vector view_ofs; +.float frame; +.float frame1time; +.float frame2; +.float frame2time; +.float lerpfrac; + +#define CSQCMODEL_PROPERTY_FRAME 32768 +#define CSQCMODEL_PROPERTY_FRAME2 16384 +#define CSQCMODEL_PROPERTY_LERPFRAC 8192 +#define CSQCMODEL_PROPERTY_TELEPORTED 4096 // the "teleport bit" cancelling interpolation +#define CSQCMODEL_PROPERTY_MODELINDEX 2048 +#define CSQCMODEL_PROPERTY_ORIGIN 1024 +#define CSQCMODEL_PROPERTY_YAW 512 +#define CSQCMODEL_PROPERTY_PITCHROLL 256 + +#define ALLPROPERTIES_COMMON \ + CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_FRAME, float, ReadByte, WriteByte, frame) \ + CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_MODELINDEX, float, ReadShort, WriteShort, modelindex) \ + CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_ORIGIN, float, ReadCoord, WriteCoord, origin_x) \ + CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_ORIGIN, float, ReadCoord, WriteCoord, origin_y) \ + CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_ORIGIN, float, ReadCoord, WriteCoord, origin_z) \ + CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_PITCHROLL, float, ReadAngle, WriteAngle, angles_x) \ + CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_YAW, float, ReadAngle, WriteAngle, angles_y) \ + CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_PITCHROLL, float, ReadAngle, WriteAngle, angles_z) \ + CSQCMODEL_EXTRAPROPERTIES + +#ifdef CSQCMODEL_HAVE_TWO_FRAMES +.float frame3; +.float frame3time; +.float lerpfrac3; +.float frame4; +.float frame4time; +.float lerpfrac4; +#define ALLPROPERTIES ALLPROPERTIES_COMMON \ + CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_FRAME2, float, ReadByte, WriteByte, frame2) \ + CSQCMODEL_PROPERTY_SCALED(CSQCMODEL_PROPERTY_LERPFRAC, float, ReadByte, WriteByte, lerpfrac, 255, 0, 255) +#else +#define ALLPROPERTIES ALLPROPERTIES_COMMON +#endif diff --git a/qcsrc/csqcmodellib/interpolate.qc b/qcsrc/csqcmodellib/interpolate.qc new file mode 100644 index 0000000000..ac0ba6e7d7 --- /dev/null +++ b/qcsrc/csqcmodellib/interpolate.qc @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2011 Rudolf Polzer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +.vector iorigin1, iorigin2; +.vector ivelocity1, ivelocity2; +.vector iforward1, iforward2; +.vector iup1, iup2; +.float itime1, itime2; +void InterpolateOrigin_Reset() +{ + self.iflags &~= IFLAG_INTERNALMASK; + self.itime1 = self.itime2 = 0; +} +void InterpolateOrigin_Note() +{ + float dt; + float f0; + + dt = time - self.itime2; + + f0 = self.iflags; + if(self.iflags & IFLAG_PREVALID) + self.iflags |= IFLAG_VALID; + else + self.iflags |= IFLAG_PREVALID; + + self.iorigin1 = self.iorigin2; + self.iorigin2 = self.origin; + + if(self.iflags & IFLAG_AUTOANGLES) + if(self.iorigin2 != self.iorigin1) + self.angles = vectoangles(self.iorigin2 - self.iorigin1); + + if(self.iflags & IFLAG_ANGLES) + { + fixedmakevectors(self.angles); + if(f0 & IFLAG_VALID) + { + self.iforward1 = self.iforward2; + self.iup1 = self.iup2; + } + else + { + self.iforward1 = v_forward; + self.iup1 = v_up; + } + self.iforward2 = v_forward; + self.iup2 = v_up; + } + + if(self.iflags & IFLAG_VELOCITY) + { + self.ivelocity1 = self.ivelocity2; + self.ivelocity2 = self.velocity; + } + + if(self.iflags & IFLAG_TELEPORTED) + { + self.iflags &~= IFLAG_TELEPORTED; + self.itime1 = self.itime2 = time; // don't lerp + } + else if(vlen(self.iorigin2 - self.iorigin1) > 1000) + { + self.itime1 = self.itime2 = time; // don't lerp + } + else if((self.iflags & IFLAG_VELOCITY) && (vlen(self.ivelocity2 - self.ivelocity1) > 1000)) + { + self.itime1 = self.itime2 = time; // don't lerp + } + else if(dt >= 0.2) + { + self.itime1 = self.itime2 = time; + } + else + { + self.itime1 = serverprevtime; + self.itime2 = time; + } +} +void InterpolateOrigin_Do() +{ + vector forward, up; + if(self.itime1 && self.itime2 && self.itime1 != self.itime2) + { + float f; + f = bound(0, (time - self.itime1) / (self.itime2 - self.itime1), 1 + autocvar_cl_lerpexcess); + self.origin = (1 - f) * self.iorigin1 + f * self.iorigin2; + if(self.iflags & IFLAG_ANGLES) + { + forward = (1 - f) * self.iforward1 + f * self.iforward2; + up = (1 - f) * self.iup1 + f * self.iup2; + self.angles = fixedvectoangles2(forward, up); + } + if(self.iflags & IFLAG_VELOCITY) + self.velocity = (1 - f) * self.ivelocity1 + f * self.ivelocity2; + } +} +void InterpolateOrigin_Undo() +{ + self.origin = self.iorigin2; + if(self.iflags & IFLAG_ANGLES) + self.angles = fixedvectoangles2(self.iforward2, self.iup2); + if(self.iflags & IFLAG_VELOCITY) + self.velocity = self.ivelocity2; +} + diff --git a/qcsrc/csqcmodellib/interpolate.qh b/qcsrc/csqcmodellib/interpolate.qh new file mode 100644 index 0000000000..8254fae8cf --- /dev/null +++ b/qcsrc/csqcmodellib/interpolate.qh @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2011 Rudolf Polzer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +.float iflags; +#define IFLAG_VELOCITY 1 +#define IFLAG_ANGLES 2 +#define IFLAG_AUTOANGLES 4 +#define IFLAG_VALID 8 +#define IFLAG_PREVALID 16 +#define IFLAG_TELEPORTED 32 +#define IFLAG_INTERNALMASK (IFLAG_VALID | IFLAG_PREVALID) + +// call this BEFORE reading an entity update +void InterpolateOrigin_Undo(); + +// call this AFTER receiving an entity update +void InterpolateOrigin_Note(); + +// call this when the entity got teleported, before InterpolateOrigin_Note +void InterpolateOrigin_Reset(); + +// call this BEFORE drawing +void InterpolateOrigin_Do(); diff --git a/qcsrc/csqcmodellib/settings.qh b/qcsrc/csqcmodellib/settings.qh new file mode 100644 index 0000000000..aab2a5637c --- /dev/null +++ b/qcsrc/csqcmodellib/settings.qh @@ -0,0 +1,27 @@ +// define this if svqc code wants to use .frame2 and .lerpfrac +//#define CSQCMODEL_HAVE_TWO_FRAMES + +// don't define this ever +//#define CSQCMODEL_SUPPORT_GETTAGINFO_BEFORE_DRAW + +// add properties you want networked to CSQC here +#define CSQCMODEL_EXTRAPROPERTIES \ + /* CSQCMODEL_PROPERTY(1, float, ReadShort, WriteShort, colormap) */ \ + /* CSQCMODEL_PROPERTY(2, float, ReadInt24_t, WriteInt24_t, effects) */ + +// add hook function calls here +#define CSQCMODEL_HOOK_PREUPDATE +#define CSQCMODEL_HOOK_POSTUPDATE +#define CSQCMODEL_HOOK_PREDRAW +#define CSQCPLAYER_HOOK_POSTCAMERASETUP + +// force updates of player entities that often even if unchanged +#define CSQCPLAYER_FORCE_UPDATES 0.25 + +// mod must define: +//vector PL_MIN = ...; +//vector PL_MAX = ...; +//vector PL_VIEW_OFS = ...; +//vector PL_CROUCH_MIN = ...; +//vector PL_CROUCH_MAX = ...; +//vector PL_CROUCH_VIEW_OFS = ...; diff --git a/qcsrc/csqcmodellib/sv_model.qc b/qcsrc/csqcmodellib/sv_model.qc new file mode 100644 index 0000000000..bf6eefa697 --- /dev/null +++ b/qcsrc/csqcmodellib/sv_model.qc @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2011 Rudolf Polzer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +// generic CSQC model code + +float CSQCModel_Send(entity to, float sf) +{ + // some nice flags for CSQCMODEL_IF + float isplayer = (self.flags & FL_CLIENT); + float islocalplayer = (self == to); + float isnolocalplayer = (isplayer && (self != to)); + + WriteByte(MSG_ENTITY, ENT_CLIENT_MODEL); + WriteShort(MSG_ENTITY, sf); + +#define CSQCMODEL_IF(cond) if(cond) { +#define CSQCMODEL_ENDIF } +#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \ + if(sf & flag) \ + { \ + w(MSG_ENTITY, self.csqcmodel_##f); \ + } +#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) CSQCMODEL_PROPERTY(flag,t,r,w,f) + ALLPROPERTIES +#undef CSQCMODEL_PROPERTY_SCALED +#undef CSQCMODEL_PROPERTY +#undef CSQCMODEL_ENDIF +#undef CSQCMODEL_IF + + return TRUE; +} + +#ifdef CSQCPLAYER_FORCE_UPDATES +.float csqcmodel_nextforcedupdate; +#endif +void CSQCModel_CheckUpdate() +{ + // some nice flags for CSQCMODEL_IF + float isplayer = (self.flags & FL_CLIENT); + float islocalplayer = isplayer; // we set BOTH to 1 here as we need the sendflags + float isnolocalplayer = isplayer; // we set BOTH to 1 here as we need the sendflags + +#ifdef CSQCPLAYER_FORCE_UPDATES + if(isplayer && time > self.csqcmodel_nextforcedupdate) + { + self.SendFlags |= CSQCMODEL_PROPERTY_ORIGIN; + self.csqcmodel_nextforcedupdate = time + CSQCPLAYER_FORCE_UPDATES * (0.5 + random()); // ensure about 4 origin sends per sec + } +#endif + + if(self.effects & EF_RESTARTANIM_BIT) + { + self.SendFlags |= CSQCMODEL_PROPERTY_FRAME | CSQCMODEL_PROPERTY_FRAME2; // full anim resend please + self.effects &~= EF_RESTARTANIM_BIT; + } + + if(self.effects & EF_TELEPORT_BIT) + { + self.SendFlags |= CSQCMODEL_PROPERTY_TELEPORTED; // no interpolation please + self.effects &~= EF_TELEPORT_BIT; + } + +#define CSQCMODEL_IF(cond) if(cond) { +#define CSQCMODEL_ENDIF } +#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \ + { \ + t tmp = self.f; \ + if(tmp != self.csqcmodel_##f) \ + { \ + self.csqcmodel_##f = tmp; \ + self.SendFlags |= flag; \ + } \ + } +#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) \ + { \ + t tmp = bound(mi, s * self.f, ma) - mi; \ + if(tmp != self.csqcmodel_##f) \ + { \ + self.csqcmodel_##f = tmp; \ + self.SendFlags |= flag; \ + } \ + } + ALLPROPERTIES +#undef CSQCMODEL_PROPERTY_SCALED +#undef CSQCMODEL_PROPERTY +#undef CSQCMODEL_ENDIF +#undef CSQCMODEL_IF +} + +void CSQCModel_LinkEntity() +{ + self.SendEntity = CSQCModel_Send; + self.SendFlags = 0xFFFFFF; + CSQCModel_CheckUpdate(); +} + +void CSQCModel_UnlinkEntity() +{ + self.SendEntity = func_null; +} diff --git a/qcsrc/csqcmodellib/sv_model.qh b/qcsrc/csqcmodellib/sv_model.qh new file mode 100644 index 0000000000..3c4ce2b786 --- /dev/null +++ b/qcsrc/csqcmodellib/sv_model.qh @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2011 Rudolf Polzer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +// generic CSQC model code + +void CSQCModel_CheckUpdate(); +void CSQCModel_LinkEntity(); +void CSQCModel_UnlinkEntity(); + +#define CSQCMODEL_IF(cond) +#define CSQCMODEL_ENDIF +#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \ + .t f; \ + .t csqcmodel_##f; +#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) CSQCMODEL_PROPERTY(flag,t,r,w,f) + ALLPROPERTIES +#undef CSQCMODEL_PROPERTY_SCALED +#undef CSQCMODEL_PROPERTY +#undef CSQCMODEL_ENDIF +#undef CSQCMODEL_IF diff --git a/qcsrc/dpdefs/csprogsdefs.qc b/qcsrc/dpdefs/csprogsdefs.qc new file mode 100644 index 0000000000..623fb01c78 --- /dev/null +++ b/qcsrc/dpdefs/csprogsdefs.qc @@ -0,0 +1,1412 @@ +/* +============================================================================== + + SOURCE FOR GLOBALVARS_T C STRUCTURE + MUST NOT BE MODIFIED, OR CRC ERRORS WILL APPEAR + +============================================================================== +*/ + +// +// system globals +// +entity self; +entity other; +entity world; +float time; +float frametime; + +float player_localentnum; //the entnum +float player_localnum; //the playernum +float maxclients; //a constant filled in by the engine. gah, portability eh? + +float clientcommandframe; //player movement +float servercommandframe; //clientframe echoed off the server + +string mapname; + +// +// global variables set by built in functions +// +vector v_forward, v_up, v_right; // set by makevectors() + +// set by traceline / tracebox +float trace_allsolid; +float trace_startsolid; +float trace_fraction; +vector trace_endpos; +vector trace_plane_normal; +float trace_plane_dist; +entity trace_ent; +float trace_inopen; +float trace_inwater; + +// +// required prog functions +// +void() CSQC_Init; +void() CSQC_Shutdown; +float(float f, float t, float n) CSQC_InputEvent; +void(float w, float h) CSQC_UpdateView; +float(string s) CSQC_ConsoleCommand; + +//these fields are read and set by the default player physics +vector pmove_org; +vector pmove_vel; +vector pmove_mins; +vector pmove_maxs; +//retrieved from the current movement commands (read by player physics) +float input_timelength; +vector input_angles; +vector input_movevalues; //forwards, right, up. +float input_buttons; //attack, use, jump (default physics only uses jump) + +float movevar_gravity; +float movevar_stopspeed; +float movevar_maxspeed; +float movevar_spectatormaxspeed; //used by NOCLIP movetypes. +float movevar_accelerate; +float movevar_airaccelerate; +float movevar_wateraccelerate; +float movevar_friction; +float movevar_waterfriction; +float movevar_entgravity; //the local player's gravity field. Is a multiple (1 is the normal value) + +//================================================ +void end_sys_globals; // flag for structure dumping +//================================================ + +/* +============================================================================== + + SOURCE FOR ENTVARS_T C STRUCTURE + MUST NOT BE MODIFIED, OR CRC ERRORS WILL APPEAR + +============================================================================== +*/ + +// +// system fields (*** = do not set in prog code, maintained by C code) +// +.float modelindex; // *** model index in the precached list +.vector absmin, absmax; // *** origin + mins / maxs + +.float entnum; // *** the ent number as on the server +.float drawmask; +.void() predraw; + +.float movetype; +.float solid; + +.vector origin; // *** +.vector oldorigin; // *** +.vector velocity; +.vector angles; +.vector avelocity; + +.string classname; // spawn function +.string model; +.float frame; +.float skin; +.float effects; + +.vector mins, maxs; // bounding box extents reletive to origin +.vector size; // maxs - mins + +.void() touch; +.void() use; +.void() think; +.void() blocked; // for doors or plats, called when can't push other + +.float nextthink; + +.entity chain; + +.string netname; + +.entity enemy; + +.float flags; + +.float colormap; + +.entity owner; // who launched a missile + +//================================================ +void end_sys_fields; // flag for structure dumping +//================================================ + +/* +============================================================================== + + OPTIONAL FIELDS AND GLOBALS + +============================================================================== +*/ + +// Additional OPTIONAL Fields and Globals +float intermission; // indicates intermission state (0 = normal, 1 = scores, 2 = finale text) + +vector view_angles; // same as input_angles +vector view_punchangle; // from server +vector view_punchvector; // from server + +/* +============================================================================== + + CONSTANT DEFINITIONS + +============================================================================== +*/ + +const float MASK_ENGINE = 1; +const float MASK_ENGINEVIEWMODELS = 2; +const float MASK_NORMAL = 4; + +const float RF_VIEWMODEL = 1; +const float RF_EXTERNALMODEL = 2; +const float RF_DEPTHHACK = 4; +const float RF_ADDITIVE = 8; +const float RF_USEAXIS = 16; + +const float VF_MIN = 1; //(vector) +const float VF_MIN_X = 2; //(float) +const float VF_MIN_Y = 3; //(float) +const float VF_SIZE = 4; //(vector) (viewport size) +const float VF_SIZE_Y = 5; //(float) +const float VF_SIZE_X = 6; //(float) +const float VF_VIEWPORT = 7; //(vector, vector) +const float VF_FOV = 8; //(vector) +const float VF_FOVX = 9; //(float) +const float VF_FOVY = 10; //(float) +const float VF_ORIGIN = 11; //(vector) +const float VF_ORIGIN_X = 12; //(float) +const float VF_ORIGIN_Y = 13; //(float) +const float VF_ORIGIN_Z = 14; //(float) +const float VF_ANGLES = 15; //(vector) +const float VF_ANGLES_X = 16; //(float) +const float VF_ANGLES_Y = 17; //(float) +const float VF_ANGLES_Z = 18; //(float) +const float VF_DRAWWORLD = 19; //(float) +const float VF_DRAWENGINESBAR = 20; //(float) +const float VF_DRAWCROSSHAIR = 21; //(float) + +const float VF_CL_VIEWANGLES = 33; //(vector) +const float VF_CL_VIEWANGLES_X = 34; //(float) +const float VF_CL_VIEWANGLES_Y = 35; //(float) +const float VF_CL_VIEWANGLES_Z = 36; //(float) + +const float VF_PERSPECTIVE = 200; + +const float STAT_HEALTH = 0; +const float STAT_WEAPONMODEL = 2; +const float STAT_AMMO = 3; +const float STAT_ARMOR = 4; +const float STAT_WEAPONFRAME = 5; +const float STAT_SHELLS = 6; +const float STAT_NAILS = 7; +const float STAT_ROCKETS = 8; +const float STAT_CELLS = 9; +const float STAT_ACTIVEWEAPON = 10; +const float STAT_TOTALSECRETS = 11; +const float STAT_TOTALMONSTERS = 12; +const float STAT_SECRETS = 13; +const float STAT_MONSTERS = 14; +const float STAT_ITEMS = 15; +const float STAT_VIEWHEIGHT = 16; + +// Quake Sound Constants +const float CHAN_AUTO = 0; +const float CHAN_WEAPON = 1; +const float CHAN_VOICE = 2; +const float CHAN_ITEM = 3; +const float CHAN_BODY = 4; + +const float ATTN_NONE = 0; +const float ATTN_NORM = 1; +const float ATTN_IDLE = 2; +const float ATTN_STATIC = 3; + +// Frik File Constants +const float FILE_READ = 0; +const float FILE_APPEND = 1; +const float FILE_WRITE = 2; + +// Quake Point Contents +const float CONTENT_EMPTY = -1; +const float CONTENT_SOLID = -2; +const float CONTENT_WATER = -3; +const float CONTENT_SLIME = -4; +const float CONTENT_LAVA = -5; +const float CONTENT_SKY = -6; + +// Quake Solid Constants +const float SOLID_NOT = 0; +const float SOLID_TRIGGER = 1; +const float SOLID_BBOX = 2; +const float SOLID_SLIDEBOX = 3; +const float SOLID_BSP = 4; +const float SOLID_CORPSE = 5; + +// Quake Move Constants +const float MOVE_NORMAL = 0; +const float MOVE_NOMONSTERS = 1; +const float MOVE_MISSILE = 2; + +// Boolean Constants +const float true = 1; +const float false = 0; +const float TRUE = 1; +const float FALSE = 0; + +const float EXTRA_LOW = -99999999; +const float EXTRA_HIGH = 99999999; + +const vector VEC_1 = '1 1 1'; +const vector VEC_0 = '0 0 0'; +const vector VEC_M1 = '-1 -1 -1'; + +const float M_PI = 3.14159265358979323846; + +vector VEC_HULL_MIN = '-16 -16 -24'; +vector VEC_HULL_MAX = '16 16 32'; + +// Quake Temporary Entity Constants +const float TE_SPIKE = 0; +const float TE_SUPERSPIKE = 1; +const float TE_GUNSHOT = 2; +const float TE_EXPLOSION = 3; +const float TE_TAREXPLOSION = 4; +const float TE_LIGHTNING1 = 5; +const float TE_LIGHTNING2 = 6; +const float TE_WIZSPIKE = 7; +const float TE_KNIGHTSPIKE = 8; +const float TE_LIGHTNING3 = 9; +const float TE_LAVASPLASH = 10; +const float TE_TELEPORT = 11; +const float TE_EXPLOSION2 = 12; + // Darkplaces Additions + const float TE_EXPLOSIONRGB = 53; + const float TE_GUNSHOTQUAD = 57; + const float TE_EXPLOSIONQUAD = 70; + const float TE_SPIKEQUAD = 58; + const float TE_SUPERSPIKEQUAD = 59; + +// PFlags for Dynamic Lights +const float PFLAGS_NOSHADOW = 1; +const float PFLAGS_CORONA = 2; +const float PFLAGS_FULLDYNAMIC = 128; + +const float EF_ADDITIVE = 32; +const float EF_BLUE = 64; +const float EF_FLAME = 1024; +const float EF_FULLBRIGHT = 512; +const float EF_NODEPTHTEST = 8192; +const float EF_NODRAW = 16; +const float EF_NOSHADOW = 4096; +const float EF_RED = 128; +const float EF_STARDUST = 2048; +const float EF_SELECTABLE = 16384; + +const float PFL_ONGROUND = 1; +const float PFL_CROUCH = 2; +const float PFL_DEAD = 4; +const float PFL_GIBBED = 8; + +// draw flags +const float DRAWFLAG_NORMAL = 0; +const float DRAWFLAG_ADDITIVE = 1; +const float DRAWFLAG_MODULATE = 2; +const float DRAWFLAG_2XMODULATE = 3; +const float DRAWFLAG_SCREEN = 4; +const float DRAWFLAG_MIPMAP = 0x100; // only for R_BeginPolygon + +/* +============================================================================== + + BUILTIN DEFINITIONS + EXTENSIONS ARE NOT ADDED HERE, BUT BELOW! + +============================================================================== +*/ + +void(vector ang) makevectors = #1; +void(entity e, vector o) setorigin = #2; +void(entity e, string m) setmodel = #3; +void(entity e, vector min, vector max) setsize = #4; + +void() break = #6; +float() random = #7; +void(entity e, float chan, string samp) sound = #8; +vector(vector v) normalize = #9; +void(string e) error = #10; +void(string e) objerror = #11; +float(vector v) vlen = #12; +float(vector v) vectoyaw = #13; +entity() spawn = #14; +void(entity e) remove = #15; +float(vector v1, vector v2, float tryents, entity ignoreentity) traceline = #16; + +entity(entity start, .string fld, string match) find = #18; +void(string s) precache_sound = #19; +void(string s) precache_model = #20; + +entity(vector org, float rad) findradius = #22; + +void(string s, ...) dprint = #25; +string(float f) ftos = #26; +string(vector v) vtos = #27; +void() coredump = #28; +void() traceon = #29; +void() traceoff = #30; +void(entity e) eprint = #31; +// settrace optional +float(float yaw, float dist, float settrace) walkmove = #32; + +float() droptofloor = #34; +void(float style, string value) lightstyle = #35; +float(float v) rint = #36; +float(float v) floor = #37; +float(float v) ceil = #38; + +float(entity e) checkbottom = #40; +float(vector v) pointcontents = #41; + +float(float f) fabs = #43; + +float(string s) cvar = #45; +void(string s, ...) localcmd = #46; +entity(entity e) nextent = #47; +void(vector o, vector d, float color, float count) particle = #48; +void() ChangeYaw = #49; + +vector(vector v) vectoangles = #51; +vector(vector v, vector w) vectoangles2 = #51; + +float(float f) sin = #60; +float(float f) cos = #61; +float(float f) sqrt = #62; +void(entity ent) changepitch = #63; +void(entity e, entity ignore) tracetoss = #64; +string(entity ent) etos = #65; + +string(string s) precache_file = #68; +void(entity e) makestatic = #69; + +void(string var, string val) cvar_set = #72; + +void(vector pos, string samp, float vol, float atten) ambientsound = #74; +string(string s) precache_model2 = #75; +string(string s) precache_sound2 = #76; +string(string s) precache_file2 = #77; + +float(string s) stof = #81; + + +void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox = #90; +vector() randomvec = #91; +vector(vector org) getlight = #92; +vector(vector org, float lpflags) getlight2 = #92; +vector getlight_dir; +vector getlight_ambient; +vector getlight_diffuse; +const float LP_LIGHTMAP = 1; +const float LP_RTWORLD = 2; +const float LP_DYNLIGHT = 4; +const float LP_COMPLETE = 7; + +float(string name, string value) registercvar = #93; +float( float a, ... ) min = #94; +float( float b, ... ) max = #95; +float(float minimum, float val, float maximum) bound = #96; +float(float f, float f) pow = #97; +entity(entity start, .float fld, float match) findfloat = #98; +float(string s) checkextension = #99; +// FrikaC and Telejano range #100-#199 + +float(string filename, float mode) fopen = #110; +void(float fhandle) fclose = #111; +string(float fhandle) fgets = #112; +void(float fhandle, string s) fputs = #113; +float(string s) strlen = #114; +string(...) strcat = #115; +string(string s, float start, float length) substring = #116; +vector(string) stov = #117; +string(string s) strzone = #118; +void(string s) strunzone = #119; + +// FTEQW range #200-#299 + +float(float number, float quantity) bitshift = #218; + +//float(string str, string sub[, float startpos]) strstrofs = #221; +float(string str, string sub, float startpos) strstrofs = #221; +float(string str, float ofs) str2chr = #222; +string(float c, ...) chr2str = #223; +string(float ccase, float calpha, float cnum, string s, ...) strconv = #224; +string(float chars, string s, ...) strpad = #225; +string(string info, string key, string value, ...) infoadd = #226; +string(string info, string key) infoget = #227; +float(string s1, string s2, float len) strncmp = #228; +float(string s1, string s2) strcasecmp = #229; +float(string s1, string s2, float len) strncasecmp = #230; + +// CSQC range #300-#399 +void() clearscene = #300; +void(float mask) addentities = #301; +void(entity ent) addentity = #302; +float(float property, ...) setproperty = #303; +float(float property) getproperty = #309; +vector(float property) getpropertyvec = #309; +void() renderscene = #304; +void(vector org, float radius, vector lightcolours) adddynamiclight = #305; +void(vector org, float radius, vector lightcolours, float style, string cubemapname, float pflags) adddynamiclight2 = #305; +//void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon = #306; +void(string texturename, float flag, ...) R_BeginPolygon = #306; +void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex = #307; +void() R_EndPolygon = #308; +vector (vector v) cs_unproject = #310; +vector (vector v) cs_project = #311; + +void(float width, vector pos1, vector pos2, float flag) drawline = #315; +float(string name) iscachedpic = #316; +string(string name, ...) precache_pic = #317; +string(string name) precache_cubemap = #317; +vector(string picname) draw_getimagesize = #318; +void(string name) freepic = #319; +float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter = #320; +float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring = #321; +float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic = #322; +float(vector position, vector size, vector rgb, float alpha, float flag) drawfill = #323; +void(float x, float y, float width, float height) drawsetcliparea = #324; +void(void) drawresetcliparea = #325; +float(vector position, string text, vector scale, float alpha, float flag) drawcolorcodedstring = #326; +vector(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawcolorcodedstring2 = #326; + +float(float stnum) getstatf = #330; +float(float stnum, ...) getstati = #331; // can optionally take first bit and count +string(float firststnum) getstats = #332; +void(entity e, float mdlindex) setmodelindex = #333; +string(float mdlindex) modelnameforindex = #334; +float(string effectname) particleeffectnum = #335; +void(entity ent, float effectnum, vector start, vector end) trailparticles = #336; +//void(float effectnum, vector origin [, vector dir, float count]) pointparticles = #337; +void(float effectnum, vector origin , vector dir, float count) pointparticles = #337; +void(string s, ...) centerprint = #338; +void(string s, ...) print = #339; +string(float keynum) keynumtostring = #340; +float(string keyname) stringtokeynum = #341; +string(float keynum) getkeybind = #342; +void(float usecursor) setcursormode = #343; +vector() getmousepos = #344; +float(float framenum) getinputstate = #345; +void(float sens) setsensitivityscale = #346; +void(...) runstandardplayerphysics = #347; // this may or may not take a player ent +string(float playernum, string keyname) getplayerkeyvalue = #348; +float() isdemo = #349; +float() isserver = #350; +void(vector origin, vector forward, vector right, vector up) SetListener = #351; +void(string cmdname) registercommand = #352; +float(entity ent) wasfreed = #353; +string(string key) serverkey = #354; + +// Use proper case; refer to the id1 Write* functions! +float() ReadByte = #360; +float() ReadChar = #361; +float() ReadShort = #362; +float() ReadLong = #363; +float() ReadCoord = #364; +float() ReadAngle = #365; +string() ReadString = #366; +float() ReadFloat = #367; + +// LordHavoc's range #400-#499 +void(entity from, entity to) copyentity = #400; + +entity(.string fld, string match) findchain = #402; +entity(.float fld, float match) findchainfloat = #403; +void(vector org, string modelname, float startframe, float endframe, float framerate) effect = #404; +void(vector org, vector velocity, float howmany) te_blood = #405; +void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower = #406; +void(vector org, vector color) te_explosionrgb = #407; +void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube = #408; +void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain = #409; +void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow = #410; +void(vector org, vector vel, float howmany) te_spark = #411; +void(vector org) te_gunshotquad = #412; +void(vector org) te_spikequad = #413; +void(vector org) te_superspikequad = #414; +void(vector org) te_explosionquad = #415; +void(vector org) te_smallflash = #416; +void(vector org, float radius, float lifetime, vector color) te_customflash = #417; +void(vector org) te_gunshot = #418; +void(vector org) te_spike = #419; +void(vector org) te_superspike = #420; +void(vector org) te_explosion = #421; +void(vector org) te_tarexplosion = #422; +void(vector org) te_wizspike = #423; +void(vector org) te_knightspike = #424; +void(vector org) te_lavasplash = #425; +void(vector org) te_teleport = #426; +void(vector org, float colorstart, float colorlength) te_explosion2 = #427; +void(entity own, vector start, vector end) te_lightning1 = #428; +void(entity own, vector start, vector end) te_lightning2 = #429; +void(entity own, vector start, vector end) te_lightning3 = #430; +void(entity own, vector start, vector end) te_beam = #431; +void(vector dir) vectorvectors = #432; +void(vector org) te_plasmaburn = #433; +float(entity e, float s) getsurfacenumpoints = #434; +vector(entity e, float s, float n) getsurfacepoint = #435; +vector(entity e, float s) getsurfacenormal = #436; +string(entity e, float s) getsurfacetexture = #437; +float(entity e, vector p) getsurfacenearpoint = #438; +vector(entity e, float s, vector p) getsurfaceclippedpoint = #439; + +float(string s) tokenize = #441; +string(float n) argv = #442; +void(entity e, entity tagentity, string tagname) setattachment = #443; +float(string pattern, float caseinsensitive, float quiet) search_begin = #444; +void(float handle) search_end = #445; +float(float handle) search_getsize = #446; +string(float handle, float num) search_getfilename = #447; +string(string s) cvar_string = #448; +entity(entity start, .float fld, float match) findflags = #449; +entity(.float fld, float match) findchainflags = #450; +float(entity ent, string tagname) gettagindex = #451; +vector(entity ent, float tagindex) gettaginfo = #452; + +void(vector org, vector vel, float howmany) te_flamejet = #457; + +entity(float num) entitybyindex = #459; +float() buf_create = #460; +void(float bufhandle) buf_del = #461; +float(float bufhandle) buf_getsize = #462; +void(float bufhandle_from, float bufhandle_to) buf_copy = #463; +void(float bufhandle, float sortpower, float backward) buf_sort = #464; +string(float bufhandle, string glue) buf_implode = #465; +string(float bufhandle, float string_index) bufstr_get = #466; +void(float bufhandle, float string_index, string str) bufstr_set = #467; +float(float bufhandle, string str, float order) bufstr_add = #468; +void(float bufhandle, float string_index) bufstr_free = #469; + +float(float s) asin = #471; +float(float c) acos = #472; +float(float t) atan = #473; +float(float c, float s) atan2 = #474; +float(float a) tan = #475; +float(string s) strippedstringlen = #476; +float(string s) strlennocol = #476; // This is the correct name for the function, but not removing the decolorizedstring mapping. +string(string s) decolorizedstring = #477; +string(string s) strdecolorize = #477; // This is the correct name for the function, but not removing the decolorizedstring mapping. +string(float uselocaltime, string format, ...) strftime = #478; +string(string s) strtolower = #480; +string(string s) strtoupper = #481; +string(string s) cvar_defstring = #482; +void(vector origin, string sample, float volume, float attenuation) pointsound = #483; +string(string search, string replace, string subject) strreplace = #484; +string(string search, string replace, string subject) strireplace = #485; +vector(entity e, float s, float n, float a) getsurfacepointattribute = #486; +#ifdef SUPPORT_GECKO +float gecko_create( string name ) = #487; +void gecko_destroy( string name ) = #488; +void gecko_navigate( string name, string URI ) = #489; +float gecko_keyevent( string name, float key, float eventtype ) = #490; +void gecko_mousemove( string name, float x, float y ) = #491; +void gecko_resize( string name, float w, float h ) = #492; +vector gecko_get_texture_extent( string name ) = #493; +#else + +#endif + +/* +============================================================================== + + EXTENSION DEFINITIONS + +============================================================================== +*/ + +// DP_CSQC_SPAWNPARTICLE +// idea: VorteX +// darkplaces implementation: VorteX +// constant definitions: +// particle base behavior: +float PT_ALPHASTATIC = 1; +float PT_STATIC = 2; +float PT_SPARK = 3; +float PT_BEAM = 4; +float PT_RAIN = 5; +float PT_RAINDECAL = 6; +float PT_SNOW = 7; +float PT_BUBBLE = 8; +float PT_BLOOD = 9; +float PT_SMOKE = 10; +float PT_DECAL = 11; +float PT_ENTITYPARTICLE = 12; +// particle blendtypes: +float PBLEND_ALPHA = 0; +float PBLEND_ADD = 1; +float PBLEND_INVMOD = 2; +// particle orientation: +float PARTICLE_BILLBOARD = 0; +float PARTICLE_SPARK = 1; +float PARTICLE_ORIENTED_DOUBLESIDED = 2; +float PARTICLE_BEAM = 3; +// global definitions: +float particle_type; // one of PT_ +float particle_blendmode; // one of PBLEND_ values +float particle_orientation; // one of PARTICLE_ values +vector particle_color1; +vector particle_color2; +float particle_tex; // number of chunk in particlefont +float particle_size; +float particle_sizeincrease; +float particle_alpha; +float particle_alphafade; +float particle_time; +float particle_gravity; +float particle_bounce; +float particle_airfriction; +float particle_liquidfriction; +float particle_originjitter; +float particle_velocityjitter; +float particle_qualityreduction; // enable culling of this particle when FPS is low +float particle_stretch; +vector particle_staincolor1; +vector particle_staincolor2; +float particle_staintex; +float particle_stainalpha; +float particle_stainsize; +float particle_delayspawn; +float particle_delaycollision; +float particle_angle; +float particle_spin; +// builtin definitions: +float(float max_themes) initparticlespawner = #522; // check fields/globals for integration and enable particle spawner, return 1 is succeded, otherwise returns 0 +void() resetparticle = #523; // reset p_ globals to default theme #0 +void(float theme) particletheme = #524; // restore p_ globals from saved theme +float() particlethemesave = #525; // save p_ globals to new particletheme and return it's index +void(float theme) particlethemeupdate = #525; // save p_ globals to new particletheme and return it's index +void(float theme) particlethemefree = #526; // delete a particle theme +float(vector org, vector vel) spawnparticle = #527; // returns 0 when failed, 1 when spawned +float(vector org, vector vel, float theme) quickparticle = #527; // not reading globals, just theme, returns 0 when failed, 1 when spawned +float(vector org, vector vel, float delay, float collisiondelay) delayedparticle = #528; +float(vector org, vector vel, float delay, float collisiondelay, float theme) quickdelayedparticle = #528; +// description: this builtin provides an easy and flexible way to spawn particles, +// it is not created as replace for DP_SV_POINTPARTICLES but as an addition to it. +// With this extension you can create a specific particles like rain particles, or entity particles +// notes: +// 1) 0 is default particle template, it could be changed +// 2) color vectors could have value 0-255 of each component +// restrictions: max themes could be between 4 and 2048 +// warning: you should call initparticlespawner() at very beginning BEFORE all other particle spawner functions +// function to query particle info +// don't remove this function as it protects all particle_ globals from FTEQCC/FRIKQCC non-referenced removal optimisation +void() printparticle = +{ + // vortex: this also protects from 'non-referenced' optimisation on some compilers + print("PARTICLE:\n"); + print(strcat(" type: ", ftos(particle_type), "\n")); + print(strcat(" blendmode: ", ftos(particle_blendmode), "\n")); + print(strcat(" orientation: ", ftos(particle_orientation), "\n")); + print(strcat(" color1: ", vtos(particle_color1), "\n")); + print(strcat(" color2: ", vtos(particle_color2), "\n")); + print(strcat(" tex: ", ftos(particle_tex), "\n")); + print(strcat(" size: ", ftos(particle_size), "\n")); + print(strcat(" sizeincrease: ", ftos(particle_sizeincrease), "\n")); + print(strcat(" alpha: ", ftos(particle_alpha), "\n")); + print(strcat(" alphafade: ", ftos(particle_alphafade), "\n")); + print(strcat(" time: ", ftos(particle_time), "\n")); + print(strcat(" gravity: ", ftos(particle_gravity), "\n")); + print(strcat(" bounce: ", ftos(particle_bounce), "\n")); + print(strcat(" airfriction: ", ftos(particle_airfriction), "\n")); + print(strcat(" liquidfriction: ", ftos(particle_liquidfriction), "\n")); + print(strcat(" originjitter: ", ftos(particle_originjitter), "\n")); + print(strcat(" velocityjitter: ", ftos(particle_velocityjitter), "\n")); + print(strcat(" qualityreduction: ", ftos(particle_qualityreduction), "\n")); + print(strcat(" stretch: ", ftos(particle_stretch), "\n")); + print(strcat(" staincolor1: ", vtos(particle_staincolor1), "\n")); + print(strcat(" staincolor2: ", vtos(particle_staincolor2), "\n")); + print(strcat(" staintex: ", ftos(particle_staintex), "\n")); + print(strcat(" stainalpha: ", ftos(particle_stainalpha), "\n")); + print(strcat(" stainsize: ", ftos(particle_stainsize), "\n")); + print(strcat(" delayspawn: ", ftos(particle_delayspawn), "\n")); + print(strcat(" delaycollision: ", ftos(particle_delaycollision), "\n")); + print(strcat(" angle: ", ftos(particle_angle), "\n")); + print(strcat(" spin: ", ftos(particle_spin), "\n")); +} + +// DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET +// idea: VorteX +// darkplaces implementation: VorteX +float RF_USETRANSPARENTOFFSET = 64; // enables transparent origin offsetting +// global definitions +float transparent_offset; // should be set before entity is added +// description: offset a model's meshes origin used for transparent sorting. Could be used to tweak sorting bugs on very large transparent entities or hacking transparent sorting order for certain objects +// example: transparent_offset = 1000000; // entity always appear on background of other transparents +// note: offset is done in view forward axis + +// DP_CSQC_ENTITYWORLDOBJECT +// idea: VorteX +// darkplaces implementation: VorteX +const float RF_WORLDOBJECT = 128; +// description: when renderflag is set, engine will not use culling methods for this entity, e.g. it will always be drawn +// useful for large outdoor objects (like asteroids on sky horizon or sky models) + +// DP_CSQC_ENTITYMODELLIGHT +// idea: VorteX +// darkplaces implementation: VorteX +const float RF_MODELLIGHT = 4096; +.vector modellight_ambient; +.vector modellight_diffuse; +.vector modellight_dir; +// description: allows CSQC to override directional model lightning on entity + +// DP_CSQC_SETPAUSE +// idea: VorteX +// darkplaces implementation: VorteX +// builtin definitions: +void(float ispaused) setpause = #531; +// description: provides ability to set pause in local games (similar to one set once console is activated) +// not stopping sound/cd track, useful for inventory screens, ingame menus with input etc. + +// DP_CSQC_QUERYRENDERENTITY +// idea: VorteX +// darkplaces implementation: VorteX +// constant definitions: +// render entity fields: +float E_ACTIVE = 0; // float 0/1 +float E_ORIGIN = 1; // vector +float E_FORWARD = 2; // vector +float E_RIGHT = 3; // vector +float E_UP = 4; // vector +float E_SCALE = 5; // float +float E_ORIGINANDVECTORS = 6; // returns origin, + sets v_* vectors to orientation +float E_ALPHA = 7; // float +float E_COLORMOD = 8; // vector +float E_PANTSCOLOR = 9; // vector +float E_SHIRTCOLOR = 10; // vector +float E_SKIN = 11; // float +float E_MINS = 12; // vector +float E_MAXS = 13; // vector +float E_ABSMIN = 14; // vector +float E_ABSMAX = 15; // vector +float E_LIGHT = 16; // vector - modellight +// builtin definitions: +float(float entitynum, float fldnum) getentity = #504; +vector(float entitynum, float fldnum) getentityvec = #504; +// description: allows to query parms from render entities, especially useful with attaching CSQC ents to +// server entities networked and interpolated by engine (monsters, players), number of entity is it's SVQC number +// you can send it via tempentity/CSQC entity message. Note that this builtin doesnt know about entity removing/reallocating +// so it's meaning to work for short period of time, dont use it on missiles/grenades whatever will be removed next five seconds + +//DP_GFX_FONTS +//idea: Blub\0, divVerent +//darkplaces implementation: Blub\0 +//console commands: +// loadfont fontname fontmaps size1 size2 ... +// A font can simply be gfx/tgafile (freetype fonts doent need extension), +// or alternatively you can specify multiple fonts and faces +// Like this: gfx/vera-sans:2,gfx/fallback:1 +// to load face 2 of the font gfx/vera-sans and use face 1 +// of gfx/fallback as fallback font +// You can also specify a list of font sizes to load, like this: +// loadfont console gfx/conchars,gfx/fallback 8 12 16 24 32 +// In many cases, 8 12 16 24 32 should be a good choice. +// for slots see: +//constant definitions: +float drawfont; // set it before drawstring()/drawchar() calls +float FONT_DEFAULT = 0; // 'default' +float FONT_CONSOLE = 1; // 'console', REALLY should be fixed width (ls!) +float FONT_SBAR = 2; // 'sbar', used on hud, must be fixed width +float FONT_NOTIFY = 3; // 'notify', used on sprint/bprint +float FONT_CHAT = 4; // 'chat' +float FONT_CENTERPRINT = 5;// 'centerprint' +float FONT_INFOBAR = 6; // 'infobar' +float FONT_MENU = 7; // 'menu', should be fixed width +float FONT_USER0 = 8; // 'user0', userdefined fonts +float FONT_USER1 = 9; // 'user1', userdefined fonts +float FONT_USER2 = 10; // 'user2', userdefined fonts +float FONT_USER3 = 11; // 'user3', userdefined fonts +float FONT_USER4 = 12; // 'user4', userdefined fonts +float FONT_USER5 = 13; // 'user5', userdefined fonts +float FONT_USER6 = 14; // 'user6', userdefined fonts +float FONT_USER7 = 15; // 'user7' slot, userdefined fonts +//builtin definitions: +float findfont(string s) = #356; // find font by fontname and return it's index +float loadfont(string fontname, string fontmaps, string sizes, float slot, float fix_scale, float fix_voffset) = #357; +// loads font immediately so stringwidth() function can be used just after builtin call +// returns a font slotnum (which is used to set drawfont to) +// first 3 parms are identical to "loadfont" console command ones +// slot could be one of FONT_ constants or result of findfont() or -1 to not use it +// if slot is given, font will be loaded to this slotnum and fontname become new title for it +// this way you can rename user* fonts to something more usable +// fix_* parms let you fix badly made fonts by applying some transformations to them +// fix_scale : per-character center-oriented scale (doesn't change line height at all) +// fix_voffset : vertical offset for each character, it's a multiplier to character height +float stringwidth(string text, float allowColorCodes, vector size) = #327; // get a width of string with given font and char size +float stringwidth_menu(string text, float allowColorCodes, vector size) = #468; // in menu.dat it has different builtin # +//description: engine support for custom fonts in console, hud, qc etc. +// limits: +// max 128 chars for font name +// max 3 font fallbacks +// max 8 sizes per font + +//DP_GFX_FONTS_FREETYPE +//idea: Blub\0, divVerent +//darkplaces implementation: Blub\0 +//cvar definitions: +// r_font_disable_freetype 0/1 : disable freetype fonts loading (uttetly disables freetype library initialization) +// r_font_antialias 0/1 : antialiasing when loading font +// r_font_hint 0/1/2/3 : hinting when loading font, 0 is no hinting, 1 light autohinting , 2 full autohinting, 3 full hinting +// r_font_postprocess_blur X : font outline blur amount +// r_font_postprocess_outline X : font outline width +// r_font_postprocess_shadow_x X : font outline shadow x shift amount, applied during outlining +// r_font_postprocess_shadow_y X : font outline shadow y shift amount, applied during outlining +// r_font_postprocess_shadow_z X : font outline shadow z shift amount, applied during blurring +//description: engine support for truetype/freetype fonts +//so .AFM+.PFB/.OTF/.TTF files could be stuffed as fontmaps in loadfont() +//(console command version will support them as well) + +//DP_CSQC_BINDMAPS +//idea: daemon, motorsep +//darkplaces implementation: divVerent +//builtin definitions: +string(float key, float bindmap) getkeybind_bindmap = #342; +float(float key, string bind, float bindmap) setkeybind_bindmap = #630; +vector(void) getbindmaps = #631; +float(vector bm) setbindmaps = #632; +string(string command, float bindmap) findkeysforcommand = #610; +//<already in EXT_CSQC> float(string key) stringtokeynum = #341; +//<already in EXT_CSQC> string(float keynum) keynumtostring = #340; +//description: key bind setting/getting including support for switchable +//bindmaps. + +//DP_CRYPTO +//idea: divVerent +//darkplaces implementation: divVerent +//builtin definitions: (CSQC) +float(string url, float id, string content_type, string delim, float buf, float keyid) crypto_uri_postbuf = #513; +//description: +//use -1 as buffer handle to justs end delim as postdata + +//DP_CSQC_MAINVIEW +//idea: divVerent +//darkplaces implementation: divVerent +//constant definitions: +const float VF_MAINVIEW = 400; +//use setproperty(VF_MAINVIEW, 1); before calling R_RenderView for the render +//that shall become the "main" view, which is e.g. used by PRYDON_CLIENTCURSOR +//this flag is set for the first scene, and not cleared by R_ClearScene +//this flag is automatically cleared by R_RenderView +//so when not using this extension, the first view rendered is the main view + +//DP_CSQC_MINFPS_QUALITY +//idea: divVerent +//darkplaces implementation: divVerent +//constant definitions: +const float VF_MINFPS_QUALITY = 401; +//use getproperty(VF_MINFPS_QUALITY); to do CSQC based LOD based on cl_minfps +//1 should lead to an unmodified view + +//DP_CSQC_V_CALCREFDEF_WIP1 +//DP_CSQC_V_CALCREFDEF_WIP2 +//idea: divVerent +//darkplaces implementation: divVerent +//builtin definitions: +void(entity e, float refdefflags) V_CalcRefdef = #640; +//constant definitions: +float PMF_DUCKED = 4; +float PMF_ONGROUND = 8; +float REFDEFFLAG_TELEPORTED = 1; +float REFDEFFLAG_JUMPING = 2; +float REFDEFFLAG_DEAD = 4; +float REFDEFFLAG_INTERMISSION = 8; +//- use this on the player entity after performing prediction +//- pass REFDEFFLAG_TELEPORTED if the player teleported since last frame +//- pass REFDEFFLAG_JUMPING if jump button is pressed +//- pass REFDEFFLAG_DEAD if dead (DP_CSQC_V_CALCREFDEF_WIP2) +//- pass REFDEFFLAG_INTERMISSION if in intermission (DP_CSQC_V_CALCREFDEF_WIP2) +//- the player entity needs to have origin, velocity, pmove_flags set according +// to prediction (the above two PMF_ flags are used in the player's pmove_flags) +//- NOTE: to check for this, ALSO OR a check with DP_CSQC_V_CALCREFDEF to also support +// the finished extension once done + +// assorted builtins +float drawsubpic(vector position, vector size, string pic, vector srcPosition, vector srcSize, vector rgb, float alpha, float flag) = #328; +vector drawgetimagesize(string pic) = #318; +#define SPA_POSITION 0 +#define SPA_S_AXIS 1 +#define SPA_T_AXIS 2 +#define SPA_R_AXIS 3 +#define SPA_TEXCOORDS0 4 +#define SPA_LIGHTMAP0_TEXCOORDS 5 +#define SPA_LIGHTMAP_COLOR 6 +float (entity e, float s) getsurfacenumpoints = #434; +vector (entity e, float s, float n) getsurfacepoint = #435; +vector (entity e, float s) getsurfacenormal = #436; +string (entity e, float s) getsurfacetexture = #437; +float (entity e, vector p) getsurfacenearpoint = #438; +vector (entity e, float s, vector p) getsurfaceclippedpoint = #439; +vector(entity e, float s, float n, float a) getsurfacepointattribute = #486; +float(entity e, float s) getsurfacenumtriangles = #628; +vector(entity e, float s, float n) getsurfacetriangle = #629; + +//DP_QC_ASINACOSATANATAN2TAN +//idea: Urre +//darkplaces implementation: LordHavoc +//constant definitions: +float DEG2RAD = 0.0174532925199432957692369076848861271344287188854172545609719144; +float RAD2DEG = 57.2957795130823208767981548141051703324054724665643215491602438612; +float PI = 3.1415926535897932384626433832795028841971693993751058209749445923; +//builtin definitions: +float(float s) asin = #471; // returns angle in radians for a given sin() value, the result is in the range -PI*0.5 to PI*0.5 +float(float c) acos = #472; // returns angle in radians for a given cos() value, the result is in the range 0 to PI +float(float t) atan = #473; // returns angle in radians for a given tan() value, the result is in the range -PI*0.5 to PI*0.5 +float(float c, float s) atan2 = #474; // returns angle in radians for a given cos() and sin() value pair, the result is in the range -PI to PI (this is identical to vectoyaw except it returns radians rather than degrees) +float(float a) tan = #475; // returns tangent value (which is simply sin(a)/cos(a)) for the given angle in radians, the result is in the range -infinity to +infinity +//description: +//useful math functions for analyzing vectors, note that these all use angles in radians (just like the cos/sin functions) not degrees unlike makevectors/vectoyaw/vectoangles, so be sure to do the appropriate conversions (multiply by DEG2RAD or RAD2DEG as needed). +//note: atan2 can take unnormalized vectors (just like vectoyaw), and the function was included only for completeness (more often you want vectoyaw or vectoangles), atan2(v_x,v_y) * RAD2DEG gives the same result as vectoyaw(v) + +//DP_QC_SPRINTF +//idea: divVerent +//darkplaces implementation: divVerent +//builtin definitions: +string(string format, ...) sprintf = #627; +//description: +//you know sprintf :P +//supported stuff: +// % +// optional: <argpos>$ for the argument to format +// flags: #0- + +// optional: <width>, *, or *<argpos>$ for the field width +// optional: .<precision>, .*, or .*<argpos>$ for the precision +// length modifiers: h for forcing a float, l for forcing an int/entity (by default, %d etc. cast a float to int) +// conversions: +// d takes a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to an int +// i takes an int/entity if no length is specified or i is, and a float if h is specified as length, and cast it to an int +// ouxXc take a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to an unsigned int +// eEfFgG take a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to a double +// s takes a string +// vV takes a vector, and processes the three components as if it were a gG for all three components, separated by space +// For conversions s and c, the flag # makes precision and width interpreted +// as byte count, by default it is interpreted as character count in UTF-8 +// enabled engines. No other conversions can create wide characters, and # +// has another meaning in these. + +//DP_QC_GETTIME +//idea: tZork +//darkplaces implementation: tZork, divVerent +//constant definitions: +float GETTIME_FRAMESTART = 0; // time of start of frame +float GETTIME_REALTIME = 1; // current time (may be OS specific) +float GETTIME_HIRES = 2; // like REALTIME, but may reset between QC invocations and thus can be higher precision +float GETTIME_UPTIME = 3; // time since start of the engine +//builtin definitions: +float(float tmr) gettime = #519; +//description: +//some timers to query... + +//DP_QC_GETTIME_CDTRACK +//idea: divVerent +//darkplaces implementation: divVerent +//constant definitions: +float GETTIME_CDTRACK = 4; +//description: +//returns the playing time of the current cdtrack when passed to gettime() +//see DP_END_GETSOUNDTIME for similar functionality but for entity sound channels + +//DP_QC_TOKENIZEBYSEPARATOR +//idea: Electro, SavageX, LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +float(string s, string separator1, ...) tokenizebyseparator = #479; +//description: +//this function returns tokens separated by any of the supplied separator strings, example: +//numnumbers = tokenizebyseparator("10.2.3.4", "."); +//returns 4 and the tokens are "10" "2" "3" "4" +//possibly useful for parsing IPv4 addresses (such as "1.2.3.4") and IPv6 addresses (such as "[1234:5678:9abc:def0:1234:5678:9abc:def0]:26000") + +//DP_QC_TOKENIZE_CONSOLE +//idea: divVerent +//darkplaces implementation: divVerent +//builtin definitions: +float(string s) tokenize_console = #514; +float(float i) argv_start_index = #515; +float(float i) argv_end_index = #516; +//description: +//this function returns tokens separated just like the console does +//also, functions are provided to get the index of the first and last character of each token in the original string +//Passing negative values to them, or to argv, will be treated as indexes from the LAST token (like lists work in Perl). So argv(-1) will return the LAST token. + +//DP_SND_SOUND7_WIP1 +//DP_SND_SOUND7_WIP2 +//idea: divVerent +//darkplaces implementation: divVerent +//builtin definitions: +void(entity e, float chan, string samp, float vol, float atten, float speed, float flags) sound7 = #8; +float SOUNDFLAG_RELIABLE = 1; +//description: +//plays a sound, with some more flags +//extensions to sound(): +//- channel may be in the range from -128 to 127; channels -128 to 0 are "auto", +// i.e. support multiple sounds at once, but cannot be stopped/restarted +//- a value 0 in the speed parameter means no change; otherwise, it is a +// percentage of playback speed ("pitch shifting"). 100 is normal pitch, 50 is +// half speed, 200 is double speed, etc. (DP_SND_SOUND7_WIP2) +//- the flag SOUNDFLAG_RELIABLE can be specified, which makes the sound send +// to MSG_ALL (reliable) instead of MSG_BROADCAST (unreliable, default); +// similarily, SOUNDFLAG_RELIABLE_TO_ONE sends to MSG_ONE +//- channel 0 is controlled by snd_channel0volume; channel 1 and -1 by +// snd_channel1volume, etc. (so, a channel shares the cvar with its respective +// auto-channel); however, the mod MUST define snd_channel8volume and upwards +// in default.cfg if they are to be used, as the engine does not create them +// to not litter the cvar list +//- this extension applies to CSQC as well; CSQC_Event_Sound will get speed and +// flags as extra 7th and 8th argument +//- WIP2 ideas: SOUNDFLAG_RELIABLE_TO_ONE, SOUNDFLAG_NOPHS, SOUNDFLAG_FORCELOOP +//- NOTE: to check for this, ALSO OR a check with DP_SND_SOUND7 to also support +// the finished extension once done + +//DP_MOVETYPEFLYWORLDONLY +//idea: Samual +//darkplaces implementation: Samual +//movetype definitions: +float MOVETYPE_FLY_WORLDONLY = 33; +//description: +//like MOVETYPE_FLY, but does all traces with MOVE_WORLDONLY, and is ignored by MOVETYPE_PUSH. Should only be combined with SOLID_NOT and SOLID_TRIGGER. + +//DP_QC_TRACE_MOVETYPE_WORLDONLY +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//constant definitions: +float MOVE_WORLDONLY = 3; +//description: +//allows traces to hit only world (ignoring all entities, unlike MOVE_NOMONSTERS which hits all bmodels), use as the nomonsters parameter to trace functions + +//DP_SND_GETSOUNDTIME +//idea: VorteX +//darkplaces implementation: VorteX +//constant definitions: +float(entity e, float channel) getsoundtime = #533; // get currently sound playing position on entity channel, -1 if not playing or error +float(string sample) soundlength = #534; // returns length of sound sample in seconds, -1 on error (sound not precached, sound system not initialized etc.) +//description: provides opportunity to query length of sound samples and realtime tracking of sound playing on entities (similar to DP_GETTIME_CDTRACK) +//note: beware dedicated server not running sound engine at all, so in dedicated mode this builtins will not work in server progs +//note also: menu progs not supporting getsoundtime() (will give a warning) since it has no sound playing on entities +//examples of use: +// - QC-driven looped sounds +// - QC events when sound playing is finished +// - toggleable ambientsounds +// - subtitles + +//DP_QC_NUM_FOR_EDICT +//idea: Blub\0 +//darkplaces implementation: Blub\0 +//Function to get the number of an entity - a clean way. +float(entity num) num_for_edict = #512; + +//DP_TRACE_HITCONTENTSMASK_SURFACEINFO +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//globals: +.float dphitcontentsmask; // if non-zero on the entity passed to traceline/tracebox/tracetoss this will override the normal collidable contents rules and instead hit these contents values (for example AI can use tracelines that hit DONOTENTER if it wants to, by simply changing this field on the entity passed to traceline), this affects normal movement as well as trace calls +float trace_dpstartcontents; // DPCONTENTS_ value at start position of trace +float trace_dphitcontents; // DPCONTENTS_ value of impacted surface (not contents at impact point, just contents of the surface that was hit) +float trace_dphitq3surfaceflags; // Q3SURFACEFLAG_ value of impacted surface +string trace_dphittexturename; // texture name of impacted surface +//constants: +float DPCONTENTS_SOLID = 1; // hit a bmodel, not a bounding box +float DPCONTENTS_WATER = 2; +float DPCONTENTS_SLIME = 4; +float DPCONTENTS_LAVA = 8; +float DPCONTENTS_SKY = 16; +float DPCONTENTS_BODY = 32; // hit a bounding box, not a bmodel +float DPCONTENTS_CORPSE = 64; // hit a SOLID_CORPSE entity +float DPCONTENTS_NODROP = 128; // an area where backpacks should not spawn +float DPCONTENTS_PLAYERCLIP = 256; // blocks player movement +float DPCONTENTS_MONSTERCLIP = 512; // blocks monster movement +float DPCONTENTS_DONOTENTER = 1024; // AI hint brush +float DPCONTENTS_LIQUIDSMASK = 14; // WATER | SLIME | LAVA +float DPCONTENTS_BOTCLIP = 2048; // AI hint brush +float DPCONTENTS_OPAQUE = 4096; // only fully opaque brushes get this (may be useful for line of sight checks) +float Q3SURFACEFLAG_NODAMAGE = 1; +float Q3SURFACEFLAG_SLICK = 2; // low friction surface +float Q3SURFACEFLAG_SKY = 4; // sky surface (also has NOIMPACT and NOMARKS set) +float Q3SURFACEFLAG_LADDER = 8; // climbable surface +float Q3SURFACEFLAG_NOIMPACT = 16; // projectiles should remove themselves on impact (this is set on sky) +float Q3SURFACEFLAG_NOMARKS = 32; // projectiles should not leave marks, such as decals (this is set on sky) +float Q3SURFACEFLAG_FLESH = 64; // projectiles should do a fleshy effect (blood?) on impact +float Q3SURFACEFLAG_NODRAW = 128; // compiler hint (not important to qc) +//float Q3SURFACEFLAG_HINT = 256; // compiler hint (not important to qc) +//float Q3SURFACEFLAG_SKIP = 512; // compiler hint (not important to qc) +//float Q3SURFACEFLAG_NOLIGHTMAP = 1024; // compiler hint (not important to qc) +//float Q3SURFACEFLAG_POINTLIGHT = 2048; // compiler hint (not important to qc) +float Q3SURFACEFLAG_METALSTEPS = 4096; // walking on this surface should make metal step sounds +float Q3SURFACEFLAG_NOSTEPS = 8192; // walking on this surface should not make footstep sounds +float Q3SURFACEFLAG_NONSOLID = 16384; // compiler hint (not important to qc) +//float Q3SURFACEFLAG_LIGHTFILTER = 32768; // compiler hint (not important to qc) +//float Q3SURFACEFLAG_ALPHASHADOW = 65536; // compiler hint (not important to qc) +//float Q3SURFACEFLAG_NODLIGHT = 131072; // compiler hint (not important to qc) +//float Q3SURFACEFLAG_DUST = 262144; // translucent 'light beam' effect (not important to qc) +//description: +//adds additional information after a traceline/tracebox/tracetoss call. +//also (very important) sets trace_* globals before calling .touch functions, +//this allows them to inspect the nature of the collision (for example +//determining if a projectile hit sky), clears trace_* variables for the other +//object in a touch event (that is to say, a projectile moving will see the +//trace results in its .touch function, but the player it hit will see very +//little information in the trace_ variables as it was not moving at the time) + +//DP_QC_CVAR_TYPE +//idea: divVerent +//DarkPlaces implementation: divVerent +//builtin definitions: +float(string name) cvar_type = #495; +float CVAR_TYPEFLAG_EXISTS = 1; +float CVAR_TYPEFLAG_SAVED = 2; +float CVAR_TYPEFLAG_PRIVATE = 4; +float CVAR_TYPEFLAG_ENGINE = 8; +float CVAR_TYPEFLAG_HASDESCRIPTION = 16; +float CVAR_TYPEFLAG_READONLY = 32; + +//DP_QC_CRC16 +//idea: divVerent +//darkplaces implementation: divVerent +//Some hash function to build hash tables with. This has to be be the CRC-16-CCITT that is also required for the QuakeWorld download protocol. +//When caseinsensitive is set, the CRC is calculated of the lower cased string. +float(float caseinsensitive, string s, ...) crc16 = #494; + +//DP_QC_URI_ESCAPE +//idea: divVerent +//darkplaces implementation: divVerent +//URI::Escape's functionality +string(string in) uri_escape = #510; +string(string in) uri_unescape = #511; + +//DP_QC_DIGEST +//idea: motorsep, Spike +//DarkPlaces implementation: divVerent +//builtin definitions: +string(string digest, string data, ...) digest_hex = #639; +//description: +//returns a given hex digest of given data +//the returned digest is always encoded in hexadecimal +//only the "MD4" digest is always supported! +//if the given digest is not supported, string_null is returned +//the digest string is matched case sensitively, use "MD4", not "md4"! + +//DP_QC_DIGEST_SHA256 +//idea: motorsep, Spike +//DarkPlaces implementation: divVerent +//description: +//"SHA256" is also an allowed digest type + +//DP_QC_LOG +//darkplaces implementation: divVerent +//builtin definitions: +float log(float f) = #532; +//description: +//logarithm + +//FTE_CSQC_SKELETONOBJECTS +//idea: Spike, LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +// all skeleton numbers are 1-based (0 being no skeleton) +// all bone numbers are 1-based (0 being invalid) +float(float modlindex) skel_create = #263; // create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex, as the skeleton uses the hierarchy from the model. +float(float skel, entity ent, float modlindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // blend in a percentage of standard animation, 0 replaces entirely, 1 does nothing, 0.5 blends half, etc, and this only alters the bones in the specified range for which out of bounds values like 0,100000 are safe (uses .frame, .frame2, .frame3, .frame4, .lerpfrac, .lerpfrac3, .lerpfrac4, .frame1time, .frame2time, .frame3time, .frame4time), returns skel on success, 0 on failure +float(float skel) skel_get_numbones = #265; // returns how many bones exist in the created skeleton, 0 if skeleton does not exist +string(float skel, float bonenum) skel_get_bonename = #266; // returns name of bone (as a tempstring), "" if invalid bonenum (< 1 for example) or skeleton does not exist +float(float skel, float bonenum) skel_get_boneparent = #267; // returns parent num for supplied bonenum, 0 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this) +float(float skel, string tagname) skel_find_bone = #268; // get number of bone with specified name, 0 on failure, bonenum (1-based) on success, same as using gettagindex but takes modelindex instead of entity +vector(float skel, float bonenum) skel_get_bonerel = #269; // get matrix of bone in skeleton relative to its parent - sets v_forward, v_right, v_up, returns origin (relative to parent bone) +vector(float skel, float bonenum) skel_get_boneabs = #270; // get matrix of bone in skeleton in model space - sets v_forward, v_right, v_up, returns origin (relative to entity) +void(float skel, float bonenum, vector org) skel_set_bone = #271; // set matrix of bone relative to its parent, reads v_forward, v_right, v_up, takes origin as parameter (relative to parent bone) +void(float skel, float bonenum, vector org) skel_mul_bone = #272; // transform bone matrix (relative to its parent) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bone) +void(float skel, float startbone, float endbone, vector org) skel_mul_bones = #273; // transform bone matrices (relative to their parents) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bones) +void(float skeldst, float skelsrc, float startbone, float endbone) skel_copybones = #274; // copy bone matrices (relative to their parents) from one skeleton to another, useful for copying a skeleton to a corpse +void(float skel) skel_delete = #275; // deletes skeleton at the beginning of the next frame (you can add the entity, delete the skeleton, renderscene, and it will still work) +float(float modlindex, string framename) frameforname = #276; // finds number of a specified frame in the animation, returns -1 if no match found +float(float modlindex, float framenum) frameduration = #277; // returns the intended play time (in seconds) of the specified framegroup, if it does not exist the result is 0, if it is a single frame it may be a small value around 0.1 or 0. +//fields: +.float skeletonindex; // active skeleton overriding standard animation on model +.float frame; // primary framegroup animation (strength = 1 - lerpfrac - lerpfrac3 - lerpfrac4) +.float frame2; // secondary framegroup animation (strength = lerpfrac) +.float frame3; // tertiary framegroup animation (strength = lerpfrac3) +.float frame4; // quaternary framegroup animation (strength = lerpfrac4) +.float lerpfrac; // strength of framegroup blend +.float lerpfrac3; // strength of framegroup blend +.float lerpfrac4; // strength of framegroup blend +.float frame1time; // start time of framegroup animation +.float frame2time; // start time of framegroup animation +.float frame3time; // start time of framegroup animation +.float frame4time; // start time of framegroup animation +//description: +//this extension provides a way to do complex skeletal animation on an entity. +// +//see also DP_SKELETONOBJECTS (this extension implemented on server as well as client) +// +//notes: +//each model contains its own skeleton, reusing a skeleton with incompatible models will yield garbage (or not render). +//each model contains its own animation data, you can use animations from other model files (for example saving out all character animations as separate model files). +//if an engine supports loading an animation-only file format such as .md5anim in FTEQW, it can be used to animate any model with a compatible skeleton. +//proper use of this extension may require understanding matrix transforms (v_forward, v_right, v_up, origin), and you must keep in mind that v_right is negative for this purpose. +// +//features include: +//multiple animations blended together. +//animating a model with animations from another model with a compatible skeleton. +//restricting animation blends to certain bones of a model - for example independent animation of legs, torso, head. +//custom bone controllers - for example making eyes track a target location. +// +// +// +//example code follows... +// +//this helper function lets you identify (by parentage) what group a bone +//belongs to - for example "torso", "leftarm", would return 1 ("torso") for +//all children of the bone named "torso", unless they are children of +//"leftarm" (which is a child of "torso") which would return 2 instead... +float(float skel, float bonenum, string g1, string g2, string g3, string g4, string g5, string g6) example_skel_findbonegroup = +{ + local string bonename; + while (bonenum >= 0) + { + bonename = skel_get_bonename(skel, bonenum); + if (bonename == g1) return 1; + if (bonename == g2) return 2; + if (bonename == g3) return 3; + if (bonename == g4) return 4; + if (bonename == g5) return 5; + if (bonename == g6) return 6; + bonenum = skel_get_boneparent(skel, bonenum); + } + return 0; +}; +// create a skeletonindex for our player using current modelindex +void() example_skel_player_setup = +{ + self.skeletonindex = skel_create(self.modelindex); +}; +// setup bones of skeleton based on an animation +// note: animmodelindex can be a different model than self.modelindex +void(float animmodelindex, float framegroup, float framegroupstarttime) example_skel_player_update_begin = +{ + // start with our standard animation + self.frame = framegroup; + self.frame2 = 0; + self.frame3 = 0; + self.frame4 = 0; + self.frame1time = framegroupstarttime; + self.frame2time = 0; + self.frame3time = 0; + self.frame4time = 0; + self.lerpfrac = 0; + self.lerpfrac3 = 0; + self.lerpfrac4 = 0; + skel_build(self.skeletonindex, self, animmodelindex, 0, 0, 100000); +}; +// apply a different framegroup animation to bones with a specified parent +void(float animmodelindex, float framegroup, float framegroupstarttime, float blendalpha, string groupbonename, string excludegroupname1, string excludegroupname2) example_skel_player_update_applyoverride = +{ + local float bonenum; + local float numbones; + self.frame = framegroup; + self.frame2 = 0; + self.frame3 = 0; + self.frame4 = 0; + self.frame1time = framegroupstarttime; + self.frame2time = 0; + self.frame3time = 0; + self.frame4time = 0; + self.lerpfrac = 0; + self.lerpfrac3 = 0; + self.lerpfrac4 = 0; + bonenum = 0; + numbones = skel_get_numbones(self.skeletonindex); + while (bonenum < numbones) + { + if (example_skel_findbonegroup(self.skeletonindex, bonenum, groupbonename, excludegroupname1, excludegroupname2, "", "", "") == 1) + skel_build(self.skeletonindex, self, animmodelindex, 1 - blendalpha, bonenum, bonenum + 1); + bonenum = bonenum + 1; + } +}; +// make eyes point at a target location, be sure v_forward, v_right, v_up are set correctly before calling +void(vector eyetarget, string bonename) example_skel_player_update_eyetarget = +{ + local float bonenum; + local vector ang; + local vector oldforward, oldright, oldup; + local vector relforward, relright, relup, relorg; + local vector boneforward, boneright, boneup, boneorg; + local vector parentforward, parentright, parentup, parentorg; + local vector u, v; + local vector modeleyetarget; + bonenum = skel_find_bone(self.skeletonindex, bonename) - 1; + if (bonenum < 0) + return; + oldforward = v_forward; + oldright = v_right; + oldup = v_up; + v = eyetarget - self.origin; + modeleyetarget_x = v * v_forward; + modeleyetarget_y = 0-v * v_right; + modeleyetarget_z = v * v_up; + // this is an eyeball, make it point at the target location + // first get all the data we can... + relorg = skel_get_bonerel(self.skeletonindex, bonenum); + relforward = v_forward; + relright = v_right; + relup = v_up; + boneorg = skel_get_boneabs(self.skeletonindex, bonenum); + boneforward = v_forward; + boneright = v_right; + boneup = v_up; + parentorg = skel_get_boneabs(self.skeletonindex, skel_get_boneparent(self.skeletonindex, bonenum)); + parentforward = v_forward; + parentright = v_right; + parentup = v_up; + // get the vector from the eyeball to the target + u = modeleyetarget - boneorg; + // now transform it inversely by the parent matrix to produce new rel vectors + v_x = u * parentforward; + v_y = u * parentright; + v_z = u * parentup; + ang = vectoangles2(v, relup); + ang_x = 0 - ang_x; + makevectors(ang); + // set the relative bone matrix + skel_set_bone(self.skeletonindex, bonenum, relorg); + // restore caller's v_ vectors + v_forward = oldforward; + v_right = oldright; + v_up = oldup; +}; +// delete skeleton when we're done with it +// note: skeleton remains valid until next frame when it is really deleted +void() example_skel_player_delete = +{ + skel_delete(self.skeletonindex); + self.skeletonindex = 0; +}; +// +// END OF EXAMPLES FOR FTE_CSQC_SKELETONOBJECTS +// + +// assorted builtins +const float STAT_MOVEVARS_TICRATE = 240; +const float STAT_MOVEVARS_TIMESCALE = 241; +const float STAT_FRAGLIMIT = 235; +const float STAT_TIMELIMIT = 236; +const float STAT_MOVEVARS_GRAVITY = 242; +string(void) ReadPicture = #501; +float PARTICLES_USEALPHA = 1; +float particles_alphamin, particles_alphamax; +float PARTICLES_USECOLOR = 2; +vector particles_colormin, particles_colormax; +void(float effectindex, entity own, vector org_from, vector org_to, vector dir_from, vector dir_to, float countmultiplier, float flags) boxparticles = #502; +float trace_networkentity; +const float RF_FULLBRIGHT = 256; +const float RF_NOSHADOW = 512; +float RF_DYNAMICMODELLIGHT = 8192; diff --git a/qcsrc/dpdefs/dpextensions.qc b/qcsrc/dpdefs/dpextensions.qc new file mode 100644 index 0000000000..0acf262b11 --- /dev/null +++ b/qcsrc/dpdefs/dpextensions.qc @@ -0,0 +1,2541 @@ + +//DarkPlaces supported extension list, draft version 1.04 + +//things that don't have extensions yet: +.float disableclientprediction; + +//definitions that id Software left out: +//these are passed as the 'nomonsters' parameter to traceline/tracebox (yes really this was supported in all quake engines, nomonsters is misnamed) +float MOVE_NORMAL = 0; // same as FALSE +float MOVE_NOMONSTERS = 1; // same as TRUE +float MOVE_MISSILE = 2; // save as movement with .movetype == MOVETYPE_FLYMISSILE + +//checkextension function +//idea: expected by almost everyone +//darkplaces implementation: LordHavoc +float(string s) checkextension = #99; +//description: +//check if (cvar("pr_checkextension")) before calling this, this is the only +//guaranteed extension to be present in the extension system, it allows you +//to check if an extension is available, by name, to check for an extension +//use code like this: +//// (it is recommended this code be placed in worldspawn or a worldspawn called function somewhere) +//if (cvar("pr_checkextension")) +//if (checkextension("DP_SV_SETCOLOR")) +// ext_setcolor = TRUE; +//from then on you can check ext_setcolor to know if that extension is available + +//BX_WAL_SUPPORT +//idea: id Software +//darkplaces implementation: LordHavoc +//description: +//indicates the engine supports .wal textures for filenames in the textures/ directory +//(note: DarkPlaces has supported this since 2001 or 2002, but did not advertise it as an extension, then I noticed Betwix was advertising it and added the extension accordingly) + +//DP_BUTTONCHAT +//idea: Vermeulen +//darkplaces implementation: LordHavoc +//field definitions: +.float buttonchat; +//description: +//true if the player is currently chatting (in messagemode, menus or console) + +//DP_BUTTONUSE +//idea: id Software +//darkplaces implementation: LordHavoc +//field definitions: +.float buttonuse; +//client console commands: +//+use +//-use +//description: +//made +use and -use commands work, they now control the .buttonuse field (.button1 was used by many mods for other purposes). + +//DP_CL_LOADSKY +//idea: Nehahra, LordHavoc +//darkplaces implementation: LordHavoc +//client console commands: +//"loadsky" (parameters: "basename", example: "mtnsun_" would load "mtnsun_up.tga" and "mtnsun_rt.tga" and similar names, use "" to revert to quake sky, note: this is the same as Quake2 skybox naming) +//description: +//sets global skybox for the map for this client (can be stuffed to a client by QC), does not hurt much to repeatedly execute this command, please don't use this in mods if it can be avoided (only if changing skybox is REALLY needed, otherwise please use DP_GFX_SKYBOX). + +//DP_CON_SET +//idea: id Software +//darkplaces implementation: LordHavoc +//description: +//indicates this engine supports the "set" console command which creates or sets a non-archived cvar (not saved to config.cfg on exit), it is recommended that set and seta commands be placed in default.cfg for mod-specific cvars. + +//DP_CON_SETA +//idea: id Software +//darkplaces implementation: LordHavoc +//description: +//indicates this engine supports the "seta" console command which creates or sets an archived cvar (saved to config.cfg on exit), it is recommended that set and seta commands be placed in default.cfg for mod-specific cvars. + +//DP_CON_ALIASPARAMETERS +//idea: many +//darkplaces implementation: Black +//description: +//indicates this engine supports aliases containing $1 through $9 parameter macros (which when called will expand to the parameters passed to the alias, for example alias test "say $2 $1", then you can type test hi there and it will execute say there hi), as well as $0 (name of the alias) and $* (all parameters $1 onward). + +//DP_CON_EXPANDCVAR +//idea: many, PHP +//darkplaces implementation: Black +//description: +//indicates this engine supports console commandlines containing $cvarname which will expand to the contents of that cvar as a parameter, for instance say my fov is $fov, will say "my fov is 90", or similar. + +//DP_CON_STARTMAP +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//description: +//adds two engine-called aliases named startmap_sp and startmap_dm which are called when the engine tries to start a singleplayer game from the menu (startmap_sp) or the -listen or -dedicated options are used or the engine is a dedicated server (uses startmap_dm), these allow a mod or game to specify their own map instead of start, and also distinguish between singleplayer and -listen/-dedicated, also these need not be a simple "map start" command, they can do other things if desired, startmap_sp and startmap_dm both default to "map start". + +//DP_EF_ADDITIVE +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//effects bit: +float EF_ADDITIVE = 32; +//description: +//additive blending when this object is rendered + +//DP_EF_BLUE +//idea: id Software +//darkplaces implementation: LordHavoc +//effects bit: +float EF_BLUE = 64; +//description: +//entity emits blue light (used for quad) + +//DP_EF_DOUBLESIDED +//idea: LordHavoc +//darkplaces implementation: [515] and LordHavoc +//effects bit: +float EF_DOUBLESIDED = 32768; +//description: +//render entity as double sided (backfaces are visible, I.E. you see the 'interior' of the model, rather than just the front), can be occasionally useful on transparent stuff. + +//DP_EF_DYNAMICMODELLIGHT +//idea: C.Brutail, divVerent, maikmerten +//darkplaces implementation: divVerent +//effects bit: +float EF_DYNAMICMODELLIGHT = 131072; +//description: +//force dynamic model light on the entity, even if it's a BSP model (or anything else with lightmaps or light colors) + +//DP_EF_FLAME +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//effects bit: +float EF_FLAME = 1024; +//description: +//entity is on fire + +//DP_EF_FULLBRIGHT +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//effects bit: +float EF_FULLBRIGHT = 512; +//description: +//entity is always brightly lit + +//DP_EF_NODEPTHTEST +//idea: Supa +//darkplaces implementation: LordHavoc +//effects bit: +float EF_NODEPTHTEST = 8192; +//description: +//makes entity show up to client even through walls, useful with EF_ADDITIVE for special indicators like where team bases are in a map, so that people don't get lost + +//DP_EF_NODRAW +//idea: id Software +//darkplaces implementation: LordHavoc +//effects bit: +float EF_NODRAW = 16; +//description: +//prevents server from sending entity to client (forced invisible, even if it would have been a light source or other such things) + +//DP_EF_NOGUNBOB +//idea: Chris Page, Dresk +//darkplaces implementation: LordHAvoc +//effects bit: +float EF_NOGUNBOB = 256; +//description: +//this has different meanings depending on the entity it is used on: +//player entity - prevents gun bobbing on player.viewmodel +//viewmodelforclient entity - prevents gun bobbing on an entity attached to the player's view +//other entities - no effect +//uses: +//disabling gun bobbing on a diving mask or other model used as a .viewmodel. +//disabling gun bobbing on view-relative models meant to be part of the heads up display. (note: if fov is changed these entities may be off-screen, or too near the center of the screen, so use fov 90 in this case) + +//DP_EF_NOSHADOW +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//effects bit: +float EF_NOSHADOW = 4096; +//description: +//realtime lights will not cast shadows from this entity (but can still illuminate it) + +//DP_EF_RED +//idea: id Software +//darkplaces implementation: LordHavoc +//effects bit: +float EF_RED = 128; +//description: +//entity emits red light (used for invulnerability) + +//DP_EF_RESTARTANIM_BIT +//idea: id software +//darkplaces implementation: divVerent +//effects bit: +float EF_RESTARTANIM_BIT = 1048576; +//description: +//when toggled, the current animation is restarted. Useful for weapon animation. +//to toggle this bit in QC, you can do: +// self.effects += (EF_RESTARTANIM_BIT - 2 * (self.effects & EF_RESTARTANIM_BIT)); + +//DP_EF_STARDUST +//idea: MythWorks Inc +//darkplaces implementation: LordHavoc +//effects bit: +float EF_STARDUST = 2048; +//description: +//entity emits bouncing sparkles in every direction + +//DP_EF_TELEPORT_BIT +//idea: id software +//darkplaces implementation: divVerent +//effects bit: +float EF_TELEPORT_BIT = 2097152; +//description: +//when toggled, interpolation of the entity is skipped for one frame. Useful for teleporting. +//to toggle this bit in QC, you can do: +// self.effects += (EF_TELEPORT_BIT - 2 * (self.effects & EF_TELEPORT_BIT)); + +//DP_ENT_ALPHA +//idea: Nehahra +//darkplaces implementation: LordHavoc +//fields: +.float alpha; +//description: +//controls opacity of the entity, 0.0 is forced to be 1.0 (otherwise everything would be invisible), use -1 if you want to make something invisible, 1.0 is solid (like normal). + +//DP_ENT_COLORMOD +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//field definition: +.vector colormod; +//description: +//controls color of the entity, '0 0 0', is forced to be '1 1 1' (otherwise everything would be black), used for tinting objects, for instance using '1 0.6 0.4' on an ogre would give you an orange ogre (order is red green blue), note the colors can go up to '8 8 8' (8x as bright as normal). + +//DP_ENT_CUSTOMCOLORMAP +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//description: +//if .colormap is set to 1024 + pants + shirt * 16, those colors will be used for colormapping the entity, rather than looking up a colormap by player number. + +/* +//NOTE: no longer supported by darkplaces because all entities are delta compressed now +//DP_ENT_DELTACOMPRESS // no longer supported +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//effects bit: +float EF_DELTA = 8388608; +//description: +//(obsolete) applies delta compression to the network updates of the entity, making updates smaller, this might cause some unreliable behavior in packet loss situations, so it should only be used on numerous (nails/plasma shots/etc) or unimportant objects (gibs/shell casings/bullet holes/etc). +*/ + +//DP_ENT_EXTERIORMODELTOCLIENT +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//fields: +.entity exteriormodeltoclient; +//description: +//the entity is visible to all clients with one exception: if the specified client is using first person view (not using chase_active) the entity will not be shown. Also if tag attachments are supported any entities attached to the player entity will not be drawn in first person. + +//DP_ENT_GLOW +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//field definitions: +.float glow_color; +.float glow_size; +.float glow_trail; +//description: +//customizable glowing light effect on the entity, glow_color is a paletted (8bit) color in the range 0-255 (note: 0 and 254 are white), glow_size is 0 or higher (up to the engine what limit to cap it to, darkplaces imposes a 1020 limit), if glow_trail is true it will leave a trail of particles of the same color as the light. + +//DP_ENT_GLOWMOD +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//field definition: +.vector glowmod; +//description: +//controls color of the entity's glow texture (fullbrights), '0 0 0', is forced to be '1 1 1' (otherwise everything would be black), used for tinting objects, see colormod (same color restrictions apply). + +//DP_ENT_LOWPRECISION +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//effects bit: +float EF_LOWPRECISION = 4194304; +//description: +//uses low quality origin coordinates, reducing network traffic compared to the default high precision, intended for numerous objects (projectiles/gibs/bullet holes/etc). + +//DP_ENT_SCALE +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//field definitions: +.float scale; +//description: +//controls rendering scale of the object, 0 is forced to be 1, darkplaces uses 1/16th accuracy and a limit of 15.9375, can be used to make an object larger or smaller. + +//DP_ENT_TRAILEFFECTNUM +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//field definitions: +.float traileffectnum; +//description: +//use a custom effectinfo.txt effect on this entity, assign it like this: +//self.traileffectnum = particleeffectnum("mycustomeffect"); +//this will do both the dlight and particle trail as described in the effect, basically equivalent to trailparticles() in CSQC but performed on a server entity. + +//DP_ENT_VIEWMODEL +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//field definitions: +.entity viewmodelforclient; +//description: +//this is a very special capability, attachs the entity to the view of the client specified, origin and angles become relative to the view of that client, all effects can be used (multiple skins on a weapon model etc)... the entity is not visible to any other client. + +//DP_GFX_EXTERNALTEXTURES +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//description: +//loads external textures found in various directories (tenebrae compatible)... +/* +in all examples .tga is merely the base texture, it can be any of these: +.tga (base texture) +_glow.tga (fullbrights or other glowing overlay stuff, NOTE: this is done using additive blend, not alpha) +_pants.tga (pants overlay for colormapping on models, this should be shades of grey (it is tinted by pants color) and black wherever the base texture is not black, as this is an additive blend) +_shirt.tga (same idea as pants, but for shirt color) +_diffuse.tga (this may be used instead of base texture for per pixel lighting) +_gloss.tga (specular texture for per pixel lighting, note this can be in color (tenebrae only supports greyscale)) +_norm.tga (normalmap texture for per pixel lighting) +_bump.tga (bumpmap, converted to normalmap at load time, supported only for reasons of tenebrae compatibility) +_luma.tga (same as _glow but supported only for reasons of tenebrae compatibility) + +due to glquake's incomplete Targa(r) loader, this section describes +required Targa(r) features support: +types: +type 1 (uncompressed 8bit paletted with 24bit/32bit palette) +type 2 (uncompressed 24bit/32bit true color, glquake supported this) +type 3 (uncompressed 8bit greyscale) +type 9 (RLE compressed 8bit paletted with 24bit/32bit palette) +type 10 (RLE compressed 24bit/32bit true color, glquake supported this) +type 11 (RLE compressed 8bit greyscale) +attribute bit 0x20 (Origin At Top Left, top to bottom, left to right) + +image formats guaranteed to be supported: tga, pcx, lmp +image formats that are optional: png, jpg + +mdl/spr/spr32 examples: +skins are named _A (A being a number) and skingroups are named like _A_B +these act as suffixes on the model name... +example names for skin _2_1 of model "progs/armor.mdl": +game/override/progs/armor.mdl_2_1.tga +game/textures/progs/armor.mdl_2_1.tga +game/progs/armor.mdl_2_1.tga +example names for skin _0 of the model "progs/armor.mdl": +game/override/progs/armor.mdl_0.tga +game/textures/progs/armor.mdl_0.tga +game/progs/armor.mdl_0.tga +note that there can be more skins files (of the _0 naming) than the mdl +contains, this is only useful to save space in the .mdl file if classic quake +compatibility is not a concern. + +bsp/md2/md3 examples: +example names for the texture "quake" of model "maps/start.bsp": +game/override/quake.tga +game/textures/quake.tga +game/quake.tga + +sbar/menu/console textures: for example the texture "conchars" (console font) in gfx.wad +game/override/gfx/conchars.tga +game/textures/gfx/conchars.tga +game/gfx/conchars.tga +*/ + +//DP_GFX_EXTERNALTEXTURES_PERMAPTEXTURES +//idea: Fuh? +//darkplaces implementation: LordHavoc +//description: +//Q1BSP and HLBSP map loading loads external textures found in textures/<mapname>/ as well as textures/. +//Where mapname is the bsp filename minus the extension (typically .bsp) and minus maps/ if it is in maps/ (any other path is not removed) +//example: +//maps/e1m1.bsp uses textures in the directory textures/e1m1/ and falls back to textures/ +//maps/b_batt0.bsp uses textures in the directory textures/b_batt0.bsp and falls back to textures/ +//as a more extreme example: +//progs/something/blah.bsp uses textures in the directory textures/progs/something/blah/ and falls back to textures/ + +//DP_GFX_FOG +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//worldspawn fields: +//"fog" (parameters: "density red green blue", example: "0.1 0.3 0.3 0.3") +//description: +//global fog for the map, can not be changed by QC + +//DP_GFX_QUAKE3MODELTAGS +//idea: id Software +//darkplaces implementation: LordHavoc +//field definitions: +.entity tag_entity; // entity this is attached to (call setattachment to set this) +.float tag_index; // which tag on that entity (0 is relative to the entity, > 0 is an index into the tags on the model if it has any) (call setattachment to set this) +//builtin definitions: +void(entity e, entity tagentity, string tagname) setattachment = #443; // attachs e to a tag on tagentity (note: use "" to attach to entity origin/angles instead of a tag) +//description: +//allows entities to be visually attached to model tags (which follow animations perfectly) on other entities, for example attaching a weapon to a player's hand, or upper body attached to lower body, allowing it to change angles and frame separately (note: origin and angles are relative to the tag, use '0 0 0' for both if you want it to follow exactly, this is similar to viewmodelforclient's behavior). +//note 2: if the tag is not found, it defaults to "" (attach to origin/angles of entity) +//note 3: attaching to world turns off attachment +//note 4: the entity that this is attached to must be visible for this to work +//note 5: if an entity is attached to the player entity it will not be drawn in first person. + +//DP_GFX_SKINFILES +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//description: +//alias models (mdl, md2, md3) can have .skin files to replace conventional texture naming, these have a naming format such as: +//progs/test.md3_0.skin +//progs/test.md3_1.skin +//... +// +//these files contain replace commands (replace meshname shadername), example: +//replace "helmet" "progs/test/helmet1.tga" // this is a mesh shader replacement +//replace "teamstripes" "progs/test/redstripes.tga" +//replace "visor" "common/nodraw" // this makes the visor mesh invisible +////it is not possible to rename tags using this format +// +//Or the Quake3 syntax (100% compatible with Quake3's .skin files): +//helmet,progs/test/helmet1.tga // this is a mesh shader replacement +//teamstripes,progs/test/redstripes.tga +//visor,common/nodraw // this makes the visor mesh invisible +//tag_camera, // this defines that the first tag in the model is called tag_camera +//tag_test, // this defines that the second tag in the model is called tag_test +// +//any names that are not replaced are automatically show up as a grey checkerboard to indicate the error status, and "common/nodraw" is a special case that is invisible. +//this feature is intended to allow multiple skin sets on md3 models (which otherwise only have one skin set). +//other commands might be added someday but it is not expected. + +//DP_GFX_SKYBOX +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//worldspawn fields: +//"sky" (parameters: "basename", example: "mtnsun_" would load "mtnsun_up.tga" and "mtnsun_rt.tga" and similar names, note: "sky" is also used the same way by Quake2) +//description: +//global skybox for the map, can not be changed by QC + +//DP_UTF8 +//idea: Blub\0, divVerent +//darkplaces implementation: Blub\0 +//cvar definitions: +// utf8_enable: enable utf8 encoding +//description: utf8 characters are allowed inside cvars, protocol strings, files, progs strings, etc., +//and count as 1 char for string functions like strlen, substring, etc. +// note: utf8_enable is run-time cvar, could be changed during execution +// note: beware that str2chr() could return value bigger than 255 once utf8 is enabled + +//DP_HALFLIFE_MAP +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//description: +//simply indicates that the engine supports HalfLife maps (BSP version 30, NOT the QER RGBA ones which are also version 30). + +//DP_HALFLIFE_MAP_CVAR +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//cvars: +//halflifebsp 0/1 +//description: +//engine sets this cvar when loading a map to indicate if it is halflife format or not. + +//DP_HALFLIFE_SPRITE +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//description: +//simply indicates that the engine supports HalfLife sprites. + +//DP_INPUTBUTTONS +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//field definitions: +.float button3; +.float button4; +.float button5; +.float button6; +.float button7; +.float button8; +.float button9; +.float button10; +.float button11; +.float button12; +.float button13; +.float button14; +.float button15; +.float button16; +//description: +//set to the state of the +button3, +button4, +button5, +button6, +button7, and +button8 buttons from the client, this does not involve protocol changes (the extra 6 button bits were simply not used). +//the exact mapping of protocol button bits on the server is: +//self.button0 = (bits & 1) != 0; +///* button1 is skipped because mods abuse it as a variable, and accordingly it has no bit */ +//self.button2 = (bits & 2) != 0; +//self.button3 = (bits & 4) != 0; +//self.button4 = (bits & 8) != 0; +//self.button5 = (bits & 16) != 0; +//self.button6 = (bits & 32) != 0; +//self.button7 = (bits & 64) != 0; +//self.button8 = (bits & 128) != 0; + +// DP_LIGHTSTYLE_STATICVALUE +// idea: VorteX +// darkplaces implementation: VorteX +// description: allows alternative 'static' lightstyle syntax : "=value" +// examples: "=0.5", "=2.0", "=2.75" +// could be used to control switchable lights or making styled lights with brightness > 2 +// Warning: this extension is experimental. It safely works in CSQC, but SVQC use is limited by the fact +// that other engines (which do not support this extension) could connect to a game and misunderstand this kind of lightstyle syntax + +//DP_LITSPRITES +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//description: +//indicates this engine supports lighting on sprites, any sprite with ! in its filename (both on disk and in the qc) will be lit rather than having forced EF_FULLBRIGHT (EF_FULLBRIGHT on the entity can still force these sprites to not be lit). + +//DP_LITSUPPORT +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//description: +//indicates this engine loads .lit files for any quake1 format .bsp files it loads to enhance maps with colored lighting. +//implementation description: these files begin with the header QLIT followed by version number 1 (as little endian 32bit), the rest of the file is a replacement lightmaps lump, except being 3x as large as the lightmaps lump of the map it matches up with (and yes the between-lightmap padding is expanded 3x to keep this consistent), so the lightmap offset in each surface is simply multiplied by 3 during loading to properly index the lit data, and the lit file is loaded instead of the lightmap lump, other renderer changes are needed to display these of course... see the litsupport.zip sample code (almost a tutorial) at http://icculus.org/twilight/darkplaces for more information. + +//DP_MONSTERWALK +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//description: +//MOVETYPE_WALK is permitted on non-clients, so bots can move smoothly, run off ledges, etc, just like a real player. + +//DP_MOVETYPEBOUNCEMISSILE +//idea: id Software +//darkplaces implementation: id Software +//movetype definitions: +//float MOVETYPE_BOUNCEMISSILE = 11; // already in defs.qc +//description: +//MOVETYPE_BOUNCE but without gravity, and with full reflection (no speed loss like grenades have), in other words - bouncing laser bolts. + +//DP_MOVETYPEFLYWORLDONLY +//idea: Samual +//darkplaces implementation: Samual +//movetype definitions: +float MOVETYPE_FLY_WORLDONLY = 33; +//description: +//like MOVETYPE_FLY, but does all traces with MOVE_WORLDONLY, and is ignored by MOVETYPE_PUSH. Should only be combined with SOLID_NOT and SOLID_TRIGGER. + +//DP_NULL_MODEL +//idea: Chris +//darkplaces implementation: divVerent +//definitions: +//string dp_null_model = "null"; +//description: +//setmodel(e, "null"); makes an entity invisible, have a zero bbox, but +//networked. useful for shared CSQC entities. + +//DP_MOVETYPEFOLLOW +//idea: id Software, LordHavoc (redesigned) +//darkplaces implementation: LordHavoc +//movetype definitions: +float MOVETYPE_FOLLOW = 12; +//description: +//MOVETYPE_FOLLOW implemented, this uses existing entity fields in unusual ways: +//aiment - the entity this is attached to. +//punchangle - the original angles when the follow began. +//view_ofs - the relative origin (note that this is un-rotated by punchangle, and that is actually the only purpose of punchangle). +//v_angle - the relative angles. +//here's an example of how you would set a bullet hole sprite to follow a bmodel it was created on, even if the bmodel rotates: +//hole.movetype = MOVETYPE_FOLLOW; // make the hole follow +//hole.solid = SOLID_NOT; // MOVETYPE_FOLLOW is always non-solid +//hole.aiment = bmodel; // make the hole follow bmodel +//hole.punchangle = bmodel.angles; // the original angles of bmodel +//hole.view_ofs = hole.origin - bmodel.origin; // relative origin +//hole.v_angle = hole.angles - bmodel.angles; // relative angles + +//DP_QC_ASINACOSATANATAN2TAN +//idea: Urre +//darkplaces implementation: LordHavoc +//constant definitions: +float DEG2RAD = 0.0174532925199432957692369076848861271344287188854172545609719144; +float RAD2DEG = 57.2957795130823208767981548141051703324054724665643215491602438612; +float PI = 3.1415926535897932384626433832795028841971693993751058209749445923; +//builtin definitions: +float(float s) asin = #471; // returns angle in radians for a given sin() value, the result is in the range -PI*0.5 to PI*0.5 +float(float c) acos = #472; // returns angle in radians for a given cos() value, the result is in the range 0 to PI +float(float t) atan = #473; // returns angle in radians for a given tan() value, the result is in the range -PI*0.5 to PI*0.5 +float(float c, float s) atan2 = #474; // returns angle in radians for a given cos() and sin() value pair, the result is in the range -PI to PI (this is identical to vectoyaw except it returns radians rather than degrees) +float(float a) tan = #475; // returns tangent value (which is simply sin(a)/cos(a)) for the given angle in radians, the result is in the range -infinity to +infinity +//description: +//useful math functions for analyzing vectors, note that these all use angles in radians (just like the cos/sin functions) not degrees unlike makevectors/vectoyaw/vectoangles, so be sure to do the appropriate conversions (multiply by DEG2RAD or RAD2DEG as needed). +//note: atan2 can take unnormalized vectors (just like vectoyaw), and the function was included only for completeness (more often you want vectoyaw or vectoangles), atan2(v_x,v_y) * RAD2DEG gives the same result as vectoyaw(v) + +//DP_QC_AUTOCVARS +//idea: divVerent +//darkplaces implementation: divVerent +//description: +//allows QC variables to be bound to cvars +//(works for float, string, vector types) +//example: +// float autocvar_developer; +// float autocvar_registered; +// string autocvar__cl_name; +//NOTE: copying a string-typed autocvar to another variable/field, and then +//changing the cvar or returning from progs is UNDEFINED. Writing to autocvar +//globals is UNDEFINED. Accessing autocvar globals after cvar_set()ing that +//cvar in the same frame is IMPLEMENTATION DEFINED (an implementation may +//either yield the previous, or the current, value). Whether autocvar globals, +//after restoring a savegame, have the cvar's current value, or the original +//value at time of saving, is UNDEFINED. Restoring a savegame however must not +//restore the cvar values themselves. +//In case the cvar does NOT exist, then it is automatically created with the +//value of the autocvar initializer, if given. This is possible with e.g. +//frikqcc and fteqcc the following way: +// var float autocvar_whatever = 42; +//If no initializer is given, the cvar will be initialized to a string +//equivalent to the NULL value of the given data type, that is, the empty +//string, 0, or '0 0 0'. However, when automatic cvar creation took place, a +//warning is printed to the game console. +//NOTE: to prevent an ambiguity with float names for vector types, autocvar +//names MUST NOT end with _x, _y or _z! + +//DP_QC_CHANGEPITCH +//idea: id Software +//darkplaces implementation: id Software +//field definitions: +.float idealpitch; +.float pitch_speed; +//builtin definitions: +void(entity ent) changepitch = #63; +//description: +//equivalent to changeyaw, ent is normally self. (this was a Q2 builtin) + +//DP_QC_COPYENTITY +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +void(entity from, entity to) copyentity = #400; +//description: +//copies all data in the entity to another entity. + +//DP_QC_CRC16 +//idea: divVerent +//darkplaces implementation: divVerent +//Some hash function to build hash tables with. This has to be be the CRC-16-CCITT that is also required for the QuakeWorld download protocol. +//When caseinsensitive is set, the CRC is calculated of the lower cased string. +float(float caseinsensitive, string s, ...) crc16 = #494; + +//DP_QC_CVAR_DEFSTRING +//idea: id Software (Doom3), LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +string(string s) cvar_defstring = #482; +//description: +//returns the default value of a cvar, as a tempstring. + +//DP_QC_CVAR_DESCRIPTION +//idea: divVerent +//DarkPlaces implementation: divVerent +//builtin definitions: +string(string name) cvar_description = #518; +//description: +//returns the description of a cvar + +//DP_QC_CVAR_STRING +//idea: VorteX +//DarkPlaces implementation: VorteX, LordHavoc +//builtin definitions: +string(string s) cvar_string = #448; +//description: +//returns the value of a cvar, as a tempstring. + +//DP_QC_CVAR_TYPE +//idea: divVerent +//DarkPlaces implementation: divVerent +//builtin definitions: +float(string name) cvar_type = #495; +float CVAR_TYPEFLAG_EXISTS = 1; +float CVAR_TYPEFLAG_SAVED = 2; +float CVAR_TYPEFLAG_PRIVATE = 4; +float CVAR_TYPEFLAG_ENGINE = 8; +float CVAR_TYPEFLAG_HASDESCRIPTION = 16; +float CVAR_TYPEFLAG_READONLY = 32; + +//DP_QC_DIGEST +//idea: motorsep, Spike +//DarkPlaces implementation: divVerent +//builtin definitions: +string(string digest, string data, ...) digest_hex = #639; +//description: +//returns a given hex digest of given data +//the returned digest is always encoded in hexadecimal +//only the "MD4" digest is always supported! +//if the given digest is not supported, string_null is returned +//the digest string is matched case sensitively, use "MD4", not "md4"! + +//DP_QC_DIGEST_SHA256 +//idea: motorsep, Spike +//DarkPlaces implementation: divVerent +//description: +//"SHA256" is also an allowed digest type + +//DP_QC_EDICT_NUM +//idea: 515 +//DarkPlaces implementation: LordHavoc +//builtin definitions: +entity(float entnum) edict_num = #459; +float(entity ent) wasfreed = #353; // same as in EXT_CSQC extension +//description: +//edict_num returns the entity corresponding to a given number, this works even for freed entities, but you should call wasfreed(ent) to see if is currently active. +//wasfreed returns whether an entity slot is currently free (entities that have never spawned are free, entities that have had remove called on them are also free). + +//DP_QC_ENTITYDATA +//idea: KrimZon +//darkplaces implementation: KrimZon +//builtin definitions: +float() numentityfields = #496; +string(float fieldnum) entityfieldname = #497; +float(float fieldnum) entityfieldtype = #498; +string(float fieldnum, entity ent) getentityfieldstring = #499; +float(float fieldnum, entity ent, string s) putentityfieldstring = #500; +//constants: +//Returned by entityfieldtype +float FIELD_STRING = 1; +float FIELD_FLOAT = 2; +float FIELD_VECTOR = 3; +float FIELD_ENTITY = 4; +float FIELD_FUNCTION = 6; +//description: +//Versatile functions intended for storing data from specific entities between level changes, but can be customized for some kind of partial savegame. +//WARNING: .entity fields cannot be saved and restored between map loads as they will leave dangling pointers. +//numentityfields returns the number of entity fields. NOT offsets. Vectors comprise 4 fields: v, v_x, v_y and v_z. +//entityfieldname returns the name as a string, eg. "origin" or "classname" or whatever. +//entityfieldtype returns a value that the constants represent, but the field may be of another type in more exotic progs.dat formats or compilers. +//getentityfieldstring returns data as would be written to a savegame, eg... "0.05" (float), "0 0 1" (vector), or "Hello World!" (string). Function names can also be returned. +//putentityfieldstring puts the data returned by getentityfieldstring back into the entity. + +//DP_QC_ENTITYSTRING +void(string s) loadfromdata = #529; +void(string s) loadfromfile = #530; +void(string s) callfunction = #605; +void(float fh, entity e) writetofile = #606; +float(string s) isfunction = #607; +void(entity e, string s) parseentitydata = #608; + +//DP_QC_ETOS +//idea: id Software +//darkplaces implementation: id Software +//builtin definitions: +string(entity ent) etos = #65; +//description: +//prints "entity 1" or similar into a string. (this was a Q2 builtin) + +//DP_QC_EXTRESPONSEPACKET +//idea: divVerent +//darkplaces implementation: divVerent +//builtin definitions: +string(void) getextresponse = #624; +//description: +//returns a string of the form "\"ipaddress:port\" data...", or the NULL string +//if no packet was found. Packets can be queued into the client/server by +//sending a packet starting with "\xFF\xFF\xFF\xFFextResponse " to the +//listening port. + +//DP_QC_FINDCHAIN +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +entity(.string fld, string match) findchain = #402; +//description: +//similar to find() but returns a chain of entities like findradius. + +//DP_QC_FINDCHAIN_TOFIELD +//idea: divVerent +//darkplaces implementation: divVerent +//builtin definitions: +entity(.string fld, float match, .entity tofield) findradius_tofield = #22; +entity(.string fld, string match, .entity tofield) findchain_tofield = #402; +entity(.string fld, float match, .entity tofield) findchainflags_tofield = #450; +entity(.string fld, float match, .entity tofield) findchainfloat_tofield = #403; +//description: +//similar to findchain() etc, but stores the chain into .tofield instead of .chain +//actually, the .entity tofield is an optional field of the the existing findchain* functions + +//DP_QC_FINDCHAINFLAGS +//idea: Sajt +//darkplaces implementation: LordHavoc +//builtin definitions: +entity(.float fld, float match) findchainflags = #450; +//description: +//similar to findflags() but returns a chain of entities like findradius. + +//DP_QC_FINDCHAINFLOAT +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +entity(.entity fld, entity match) findchainentity = #403; +entity(.float fld, float match) findchainfloat = #403; +//description: +//similar to findentity()/findfloat() but returns a chain of entities like findradius. + +//DP_QC_FINDFLAGS +//idea: Sajt +//darkplaces implementation: LordHavoc +//builtin definitions: +entity(entity start, .float fld, float match) findflags = #449; +//description: +//finds an entity with the specified flag set in the field, similar to find() + +//DP_QC_FINDFLOAT +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +entity(entity start, .entity fld, entity match) findentity = #98; +entity(entity start, .float fld, float match) findfloat = #98; +//description: +//finds an entity or float field value, similar to find(), but for entity and float fields. + +//DP_QC_FS_SEARCH +//idea: Black +//darkplaces implementation: Black +//builtin definitions: +float(string pattern, float caseinsensitive, float quiet) search_begin = #444; +void(float handle) search_end = #445; +float(float handle) search_getsize = #446; +string(float handle, float num) search_getfilename = #447; +//description: +//search_begin performs a filename search with the specified pattern (for example "maps/*.bsp") and stores the results in a search slot (minimum of 128 supported by any engine with this extension), the other functions take this returned search slot number, be sure to search_free when done (they are also freed on progs reload). +//search_end frees a search slot (also done at progs reload). +//search_getsize returns how many filenames were found. +//search_getfilename returns a filename from the search. + +//DP_QC_GETLIGHT +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +vector(vector org) getlight = #92; +//description: +//returns the lighting at the requested location (in color), 0-255 range (can exceed 255). + +//DP_QC_GETSURFACE +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +float(entity e, float s) getsurfacenumpoints = #434; +vector(entity e, float s, float n) getsurfacepoint = #435; +vector(entity e, float s) getsurfacenormal = #436; +string(entity e, float s) getsurfacetexture = #437; +float(entity e, vector p) getsurfacenearpoint = #438; +vector(entity e, float s, vector p) getsurfaceclippedpoint = #439; +//description: +//functions to query surface information. + +//DP_QC_GETSURFACEPOINTATTRIBUTE +//idea: BlackHC +//darkplaces implementation: BlackHC +// constants +float SPA_POSITION = 0; +float SPA_S_AXIS = 1; +float SPA_T_AXIS = 2; +float SPA_R_AXIS = 3; // same as SPA_NORMAL +float SPA_TEXCOORDS0 = 4; +float SPA_LIGHTMAP0_TEXCOORDS = 5; +float SPA_LIGHTMAP0_COLOR = 6; +//builtin definitions: +vector(entity e, float s, float n, float a) getsurfacepointattribute = #486; + +//description: +//function to query extended information about a point on a certain surface + +//DP_QC_GETSURFACETRIANGLE +//idea: divVerent +//darkplaces implementation: divVerent +//builtin definitions: +float(entity e, float s) getsurfacenumtriangles = #628; +vector(entity e, float s, float n) getsurfacetriangle = #629; +//description: +//function to query triangles of a surface + +//DP_QC_GETTAGINFO +//idea: VorteX, LordHavoc +//DarkPlaces implementation: VorteX +//builtin definitions: +float(entity ent, string tagname) gettagindex = #451; +vector(entity ent, float tagindex) gettaginfo = #452; +//description: +//gettagindex returns the number of a tag on an entity, this number is the same as set by setattachment (in the .tag_index field), allowing the qc to save a little cpu time by keeping the number around if it wishes (this could already be done by calling setattachment and saving off the tag_index). +//gettaginfo returns the origin of the tag in worldspace and sets v_forward, v_right, and v_up to the current orientation of the tag in worldspace, this automatically resolves all dependencies (attachments, including viewmodelforclient), this means you could fire a shot from a tag on a gun entity attached to the view for example. + +//DP_QC_GETTAGINFO_BONEPROPERTIES +//idea: daemon +//DarkPlaces implementation: divVerent +//global definitions: +float gettaginfo_parent; +string gettaginfo_name; +vector gettaginfo_offset; +vector gettaginfo_forward; +vector gettaginfo_right; +vector gettaginfo_up; +//description: +//when this extension is present, gettaginfo fills in some globals with info about the bone that had been queried +//gettaginfo_parent is set to the number of the parent bone, or 0 if it is a root bone +//gettaginfo_name is set to the name of the bone whose index had been specified in gettaginfo +//gettaginfo_offset, gettaginfo_forward, gettaginfo_right, gettaginfo_up contain the transformation matrix of the bone relative to its parent. Note that the matrix may contain a scaling component. + +//DP_QC_GETTIME +//idea: tZork +//darkplaces implementation: tZork, divVerent +//constant definitions: +float GETTIME_FRAMESTART = 0; // time of start of frame +float GETTIME_REALTIME = 1; // current time (may be OS specific) +float GETTIME_HIRES = 2; // like REALTIME, but may reset between QC invocations and thus can be higher precision +float GETTIME_UPTIME = 3; // time since start of the engine +//builtin definitions: +float(float tmr) gettime = #519; +//description: +//some timers to query... + +//DP_QC_GETTIME_CDTRACK +//idea: divVerent +//darkplaces implementation: divVerent +//constant definitions: +float GETTIME_CDTRACK = 4; +//description: +//returns the playing time of the current cdtrack when passed to gettime() +//see DP_END_GETSOUNDTIME for similar functionality but for entity sound channels + +//DP_QC_I18N +//idea: divVerent +//darkplaces implementation: divVerent +//description: +// +//The engine supports translating by gettext compatible .po files. +//progs.dat uses progs.dat.<LANGUAGE>.po +//menu.dat uses menu.dat.<LANGUAGE>.po +//csprogs.dat uses csprogs.dat.<LANGUAGE>.po +// +//To create a string that can be translated, define it as +// string dotranslate_FILENOTFOUND = "File not found"; +//Note: if the compiler does constant folding, this will only work if there is +//no other "File not found" string in the progs! +// +//Alternatively, if using the Xonotic patched fteqcc compiler, you can simplify +//this by using _("File not found") directly in the source code. +// +//The language is set by the "prvm_language" cvar: if prvm_language is set to +//"de", it will read progs.dat.de.po for translating strings in progs.dat. +// +//If prvm_language is set to the special name "dump", progs.dat.pot will be +//written, which is a translation template to be edited by filling out the +//msgstr entries. + +//DP_QC_LOG +//darkplaces implementation: divVerent +//builtin definitions: +float log(float f) = #532; +//description: +//logarithm + +//DP_QC_MINMAXBOUND +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +float(float a, float b, ...) min = #94; +float(float a, float b, float c) min3 = #94; +float(float a, float b, float c, float d) min4 = #94; +float(float a, float b, float c, float d, float e) min5 = #94; +float(float a, float b, float c, float d, float e, float f) min6 = #94; +float(float a, float b, float c, float d, float e, float f, float g) min7 = #94; +float(float a, float b, float c, float d, float e, float f, float g, float h) min8 = #94; +float(float a, float b, ...) max = #95; +float(float a, float b, float c) max3 = #95; +float(float a, float b, float c, float d) max4 = #95; +float(float a, float b, float c, float d, float e) max5 = #95; +float(float a, float b, float c, float d, float e, float f) max6 = #95; +float(float a, float b, float c, float d, float e, float f, float g) max7 = #95; +float(float a, float b, float c, float d, float e, float f, float g, float h) max8 = #95; +float(float minimum, float val, float maximum) bound = #96; +//description: +//min returns the lowest of all the supplied numbers. +//max returns the highest of all the supplied numbers. +//bound clamps the value to the range and returns it. + +//DP_QC_MULTIPLETEMPSTRINGS +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//description: +//this extension makes all builtins returning tempstrings (ftos for example) +//cycle through a pool of multiple tempstrings (at least 16), allowing +//multiple ftos results to be gathered before putting them to use, normal +//quake only had 1 tempstring, causing many headaches. +// +//Note that for longer term storage (or compatibility on engines having +//FRIK_FILE but not this extension) the FRIK_FILE extension's +//strzone/strunzone builtins provide similar functionality (slower though). +// +//NOTE: this extension is superseded by DP_QC_UNLIMITEDTEMPSTRINGS + +//DP_QC_NUM_FOR_EDICT +//idea: Blub\0 +//darkplaces implementation: Blub\0 +//Function to get the number of an entity - a clean way. +float(entity num) num_for_edict = #512; + +//DP_QC_RANDOMVEC +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +vector() randomvec = #91; +//description: +//returns a vector of length < 1, much quicker version of this QC: do {v_x = random()*2-1;v_y = random()*2-1;v_z = random()*2-1;} while(vlen(v) > 1) + +//DP_QC_SINCOSSQRTPOW +//idea: id Software, LordHavoc +//darkplaces implementation: id Software, LordHavoc +//builtin definitions: +float(float val) sin = #60; +float(float val) cos = #61; +float(float val) sqrt = #62; +float(float a, float b) pow = #97; +//description: +//useful math functions, sine of val, cosine of val, square root of val, and raise a to power b, respectively. + +//DP_QC_SPRINTF +//idea: divVerent +//darkplaces implementation: divVerent +//builtin definitions: +string(string format, ...) sprintf = #627; +//description: +//you know sprintf :P +//supported stuff: +// % +// optional: <argpos>$ for the argument to format +// flags: #0- + +// optional: <width>, *, or *<argpos>$ for the field width +// optional: .<precision>, .*, or .*<argpos>$ for the precision +// length modifiers: h for forcing a float, l for forcing an int/entity (by default, %d etc. cast a float to int) +// conversions: +// d takes a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to an int +// i takes an int/entity if no length is specified or i is, and a float if h is specified as length, and cast it to an int +// ouxXc take a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to an unsigned int +// eEfFgG take a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to a double +// s takes a string +// vV takes a vector, and processes the three components as if it were a gG for all three components, separated by space +// For conversions s and c, the flag # makes precision and width interpreted +// as byte count, by default it is interpreted as character count in UTF-8 +// enabled engines. No other conversions can create wide characters, and # +// has another meaning in these. When in character count mode, color codes +// are ignored. To get UTF-8 semantics WITHOUT color code parsing, use +// the + flag. + +//DP_QC_STRFTIME +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +string(float uselocaltime, string format, ...) strftime = #478; +//description: +//provides the ability to get the local (in your timezone) or world (Universal Coordinated Time) time as a string using the formatting of your choice: +//example: "%Y-%m-%d %H:%M:%S" (result looks like: 2007-02-08 01:03:15) +//note: "%F %T" gives the same result as "%Y-%m-%d %H:%M:%S" (ISO 8601 date format and 24-hour time) +//for more format codes please do a web search for strftime 3 and you should find the man(3) pages for this standard C function. +// +//practical uses: +//changing day/night cycle (shops closing, monsters going on the prowl) in an RPG, for this you probably want to use s = strftime(TRUE, "%H");hour = stof(s); +//printing current date/time for competitive multiplayer games, such as the beginning/end of each round in real world time. +//activating eastereggs in singleplayer games on certain dates. +// +//note: some codes such as %x and %X use your locale settings and thus may not make sense to international users, it is not advisable to use these as the server and clients may be in different countries. +//note: if you display local time to a player, it would be a good idea to note whether it is local time using a string like "%F %T (local)", and otherwise use "%F %T (UTC)". +//note: be aware that if the game is saved and reloaded a week later the date and time will be different, so if activating eastereggs in a singleplayer game or something you may want to only check when a level is loaded and then keep the same easteregg state throughout the level so that the easteregg does not deactivate when reloading from a savegame (also be aware that precaches should not depend on such date/time code because reloading a savegame often scrambles the precaches if so!). +//note: this function can return a NULL string (you can check for it with if (!s)) if the localtime/gmtime functions returned NULL in the engine code, such as if those functions don't work on this platform (consoles perhaps?), so be aware that this may return nothing. + +//DP_QC_STRINGCOLORFUNCTIONS +//idea: Dresk +//darkplaces implementation: Dresk +//builtin definitions: +float(string s) strlennocol = #476; // returns how many characters are in a string, minus color codes +string(string s) strdecolorize = #477; // returns a string minus the color codes of the string provided +//description: +//provides additional functionality to strings by supporting functions that isolate and identify strings with color codes + +//DP_QC_STRING_CASE_FUNCTIONS +//idea: Dresk +//darkplaces implementation: LordHavoc / Dresk +//builtin definitions: +string(string s) strtolower = #480; // returns the passed in string in pure lowercase form +string(string s) strtoupper = #481; // returns the passed in string in pure uppercase form +//description: +//provides simple string uppercase and lowercase functions + +//DP_QC_TOKENIZEBYSEPARATOR +//idea: Electro, SavageX, LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +float(string s, string separator1, ...) tokenizebyseparator = #479; +//description: +//this function returns tokens separated by any of the supplied separator strings, example: +//numnumbers = tokenizebyseparator("10.2.3.4", "."); +//returns 4 and the tokens are "10" "2" "3" "4" +//possibly useful for parsing IPv4 addresses (such as "1.2.3.4") and IPv6 addresses (such as "[1234:5678:9abc:def0:1234:5678:9abc:def0]:26000") + +//DP_QC_TOKENIZE_CONSOLE +//idea: divVerent +//darkplaces implementation: divVerent +//builtin definitions: +float(string s) tokenize_console = #514; +float(float i) argv_start_index = #515; +float(float i) argv_end_index = #516; +//description: +//this function returns tokens separated just like the console does +//also, functions are provided to get the index of the first and last character of each token in the original string +//Passing negative values to them, or to argv, will be treated as indexes from the LAST token (like lists work in Perl). So argv(-1) will return the LAST token. + +//DP_QC_TRACEBOX +//idea: id Software +//darkplaces implementation: id Software +//builtin definitions: +void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox = #90; +//description: +//similar to traceline but much more useful, traces a box of the size specified (technical note: in quake1 and halflife bsp maps the mins and maxs will be rounded up to one of the hull sizes, quake3 bsp does not have this problem, this is the case with normal moving entities as well). + +//DP_QC_TRACETOSS +//idea: id Software +//darkplaces implementation: id Software +//builtin definitions: +void(entity ent, entity ignore) tracetoss = #64; +//description: +//simulates movement of the entity as if it is MOVETYPE_TOSS and starting with it's current state (location, velocity, etc), returns relevant trace_ variables (trace_fraction is always 0, all other values are supported - trace_ent, trace_endpos, trace_plane_normal), does not actually alter the entity. + +//DP_QC_TRACE_MOVETYPE_HITMODEL +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//constant definitions: +float MOVE_HITMODEL = 4; +//description: +//allows traces to hit alias models (not sprites!) instead of entity boxes, use as the nomonsters parameter to trace functions, note that you can hit invisible model entities (alpha < 0 or EF_NODRAW or model "", it only checks modelindex) + +//DP_QC_TRACE_MOVETYPE_WORLDONLY +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//constant definitions: +float MOVE_WORLDONLY = 3; +//description: +//allows traces to hit only world (ignoring all entities, unlike MOVE_NOMONSTERS which hits all bmodels), use as the nomonsters parameter to trace functions + +//DP_QC_UNLIMITEDTEMPSTRINGS +//idea: divVerent +//darkplaces implementation: LordHavoc +//description: +//this extension alters Quake behavior such that instead of reusing a single +//tempstring (or multiple) there are an unlimited number of tempstrings, which +//are removed only when a QC function invoked by the engine returns, +//eliminating almost all imaginable concerns with string handling in QuakeC. +// +//in short: +//you can now use and abuse tempstrings as much as you like, you still have to +//use strzone (FRIK_FILE) for permanent storage however. +// +// +// +//implementation notes for other engine coders: +//these tempstrings are expected to be stored in a contiguous buffer in memory +//which may be fixed size or controlled by a cvar, or automatically grown on +//demand (in the case of DarkPlaces). +// +//this concept is similar to quake's Zone system, however these are all freed +//when the QC interpreter returns. +// +//this is basically a poor man's garbage collection system for strings. + +//DP_QC_VECTOANGLES_WITH_ROLL +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +vector(vector forward, vector up) vectoangles2 = #51; // same number as vectoangles +//description: +//variant of vectoangles that takes an up vector to calculate roll angle (also uses this to calculate yaw correctly if the forward is straight up or straight down) +//note: just like normal vectoangles you need to negate the pitch of the returned angles if you want to feed them to makevectors or assign to self.v_angle + +//DP_QC_VECTORVECTORS +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +void(vector dir) vectorvectors = #432; +//description: +//creates v_forward, v_right, and v_up vectors given a forward vector, similar to makevectors except it takes a forward direction vector instead of angles. + +//DP_QC_WHICHPACK +//idea: divVerent +//darkplaces implementation: divVerent +//builtin definitions: +string(string filename) whichpack = #503; +//description: +//returns the name of the pak/pk3/whatever containing the given file, in the same path space as FRIK_FILE functions use (that is, possibly with a path name prefix) + +//DP_QC_URI_ESCAPE +//idea: divVerent +//darkplaces implementation: divVerent +//URI::Escape's functionality +string(string in) uri_escape = #510; +string(string in) uri_unescape = #511; + +//DP_QC_URI_GET +//idea: divVerent +//darkplaces implementation: divVerent +//loads text from an URL into a string +//returns 1 on success of initiation, 0 if there are too many concurrent +//connections already or if the URL is invalid +//the following callback will receive the data and MUST exist! +// void(float id, float status, string data) URI_Get_Callback; +//status is either +// negative for an internal error, +// 0 for success, or +// the HTTP response code on server error (e.g. 404) +//if 1 is returned by uri_get, the callback will be called in the future +float(string url, float id) uri_get = #513; + +//DP_QC_URI_POST +//idea: divVerent +//darkplaces implementation: divVerent +//loads text from an URL into a string after POSTing via HTTP +//works like uri_get, but uri_post sends data with Content-Type: content_type to the server +//and uri_post sends the string buffer buf, joined using the delimiter delim +float(string url, float id, string content_type, string data) uri_post = #513; +float(string url, float id, string content_type, string delim, float buf) uri_postbuf = #513; + +//DP_SKELETONOBJECTS +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//description: +//this extension indicates that FTE_CSQC_SKELETONOBJECTS functionality is available in server QC (as well as CSQC). + +//DP_SV_SPAWNFUNC_PREFIX +//idea: divVerent +//darkplaces implementation: divVerent +//Make functions whose name start with spawnfunc_ take precedence as spawn function for loading entities. +//Useful if you have a field ammo_shells (required in any Quake mod) but want to support spawn functions called ammo_shells (like in Q3A). +//Optionally, you can declare a global "float require_spawnfunc_prefix;" which will require ANY spawn function to start with that prefix. + + +//DP_QUAKE2_MODEL +//idea: quake community +//darkplaces implementation: LordHavoc +//description: +//shows that the engine supports Quake2 .md2 files. + +//DP_QUAKE2_SPRITE +//idea: LordHavoc +//darkplaces implementation: Elric +//description: +//shows that the engine supports Quake2 .sp2 files. + +//DP_QUAKE3_MAP +//idea: quake community +//darkplaces implementation: LordHavoc +//description: +//shows that the engine supports Quake3 .bsp files. + +//DP_QUAKE3_MODEL +//idea: quake community +//darkplaces implementation: LordHavoc +//description: +//shows that the engine supports Quake3 .md3 files. + +//DP_REGISTERCVAR +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +float(string name, string value) registercvar = #93; +//description: +//adds a new console cvar to the server console (in singleplayer this is the player's console), the cvar exists until the mod is unloaded or the game quits. +//NOTE: DP_CON_SET is much better. + +//DP_SND_DIRECTIONLESSATTNNONE +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//description: +//make sounds with ATTN_NONE have no spatialization (enabling easy use as music sources). + +//DP_SND_FAKETRACKS +//idea: requested + +//darkplaces implementation: Elric +//description: +//the engine plays sound/cdtracks/track001.wav instead of cd track 1 and so on if found, this allows games and mods to have music tracks without using ambientsound. +//Note: also plays .ogg with DP_SND_OGGVORBIS extension. + +//DP_SND_SOUND7_WIP1 +//DP_SND_SOUND7_WIP2 +//idea: divVerent +//darkplaces implementation: divVerent +//builtin definitions: +void(entity e, float chan, string samp, float vol, float atten, float speed, float flags) sound7 = #8; +float SOUNDFLAG_RELIABLE = 1; +//description: +//plays a sound, with some more flags +//extensions to sound(): +//- channel may be in the range from -128 to 127; channels -128 to 0 are "auto", +// i.e. support multiple sounds at once, but cannot be stopped/restarted +//- a value 0 in the speed parameter means no change; otherwise, it is a +// percentage of playback speed ("pitch shifting"). 100 is normal pitch, 50 is +// half speed, 200 is double speed, etc. (DP_SND_SOUND7_WIP2) +//- the flag SOUNDFLAG_RELIABLE can be specified, which makes the sound send +// to MSG_ALL (reliable) instead of MSG_BROADCAST (unreliable, default); +// similarily, SOUNDFLAG_RELIABLE_TO_ONE sends to MSG_ONE +//- channel 0 is controlled by snd_channel0volume; channel 1 and -1 by +// snd_channel1volume, etc. (so, a channel shares the cvar with its respective +// auto-channel); however, the mod MUST define snd_channel8volume and upwards +// in default.cfg if they are to be used, as the engine does not create them +// to not litter the cvar list +//- this extension applies to CSQC as well; CSQC_Event_Sound will get speed and +// flags as extra 7th and 8th argument +//- WIP2 ideas: SOUNDFLAG_RELIABLE_TO_ONE, SOUNDFLAG_NOPHS, SOUNDFLAG_FORCELOOP +//- NOTE: to check for this, ALSO OR a check with DP_SND_SOUND7 to also support +// the finished extension once done + +//DP_SND_OGGVORBIS +//idea: Transfusion +//darkplaces implementation: Elric +//description: +//the engine supports loading Ogg Vorbis sound files. Use either the .ogg filename directly, or a .wav of the same name (will try to load the .wav first and then .ogg). + +//DP_SND_STEREOWAV +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//description: +//the engine supports stereo WAV files. (useful with DP_SND_DIRECTIONLESSATTNNONE for music) + +//DP_SND_GETSOUNDTIME +//idea: VorteX +//darkplaces implementation: VorteX +//constant definitions: +float(entity e, float channel) getsoundtime = #533; // get currently sound playing position on entity channel, -1 if not playing or error +float(string sample) soundlength = #534; // returns length of sound sample in seconds, -1 on error (sound not precached, sound system not initialized etc.) +//description: provides opportunity to query length of sound samples and realtime tracking of sound playing on entities (similar to DP_GETTIME_CDTRACK) +//note: beware dedicated server not running sound engine at all, so in dedicated mode this builtins will not work in server progs +//note also: menu progs not supporting getsoundtime() (will give a warning) since it has no sound playing on entities +//examples of use: +// - QC-driven looped sounds +// - QC events when sound playing is finished +// - toggleable ambientsounds +// - subtitles + +//DP_VIDEO_DPV +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//console commands: +// playvideo <videoname> - start playing video +// stopvideo - stops current video +//description: indicated that engine support playing videos in DPV format + +//DP_VIDEO_SUBTITLES +//idea: VorteX +//darkplaces implementation: VorteX +//cvars: +// cl_video_subtitles - toggles subtitles showing +// cl_video_subtitles_lines - how many lines to reserve for subtitles +// cl_video_subtitles_textsize - font size +//console commands: +// playvideo <videoname> <custom_subtitles_file> - start playing video +// stopvideo - stops current video +//description: indicates that engine support subtitles on videos +//subtitles stored in external text files, each video file has it's default subtitles file ( <videoname>.dpsubs ) +//example: for video/act1.dpv default subtitles file will be video/act1.dpsubs +//also video could be played with custom subtitles file by utilizing second parm of playvideo command +//syntax of .dpsubs files: each line in .dpsubs file defines 1 subtitle, there are three tokens: +// <start> <end> "string" +// start: subtitle start time in seconds +// end: subtitle time-to-show in seconds, if 0 - subtitle will be showed until next subtitle is started, +// if below 0 - show until next subtitles minus this number of seconds +// text: subtitle text, color codes (Q3-style and ^xRGB) are allowed +//example of subtitle file: +// 3 0 "Vengeance! Vengeance for my eternity of suffering!" +// 9 0 "Whelp! As if you knew what eternity was!" +// 13 0 "Grovel before your true master." +// 17 0 "Never!" +// 18 7 "I'll hack you from crotch to gizzard and feed what's left of you to your brides..." + +//DP_SOLIDCORPSE +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//solid definitions: +float SOLID_CORPSE = 5; +//description: +//the entity will not collide with SOLID_CORPSE and SOLID_SLIDEBOX entities (and likewise they will not collide with it), this is useful if you want dead bodies that are shootable but do not obstruct movement by players and monsters, note that if you traceline with a SOLID_SLIDEBOX entity as the ignoreent, it will ignore SOLID_CORPSE entities, this is desirable for visibility and movement traces, but not for bullets, for the traceline to hit SOLID_CORPSE you must temporarily force the player (or whatever) to SOLID_BBOX and then restore to SOLID_SLIDEBOX after the traceline. + +//DP_SPRITE32 +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//description: +//the engine supports .spr32 sprites. + +//DP_SV_BOTCLIENT +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//constants: +float CLIENTTYPE_DISCONNECTED = 0; +float CLIENTTYPE_REAL = 1; +float CLIENTTYPE_BOT = 2; +float CLIENTTYPE_NOTACLIENT = 3; +//builtin definitions: +entity() spawnclient = #454; // like spawn but for client slots (also calls relevant connect/spawn functions), returns world if no clients available +float(entity clent) clienttype = #455; // returns one of the CLIENTTYPE_* constants +//description: +//spawns a client with no network connection, to allow bots to use client slots with no hacks. +//How to use: +/* + // to spawn a bot + local entity oldself; + oldself = self; + self = spawnclient(); + if (!self) + { + bprint("Can not add bot, server full.\n"); + self = oldself; + return; + } + self.netname = "Yoyobot"; + self.clientcolors = 12 * 16 + 4; // yellow (12) shirt and red (4) pants + ClientConnect(); + PutClientInServer(); + self = oldself; + + // to remove all bots + local entity head; + head = find(world, classname, "player"); + while (head) + { + if (clienttype(head) == CLIENTTYPE_BOT) + dropclient(head); + head = find(head, classname, "player"); + } + + // to identify if a client is a bot (for example in PlayerPreThink) + if (clienttype(self) == CLIENTTYPE_BOT) + botthink(); +*/ +//see also DP_SV_CLIENTCOLORS DP_SV_CLIENTNAME DP_SV_DROPCLIENT +//How it works: +//creates a new client, calls SetNewParms and stores the parms, and returns the client. +//this intentionally does not call SV_SendServerinfo to allow the QuakeC a chance to set the netname and clientcolors fields before actually spawning the bot by calling ClientConnect and PutClientInServer manually +//on level change ClientConnect and PutClientInServer are called by the engine to spawn in the bot (this is why clienttype() exists to tell you on the next level what type of client this is). +//parms work the same on bot clients as they do on real clients, and do carry from level to level + +//DP_SV_BOUNCEFACTOR +//idea: divVerent +//darkplaces implementation: divVerent +//field definitions: +.float bouncefactor; // velocity multiplier after a bounce +.float bouncestop; // bounce stops if velocity to bounce plane is < bouncestop * gravity AFTER the bounce +//description: +//allows qc to customize MOVETYPE_BOUNCE a bit + +//DP_SV_CLIENTCAMERA +//idea: LordHavoc, others +//darkplaces implementation: Black +//field definitions: +.entity clientcamera; // override camera entity +//description: +//allows another entity to be the camera for a client, for example a remote camera, this is similar to sending svc_setview manually except that it also changes the network culling appropriately. + +//DP_SV_CLIENTCOLORS +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//field definitions: +.float clientcolors; // colors of the client (format: pants + shirt * 16) +//description: +//allows qc to read and modify the client colors associated with a client entity (not particularly useful on other entities), and automatically sends out any appropriate network updates if changed + +//DP_SV_CLIENTNAME +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//description: +//allows qc to modify the client's .netname, and automatically sends out any appropriate network updates if changed + +//DP_SV_CUSTOMIZEENTITYFORCLIENT +//idea: LordHavoc +//darkplaces implementation: [515] and LordHavoc +//field definitions: +.float() customizeentityforclient; // self = this entity, other = client entity +//description: +//allows qc to modify an entity before it is sent to each client, the function returns TRUE if it should send, FALSE if it should not, and is fully capable of editing the entity's fields, this allows cloaked players to appear less transparent to their teammates, navigation markers to only show to their team, etc +//tips on writing customize functions: +//it is a good idea to return FALSE early in the function if possible to reduce cpu usage, because this function may be called many thousands of times per frame if there are many customized entities on a 64+ player server. +//you are free to change anything in self, but please do not change any other entities (the results may be very inconsistent). +//example ideas for use of this extension: +//making icons over teammates' heads which are only visible to teammates. for exasmple: float() playericon_customizeentityforclient = {return self.owner.team == other.team;}; +//making cloaked players more visible to their teammates than their enemies. for example: float() player_customizeentityforclient = {if (self.items & IT_CLOAKING) {if (self.team == other.team) self.alpha = 0.6;else self.alpha = 0.1;} return TRUE;}; +//making explosion models that face the viewer (does not work well with chase_active). for example: float() explosion_customizeentityforclient = {self.angles = vectoangles(other.origin + other.view_ofs - self.origin);self.angles_x = 0 - self.angles_x;}; +//implementation notes: +//entity customization is done before per-client culling (visibility for instance) because the entity may be doing setorigin to display itself in different locations on different clients, may be altering its .modelindex, .effects and other fields important to culling, so customized entities increase cpu usage (non-customized entities can use all the early culling they want however, as they are not changing on a per client basis). + +//DP_SV_DISCARDABLEDEMO +//idea: parasti +//darkplaces implementation: parasti +//field definitions: +.float discardabledemo; +//description: +//when this field is set to a non-zero value on a player entity, a possibly recorded server-side demo for the player is discarded +//Note that this extension only works if: +// auto demos are enabled (the cvar sv_autodemo_perclient is set) +// discarding demos is enabled (the cvar sv_autodemo_perclient_discardable is set) + +//DP_SV_DRAWONLYTOCLIENT +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//field definitions: +.entity drawonlytoclient; +//description: +//the entity is only visible to the specified client. + +//DP_SV_DROPCLIENT +//idea: FrikaC +//darkplaces implementation: LordHavoc +//builtin definitions: +void(entity clent) dropclient = #453; +//description: +//causes the server to immediately drop the client, more reliable than stuffcmd(clent, "disconnect\n"); which could be intentionally ignored by the client engine + +//DP_SV_EFFECT +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +void(vector org, string modelname, float startframe, float endframe, float framerate) effect = #404; +//SVC definitions: +//float svc_effect = #52; // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate +//float svc_effect2 = #53; // [vector] org [short] modelindex [byte] startframe [byte] framecount [byte] framerate +//description: +//clientside playback of simple custom sprite effects (explosion sprites, etc). + +//DP_SV_ENTITYCONTENTSTRANSITION +//idea: Dresk +//darkplaces implementation: Dresk +//field definitions: +.void(float nOriginalContents, float nNewContents) contentstransition; +//description: +//This field function, when provided, is triggered on an entity when the contents (ie. liquid / water / etc) is changed. +//The first parameter provides the entities original contents, prior to the transition. The second parameter provides the new contents. +//NOTE: If this field function is provided on an entity, the standard watersplash sound IS SUPPRESSED to allow for authors to create their own transition sounds. + +//DP_SV_MOVETYPESTEP_LANDEVENT +//idea: Dresk +//darkplaces implementation: Dresk +//field definitions: +.void(vector vImpactVelocity) movetypesteplandevent; +//description: +//This field function, when provided, is triggered on a MOVETYPE_STEP entity when it experiences "land event". +// The standard engine behavior for this event is to play the sv_sound_land CVar sound. +//The parameter provides the velocity of the entity at the time of the impact. The z value may therefore be used to calculate how "hard" the entity struck the surface. +//NOTE: If this field function is provided on a MOVETYPE_STEP entity, the standard sv_sound_land sound IS SUPPRESSED to allow for authors to create their own feedback. + +//DP_SV_POINTSOUND +//idea: Dresk +//darkplaces implementation: Dresk +//builtin definitions: +void(vector origin, string sample, float volume, float attenuation) pointsound = #483; +//description: +//Similar to the standard QC sound function, this function takes an origin instead of an entity and omits the channel parameter. +// This allows sounds to be played at arbitrary origins without spawning entities. + +//DP_SV_ONENTITYNOSPAWNFUNCTION +//idea: Dresk +//darkplaces implementation: Dresk +//engine-called QC prototypes: +//void() SV_OnEntityNoSpawnFunction; +//description: +// This function is called whenever an entity on the server has no spawn function, and therefore has no defined QC behavior. +// You may as such dictate the behavior as to what happens to the entity. +// To mimic the engine's default behavior, simply call remove(self). + +//DP_SV_ONENTITYPREPOSTSPAWNFUNCTION +//idea: divVerent +//darkplaces implementation: divVerent +//engine-called QC prototypes: +//void() SV_OnEntityPreSpawnFunction; +//void() SV_OnEntityPostSpawnFunction; +//description: +// These functions are called BEFORE or AFTER an entity is spawned the regular way. +// You may as such dictate the behavior as to what happens to the entity. +// SV_OnEntityPreSpawnFunction is called before even looking for the spawn function, so you can even change its classname in there. If it remove()s the entity, the spawn function will not be looked for. +// SV_OnEntityPostSpawnFunction is called ONLY after its spawn function or SV_OnEntityNoSpawnFunction was called, and skipped if the entity got removed by either. + +//DP_SV_MODELFLAGS_AS_EFFECTS +//idea: LordHavoc, Dresk +//darkplaces implementation: LordHavoc +//field definitions: +.float modelflags; +//constant definitions: +float EF_NOMODELFLAGS = 8388608; // ignore any effects in a model file and substitute your own +float MF_ROCKET = 1; // leave a trail +float MF_GRENADE = 2; // leave a trail +float MF_GIB = 4; // leave a trail +float MF_ROTATE = 8; // rotate (bonus items) +float MF_TRACER = 16; // green split trail +float MF_ZOMGIB = 32; // small blood trail +float MF_TRACER2 = 64; // orange split trail +float MF_TRACER3 = 128; // purple trail +//description: +//this extension allows model flags to be specified on entities so you can add a rocket trail and glow to any entity, etc. +//setting any of these will override the flags the model already has, to disable the model's flags without supplying any of your own you must use EF_NOMODELFLAGS. +// +//silly example modification #1 to W_FireRocket in weapons.qc: +//missile.effects = EF_NOMODELFLAGS; // rocket without a glow/fire trail +//silly example modification #2 to W_FireRocket in weapons.qc: +//missile.modelflags = MF_GIB; // leave a blood trail instead of glow/fire trail +// +//note: you can not combine multiple kinds of trail, only one of them will be active, you can combine MF_ROTATE and the other MF_ flags however, and using EF_NOMODELFLAGS along with these does no harm. +// +//note to engine coders: they are internally encoded in the protocol as extra EF_ flags (shift the values left 24 bits and send them in the protocol that way), so no protocol change was required (however 32bit effects is a protocol extension itself), within the engine they are referred to as EF_ for the 24bit shifted values. + +//DP_SV_NETADDRESS +//idea: Dresk +//darkplaces implementation: Dresk +//field definitions: +.string netaddress; +//description: +// provides the netaddress of the associated entity (ie. 127.0.0.1) and "null/botclient" if the netconnection of the entity is invalid + +//DP_SV_NODRAWTOCLIENT +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//field definitions: +.entity nodrawtoclient; +//description: +//the entity is not visible to the specified client. + +//DP_SV_PING +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//field definitions: +.float ping; +//description: +//continuously updated field indicating client's ping (based on average of last 16 packet time differences). + +//DP_SV_PING_PACKETLOSS +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//field definitions: +.float ping_packetloss; +.float ping_movementloss; +//description: +//continuously updated field indicating client's packet loss, and movement loss (i.e. packet loss affecting player movement). + +//DP_SV_POINTPARTICLES +//idea: Spike +//darkplaces implementation: LordHavoc +//function definitions: +float(string effectname) particleeffectnum = #335; // same as in CSQC +void(entity ent, float effectnum, vector start, vector end) trailparticles = #336; // same as in CSQC +void(float effectnum, vector org, vector vel, float howmany) pointparticles = #337; // same as in CSQC +//SVC definitions: +//float svc_trailparticles = 60; // [short] entnum [short] effectnum [vector] start [vector] end +//float svc_pointparticles = 61; // [short] effectnum [vector] start [vector] velocity [short] count +//float svc_pointparticles1 = 62; // [short] effectnum [vector] start, same as svc_pointparticles except velocity is zero and count is 1 +//description: +//provides the ability to spawn non-standard particle effects, typically these are defined in a particle effect information file such as effectinfo.txt in darkplaces. +//this is a port of particle effect features from clientside QC (EXT_CSQC) to server QC, as these effects are potentially useful to all games even if they do not make use of EXT_CSQC. +//warning: server must have same order of effects in effectinfo.txt as client does or the numbers would not match up, except for standard quake effects which are always the same numbers. + +//DP_SV_PUNCHVECTOR +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//field definitions: +.vector punchvector; +//description: +//offsets client view in worldspace, similar to view_ofs but all 3 components are used and are sent with at least 8 bits of fraction, this allows the view to be kicked around by damage or hard landings or whatever else, note that unlike punchangle this is not faded over time, it is up to the mod to fade it (see also DP_SV_PLAYERPHYSICS). + +//DP_SV_PLAYERPHYSICS +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//field definitions: +.vector movement; +//cvar definitions: +//"sv_playerphysicsqc" (0/1, default 1, allows user to disable qc player physics) +//engine-called QC prototypes: +//void() SV_PlayerPhysics; +//description: +//.movement vector contains the movement input from the player, allowing QC to do as it wishs with the input, and SV_PlayerPhysics will completely replace the player physics if present (works for all MOVETYPE's), see darkplaces mod source for example of this function (in playermovement.qc, adds HalfLife ladders support, as well as acceleration/deceleration while airborn (rather than the quake sudden-stop while airborn), and simplifies the physics a bit) + +//DP_PHYSICS_ODE +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//globals: +//new movetypes: +const float MOVETYPE_PHYSICS = 32; // need to be set before any physics_* builtins applied +//new solid types (deprecated): +const float SOLID_PHYSICS_BOX = 32; +const float SOLID_PHYSICS_SPHERE = 33; +const float SOLID_PHYSICS_CAPSULE = 34; +const float SOLID_PHYSICS_TRIMESH = 35; +const float SOLID_PHYSICS_CYLINDER = 36; +//geometry types: +const float GEOMTYPE_NONE = -1; // entity will be entirely skipped by ODE +const float GEOMTYPE_SOLID = 0; // geometry type will be set based on .solid field +const float GEOMTYPE_BOX = 1; // entity bound box +const float GEOMTYPE_SPHERE = 2; // sphere with radius picked from x axis of entity bound box +const float GEOMTYPE_CAPSULE = 3; // with leading axis automatically determined from longest one, radius is picked as minimal of the rest 2 axes +const float GEOMTYPE_TRIMESH = 4; // triangle mesh +const float GEOMTYPE_CYLINDER = 5; // like capsule but not capped + // note that ODE's builtin cylinder support is experimental, somewhat bugged and unfinished (no cylinder-cylinder collision) + // to use properly working cylinder should build ODE with LIBCCD extension +const float GEOMTYPE_CAPSULE_X = 6; // capsule with fixed leading axis +const float GEOMTYPE_CAPSULE_Y = 7; +const float GEOMTYPE_CAPSULE_Z = 8; +const float GEOMTYPE_CYLINDER_X = 9; // cylinder with fixed leading axis +const float GEOMTYPE_CYLINDER_Y = 10; +const float GEOMTYPE_CYLINDER_Z = 11; +//joint types: +const float JOINTTYPE_NONE = 0; +const float JOINTTYPE_POINT = 1; +const float JOINTTYPE_HINGE = 2; +const float JOINTTYPE_SLIDER = 3; +const float JOINTTYPE_UNIVERSAL = 4; +const float JOINTTYPE_HINGE2 = 5; +const float JOINTTYPE_FIXED = -1; +//force types: +const float FORCETYPE_NONE = 0; +const float FORCETYPE_FORCE = 1; // applied at center of mass +const float FORCETYPE_FORCEATPOS = 2; +const float FORCETYPE_TORQUE = 3; +// common joint properties: +// .entity aiment; // connected objects +// .entity enemy; // connected objects, forces +// .vector movedir; +// for a spring: +// movedir_x = spring constant (force multiplier, must be > 0) +// movedir_y = spring dampening constant to prevent oscillation (must be > 0) +// movedir_z = spring stop position (+/-) +// for a motor: +// movedir_x = desired motor velocity +// movedir_y = -1 * max motor force to use +// movedir_z = stop position (+/-), set to 0 for no stop +// note that ODE does not support both in one anyway +// for a force: +// force vector to apply +//field definitions: +.float geomtype; // see GEOMTYPE_*, a more correct way to set collision shape, allows to set SOLID_CORPSE and trimesh collisions +.float maxcontacts; // maximum number of contacts to make for this object, lesser = faster (but setting it too low will could make object pass though walls), default is 16, maximum is 32 +.float mass; // ODE mass, standart value is 1 +.vector massofs; // offsets a mass center out of object center, if not set a center of model bounds is used +.float friction; // a friction of object, get multiplied by second objects's friction on contact +.float bouncefactor; +.float bouncestop; +.float jointtype; // type of joint +.float forcetype; // type of force +.float erp; // error restitution parameter, makes ODE solver attempt to fix errors in contacts, + // bringing together 2 joints or fixing object being stuch in other object, + // a value of 0.1 will fix slightly, a value of 1.0 attempts to fix whole error in one frame + // use with care as high values makes system unstable and likely to explode +//builtin definitions: +void(entity e, float physics_enabled) physics_enable = #540; // enable or disable physics on object +void(entity e, vector force, vector force_pos) physics_addforce = #541; // deprecated, apply a force from certain origin, length of force vector is power of force +void(entity e, vector torque) physics_addtorque = #542; // deprecated, add relative torque +//description: provides Open Dynamics Engine support, requires extenal dll to be present or engine compiled with statical link option +//be sure to checkextension for it to know if library is loaded and ready, also to enable physics set "physics_ode" cvar to 1 +//note: this extension is highly experimental and may be unstable + +//DP_SV_PRINT +//idea: id Software (QuakeWorld Server) +//darkplaces implementation: Black, LordHavoc +void(string s, ...) print = #339; // same number as in EXT_CSQC +//description: +//this is identical to dprint except that it always prints regardless of the developer cvar. + +//DP_SV_PRECACHEANYTIME +//idea: id Software (Quake2) +//darkplaces implementation: LordHavoc +//description: +//this extension allows precache_model and precache_sound (and any variants) to be used during the game (with automatic messages to clients to precache the new model/sound indices), also setmodel/sound/ambientsound can be called without precaching first (they will cause an automatic precache). + +//DP_SV_QCSTATUS +//idea: divVerent +//darkplaces implementation: divVerent +//1. A global variable +string worldstatus; +//Its content is set as "qcstatus" field in the rules. +//It may be at most 255 characters, and must not contain newlines or backslashes. +//2. A per-client field +.string clientstatus; +//It is sent instead of the "frags" in status responses. +//It should always be set in a way so that stof(player.clientstatus) is a meaningful score value. Other info may be appended. If used this way, the cvar sv_status_use_qcstatus may be set to 1, and then this value will replace the frags in "status". +//Currently, qstat does not support this and will not show player info if used and set to anything other than ftos(some integer). + +//DP_SV_ROTATINGBMODEL +//idea: id Software +//darkplaces implementation: LordHavoc +//description: +//this extension merely indicates that MOVETYPE_PUSH supports avelocity, allowing rotating brush models to be created, they rotate around their origin (needs rotation supporting qbsp/light utilities because id ones expected bmodel entity origins to be '0 0 0', recommend setting "origin" key in the entity fields in the map before compiling, there may be other methods depending on your qbsp, most are more complicated however). +//tip: level designers can create a func_wall with an origin, and avelocity (for example "avelocity" "0 90 0"), and "nextthink" "99999999" to make a rotating bmodel without any qc modifications, such entities will be solid in stock quake but will not rotate) + +//DP_SV_SETCOLOR +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +void(entity ent, float colors) setcolor = #401; +//engine called QC functions (optional): +//void(float color) SV_ChangeTeam; +//description: +//setcolor sets the color on a client and updates internal color information accordingly (equivalent to stuffing a "color" command but immediate) +//SV_ChangeTeam is called by the engine whenever a "color" command is recieved, it may decide to do anything it pleases with the color passed by the client, including rejecting it (by doing nothing), or calling setcolor to apply it, preventing team changes is one use for this. +//the color format is pants + shirt * 16 (0-255 potentially) + +//DP_SV_SLOWMO +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//cvars: +//"slowmo" (0+, default 1) +//description: +//sets the time scale of the server, mainly intended for use in singleplayer by the player, however potentially useful for mods, so here's an extension for it. +//range is 0 to infinite, recommended values to try are 0.1 (very slow, 10% speed), 1 (normal speed), 5 (500% speed). + +//DP_SV_WRITEPICTURE +//idea: divVerent +//darkplaces implementation: divVerent +//builtin definitions: +void(float to, string s, float sz) WritePicture = #501; +//description: +//writes a picture to the data stream so CSQC can read it using ReadPicture, which has the definition +// string(void) ReadPicture = #501; +//The picture data is sent as at most sz bytes, by compressing to low quality +//JPEG. The data being sent will be equivalent to: +// WriteString(to, s); +// WriteShort(to, imagesize); +// for(i = 0; i < imagesize; ++i) +// WriteByte(to, [the i-th byte of the compressed JPEG image]); + +//DP_SV_WRITEUNTERMINATEDSTRING +//idea: FrikaC +//darkplaces implementation: Sajt +//builtin definitions: +void(float to, string s) WriteUnterminatedString = #456; +//description: +//like WriteString, but does not write a terminating 0 after the string. This means you can include things like a player's netname in the middle of a string sent over the network. Just be sure to end it up with either a call to WriteString (which includes the trailing 0) or WriteByte(0) to terminate it yourself. +//A historical note: this extension was suggested by FrikaC years ago, more recently Shadowalker has been badmouthing LordHavoc and Spike for stealing 'his' extension writestring2 which does exactly the same thing but uses a different builtin number and name and extension string, this argument hinges on the idea that it was his idea in the first place, which is incorrect as FrikaC first suggested it and used a rough equivalent of it in his FrikBot mod years ago involving WriteByte calls on each character. + +//DP_TE_BLOOD +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +void(vector org, vector velocity, float howmany) te_blood = #405; +//temp entity definitions: +float TE_BLOOD = 50; +//protocol: +//vector origin +//byte xvelocity (-128 to +127) +//byte yvelocity (-128 to +127) +//byte zvelocity (-128 to +127) +//byte count (0 to 255, how much blood) +//description: +//creates a blood effect. + +//DP_TE_BLOODSHOWER +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower = #406; +//temp entity definitions: +//float TE_BLOODSHOWER = 52; +//protocol: +//vector mins (minimum corner of the cube) +//vector maxs (maximum corner of the cube) +//coord explosionspeed (velocity of blood particles flying out of the center) +//short count (number of blood particles) +//description: +//creates an exploding shower of blood, for making gibbings more convincing. + +//DP_TE_CUSTOMFLASH +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +void(vector org, float radius, float lifetime, vector color) te_customflash = #417; +//temp entity definitions: +//float TE_CUSTOMFLASH = 73; +//protocol: +//vector origin +//byte radius ((MSG_ReadByte() + 1) * 8, meaning 8-2048 unit radius) +//byte lifetime ((MSG_ReadByte() + 1) / 256.0, meaning approximately 0-1 second lifetime) +//byte red (0.0 to 1.0 converted to 0-255) +//byte green (0.0 to 1.0 converted to 0-255) +//byte blue (0.0 to 1.0 converted to 0-255) +//description: +//creates a customized light flash. + +//DP_TE_EXPLOSIONRGB +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +void(vector org, vector color) te_explosionrgb = #407; +//temp entity definitions: +//float TE_EXPLOSIONRGB = 53; +//protocol: +//vector origin +//byte red (0.0 to 1.0 converted to 0 to 255) +//byte green (0.0 to 1.0 converted to 0 to 255) +//byte blue (0.0 to 1.0 converted to 0 to 255) +//description: +//creates a colored explosion effect. + +//DP_TE_FLAMEJET +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +void(vector org, vector vel, float howmany) te_flamejet = #457; +//temp entity definitions: +//float TE_FLAMEJET = 74; +//protocol: +//vector origin +//vector velocity +//byte count (0 to 255, how many flame particles) +//description: +//creates a single puff of flame particles. (not very useful really) + +//DP_TE_PARTICLECUBE +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube = #408; +//temp entity definitions: +//float TE_PARTICLECUBE = 54; +//protocol: +//vector mins (minimum corner of the cube) +//vector maxs (maximum corner of the cube) +//vector velocity +//short count +//byte color (palette color) +//byte gravity (TRUE or FALSE, FIXME should this be a scaler instead?) +//coord randomvel (how much to jitter the velocity) +//description: +//creates a cloud of particles, useful for forcefields but quite customizable. + +//DP_TE_PARTICLERAIN +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain = #409; +//temp entity definitions: +//float TE_PARTICLERAIN = 55; +//protocol: +//vector mins (minimum corner of the cube) +//vector maxs (maximum corner of the cube) +//vector velocity (velocity of particles) +//short count (number of particles) +//byte color (8bit palette color) +//description: +//creates a shower of rain, the rain will appear either at the top (if falling down) or bottom (if falling up) of the cube. + +//DP_TE_PARTICLESNOW +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow = #410; +//temp entity definitions: +//float TE_PARTICLERAIN = 56; +//protocol: +//vector mins (minimum corner of the cube) +//vector maxs (maximum corner of the cube) +//vector velocity (velocity of particles) +//short count (number of particles) +//byte color (8bit palette color) +//description: +//creates a shower of snow, the snow will appear either at the top (if falling down) or bottom (if falling up) of the cube, low velocities are advisable for convincing snow. + +//DP_TE_PLASMABURN +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +void(vector org) te_plasmaburn = #433; +//temp entity definitions: +//float TE_PLASMABURN = 75; +//protocol: +//vector origin +//description: +//creates a small light flash (radius 200, time 0.2) and marks the walls. + +//DP_TE_QUADEFFECTS1 +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +void(vector org) te_gunshotquad = #412; +void(vector org) te_spikequad = #413; +void(vector org) te_superspikequad = #414; +void(vector org) te_explosionquad = #415; +//temp entity definitions: +//float TE_GUNSHOTQUAD = 57; // [vector] origin +//float TE_SPIKEQUAD = 58; // [vector] origin +//float TE_SUPERSPIKEQUAD = 59; // [vector] origin +//float TE_EXPLOSIONQUAD = 70; // [vector] origin +//protocol: +//vector origin +//description: +//all of these just take a location, and are equivalent in function (but not appearance :) to the original TE_GUNSHOT, etc. + +//DP_TE_SMALLFLASH +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +void(vector org) te_smallflash = #416; +//temp entity definitions: +//float TE_SMALLFLASH = 72; +//protocol: +//vector origin +//description: +//creates a small light flash (radius 200, time 0.2). + +//DP_TE_SPARK +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +void(vector org, vector vel, float howmany) te_spark = #411; +//temp entity definitions: +//float TE_SPARK = 51; +//protocol: +//vector origin +//byte xvelocity (-128 to 127) +//byte yvelocity (-128 to 127) +//byte zvelocity (-128 to 127) +//byte count (number of sparks) +//description: +//creates a shower of sparks and a smoke puff. + +//DP_TE_STANDARDEFFECTBUILTINS +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +void(vector org) te_gunshot = #418; +void(vector org) te_spike = #419; +void(vector org) te_superspike = #420; +void(vector org) te_explosion = #421; +void(vector org) te_tarexplosion = #422; +void(vector org) te_wizspike = #423; +void(vector org) te_knightspike = #424; +void(vector org) te_lavasplash = #425; +void(vector org) te_teleport = #426; +void(vector org, float color, float colorlength) te_explosion2 = #427; +void(entity own, vector start, vector end) te_lightning1 = #428; +void(entity own, vector start, vector end) te_lightning2 = #429; +void(entity own, vector start, vector end) te_lightning3 = #430; +void(entity own, vector start, vector end) te_beam = #431; +//description: +//to make life easier on mod coders. + +//DP_TRACE_HITCONTENTSMASK_SURFACEINFO +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//globals: +.float dphitcontentsmask; // if non-zero on the entity passed to traceline/tracebox/tracetoss this will override the normal collidable contents rules and instead hit these contents values (for example AI can use tracelines that hit DONOTENTER if it wants to, by simply changing this field on the entity passed to traceline), this affects normal movement as well as trace calls +float trace_dpstartcontents; // DPCONTENTS_ value at start position of trace +float trace_dphitcontents; // DPCONTENTS_ value of impacted surface (not contents at impact point, just contents of the surface that was hit) +float trace_dphitq3surfaceflags; // Q3SURFACEFLAG_ value of impacted surface +string trace_dphittexturename; // texture name of impacted surface +//constants: +float DPCONTENTS_SOLID = 1; // hit a bmodel, not a bounding box +float DPCONTENTS_WATER = 2; +float DPCONTENTS_SLIME = 4; +float DPCONTENTS_LAVA = 8; +float DPCONTENTS_SKY = 16; +float DPCONTENTS_BODY = 32; // hit a bounding box, not a bmodel +float DPCONTENTS_CORPSE = 64; // hit a SOLID_CORPSE entity +float DPCONTENTS_NODROP = 128; // an area where backpacks should not spawn +float DPCONTENTS_PLAYERCLIP = 256; // blocks player movement +float DPCONTENTS_MONSTERCLIP = 512; // blocks monster movement +float DPCONTENTS_DONOTENTER = 1024; // AI hint brush +float DPCONTENTS_LIQUIDSMASK = 14; // WATER | SLIME | LAVA +float DPCONTENTS_BOTCLIP = 2048; // AI hint brush +float DPCONTENTS_OPAQUE = 4096; // only fully opaque brushes get this (may be useful for line of sight checks) +float Q3SURFACEFLAG_NODAMAGE = 1; +float Q3SURFACEFLAG_SLICK = 2; // low friction surface +float Q3SURFACEFLAG_SKY = 4; // sky surface (also has NOIMPACT and NOMARKS set) +float Q3SURFACEFLAG_LADDER = 8; // climbable surface +float Q3SURFACEFLAG_NOIMPACT = 16; // projectiles should remove themselves on impact (this is set on sky) +float Q3SURFACEFLAG_NOMARKS = 32; // projectiles should not leave marks, such as decals (this is set on sky) +float Q3SURFACEFLAG_FLESH = 64; // projectiles should do a fleshy effect (blood?) on impact +float Q3SURFACEFLAG_NODRAW = 128; // compiler hint (not important to qc) +//float Q3SURFACEFLAG_HINT = 256; // compiler hint (not important to qc) +//float Q3SURFACEFLAG_SKIP = 512; // compiler hint (not important to qc) +//float Q3SURFACEFLAG_NOLIGHTMAP = 1024; // compiler hint (not important to qc) +//float Q3SURFACEFLAG_POINTLIGHT = 2048; // compiler hint (not important to qc) +float Q3SURFACEFLAG_METALSTEPS = 4096; // walking on this surface should make metal step sounds +float Q3SURFACEFLAG_NOSTEPS = 8192; // walking on this surface should not make footstep sounds +float Q3SURFACEFLAG_NONSOLID = 16384; // compiler hint (not important to qc) +//float Q3SURFACEFLAG_LIGHTFILTER = 32768; // compiler hint (not important to qc) +//float Q3SURFACEFLAG_ALPHASHADOW = 65536; // compiler hint (not important to qc) +//float Q3SURFACEFLAG_NODLIGHT = 131072; // compiler hint (not important to qc) +//float Q3SURFACEFLAG_DUST = 262144; // translucent 'light beam' effect (not important to qc) +//description: +//adds additional information after a traceline/tracebox/tracetoss call. +//also (very important) sets trace_* globals before calling .touch functions, +//this allows them to inspect the nature of the collision (for example +//determining if a projectile hit sky), clears trace_* variables for the other +//object in a touch event (that is to say, a projectile moving will see the +//trace results in its .touch function, but the player it hit will see very +//little information in the trace_ variables as it was not moving at the time) + +//DP_VIEWZOOM +//idea: LordHavoc +//darkplaces implementation: LordHavoc +//field definitions: +.float viewzoom; +//description: +//scales fov and sensitivity of player, valid range is 0 to 1 (intended for sniper rifle zooming, and such) + +//EXT_BITSHIFT +//idea: Spike +//darkplaces implementation: [515] +//builtin definitions: +float(float number, float quantity) bitshift = #218; +//description: +//multiplies number by a power of 2 corresponding to quantity (0 = *1, 1 = *2, 2 = *4, 3 = *8, -1 = /2, -2 = /4x, etc), and rounds down (due to integer math) like other bit operations do (& and | and the like). +//note: it is faster to use multiply if you are shifting by a constant, avoiding the quakec function call cost, however that does not do a floor for you. + +//FRIK_FILE +//idea: FrikaC +//darkplaces implementation: LordHavoc +//builtin definitions: +float(string s) stof = #81; // get numerical value from a string +float(string filename, float mode) fopen = #110; // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE), returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason +void(float fhandle) fclose = #111; // closes a file +string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring +void(float fhandle, string s, ...) fputs = #113; // writes a line of text to the end of the file +float(string s) strlen = #114; // returns how many characters are in a string +string(string s1, string s2, ...) strcat = #115; // concatenates two or more strings (for example "abc", "def" would return "abcdef") and returns as a tempstring +string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring - see FTE_STRINGS for enhanced version +vector(string s) stov = #117; // returns vector value from a string +string(string s, ...) strzone = #118; // makes a copy of a string into the string zone and returns it, this is often used to keep around a tempstring for longer periods of time (tempstrings are replaced often) +void(string s) strunzone = #119; // removes a copy of a string from the string zone (you can not use that string again or it may crash!!!) +//constants: +float FILE_READ = 0; +float FILE_APPEND = 1; +float FILE_WRITE = 2; +//cvars: +//pr_zone_min_strings : default 64 (64k), min 64 (64k), max 8192 (8mb) +//description: +//provides text file access functions and string manipulation functions, note that you may want to set pr_zone_min_strings in the worldspawn function if 64k is not enough string zone space. +// +//NOTE: strzone functionality is partially superseded by +//DP_QC_UNLIMITEDTEMPSTRINGS when longterm storage is not needed +//NOTE: substring is upgraded by FTE_STRINGS extension with negative start/length handling identical to php 5.2.0 + +//FTE_CSQC_SKELETONOBJECTS +//idea: Spike, LordHavoc +//darkplaces implementation: LordHavoc +//builtin definitions: +// all skeleton numbers are 1-based (0 being no skeleton) +// all bone numbers are 1-based (0 being invalid) +float(float modlindex) skel_create = #263; // create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex, as the skeleton uses the hierarchy from the model. +float(float skel, entity ent, float modlindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // blend in a percentage of standard animation, 0 replaces entirely, 1 does nothing, 0.5 blends half, etc, and this only alters the bones in the specified range for which out of bounds values like 0,100000 are safe (uses .frame, .frame2, .frame3, .frame4, .lerpfrac, .lerpfrac3, .lerpfrac4, .frame1time, .frame2time, .frame3time, .frame4time), returns skel on success, 0 on failure +float(float skel) skel_get_numbones = #265; // returns how many bones exist in the created skeleton, 0 if skeleton does not exist +string(float skel, float bonenum) skel_get_bonename = #266; // returns name of bone (as a tempstring), "" if invalid bonenum (< 1 for example) or skeleton does not exist +float(float skel, float bonenum) skel_get_boneparent = #267; // returns parent num for supplied bonenum, 0 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this) +float(float skel, string tagname) skel_find_bone = #268; // get number of bone with specified name, 0 on failure, bonenum (1-based) on success, same as using gettagindex but takes modelindex instead of entity +vector(float skel, float bonenum) skel_get_bonerel = #269; // get matrix of bone in skeleton relative to its parent - sets v_forward, v_right, v_up, returns origin (relative to parent bone) +vector(float skel, float bonenum) skel_get_boneabs = #270; // get matrix of bone in skeleton in model space - sets v_forward, v_right, v_up, returns origin (relative to entity) +void(float skel, float bonenum, vector org) skel_set_bone = #271; // set matrix of bone relative to its parent, reads v_forward, v_right, v_up, takes origin as parameter (relative to parent bone) +void(float skel, float bonenum, vector org) skel_mul_bone = #272; // transform bone matrix (relative to its parent) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bone) +void(float skel, float startbone, float endbone, vector org) skel_mul_bones = #273; // transform bone matrices (relative to their parents) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bones) +void(float skeldst, float skelsrc, float startbone, float endbone) skel_copybones = #274; // copy bone matrices (relative to their parents) from one skeleton to another, useful for copying a skeleton to a corpse +void(float skel) skel_delete = #275; // deletes skeleton at the beginning of the next frame (you can add the entity, delete the skeleton, renderscene, and it will still work) +float(float modlindex, string framename) frameforname = #276; // finds number of a specified frame in the animation, returns -1 if no match found +float(float modlindex, float framenum) frameduration = #277; // returns the intended play time (in seconds) of the specified framegroup, if it does not exist the result is 0, if it is a single frame it may be a small value around 0.1 or 0. +//fields: +.float skeletonindex; // active skeleton overriding standard animation on model +.float frame; // primary framegroup animation (strength = 1 - lerpfrac - lerpfrac3 - lerpfrac4) +.float frame2; // secondary framegroup animation (strength = lerpfrac) +.float frame3; // tertiary framegroup animation (strength = lerpfrac3) +.float frame4; // quaternary framegroup animation (strength = lerpfrac4) +.float lerpfrac; // strength of framegroup blend +.float lerpfrac3; // strength of framegroup blend +.float lerpfrac4; // strength of framegroup blend +.float frame1time; // start time of framegroup animation +.float frame2time; // start time of framegroup animation +.float frame3time; // start time of framegroup animation +.float frame4time; // start time of framegroup animation +//description: +//this extension provides a way to do complex skeletal animation on an entity. +// +//see also DP_SKELETONOBJECTS (this extension implemented on server as well as client) +// +//notes: +//each model contains its own skeleton, reusing a skeleton with incompatible models will yield garbage (or not render). +//each model contains its own animation data, you can use animations from other model files (for example saving out all character animations as separate model files). +//if an engine supports loading an animation-only file format such as .md5anim in FTEQW, it can be used to animate any model with a compatible skeleton. +//proper use of this extension may require understanding matrix transforms (v_forward, v_right, v_up, origin), and you must keep in mind that v_right is negative for this purpose. +// +//features include: +//multiple animations blended together. +//animating a model with animations from another model with a compatible skeleton. +//restricting animation blends to certain bones of a model - for example independent animation of legs, torso, head. +//custom bone controllers - for example making eyes track a target location. +// +// +// +//example code follows... +// +//this helper function lets you identify (by parentage) what group a bone +//belongs to - for example "torso", "leftarm", would return 1 ("torso") for +//all children of the bone named "torso", unless they are children of +//"leftarm" (which is a child of "torso") which would return 2 instead... +float(float skel, float bonenum, string g1, string g2, string g3, string g4, string g5, string g6) example_skel_findbonegroup = +{ + local string bonename; + while (bonenum >= 0) + { + bonename = skel_get_bonename(skel, bonenum); + if (bonename == g1) return 1; + if (bonename == g2) return 2; + if (bonename == g3) return 3; + if (bonename == g4) return 4; + if (bonename == g5) return 5; + if (bonename == g6) return 6; + bonenum = skel_get_boneparent(skel, bonenum); + } + return 0; +}; +// create a skeletonindex for our player using current modelindex +void() example_skel_player_setup = +{ + self.skeletonindex = skel_create(self.modelindex); +}; +// setup bones of skeleton based on an animation +// note: animmodelindex can be a different model than self.modelindex +void(float animmodelindex, float framegroup, float framegroupstarttime) example_skel_player_update_begin = +{ + // start with our standard animation + self.frame = framegroup; + self.frame2 = 0; + self.frame3 = 0; + self.frame4 = 0; + self.frame1time = framegroupstarttime; + self.frame2time = 0; + self.frame3time = 0; + self.frame4time = 0; + self.lerpfrac = 0; + self.lerpfrac3 = 0; + self.lerpfrac4 = 0; + skel_build(self.skeletonindex, self, animmodelindex, 0, 0, 100000); +}; +// apply a different framegroup animation to bones with a specified parent +void(float animmodelindex, float framegroup, float framegroupstarttime, float blendalpha, string groupbonename, string excludegroupname1, string excludegroupname2) example_skel_player_update_applyoverride = +{ + local float bonenum; + local float numbones; + self.frame = framegroup; + self.frame2 = 0; + self.frame3 = 0; + self.frame4 = 0; + self.frame1time = framegroupstarttime; + self.frame2time = 0; + self.frame3time = 0; + self.frame4time = 0; + self.lerpfrac = 0; + self.lerpfrac3 = 0; + self.lerpfrac4 = 0; + bonenum = 0; + numbones = skel_get_numbones(self.skeletonindex); + while (bonenum < numbones) + { + if (example_skel_findbonegroup(self.skeletonindex, bonenum, groupbonename, excludegroupname1, excludegroupname2, "", "", "") == 1) + skel_build(self.skeletonindex, self, animmodelindex, 1 - blendalpha, bonenum, bonenum + 1); + bonenum = bonenum + 1; + } +}; +// make eyes point at a target location, be sure v_forward, v_right, v_up are set correctly before calling +void(vector eyetarget, string bonename) example_skel_player_update_eyetarget = +{ + local float bonenum; + local vector ang; + local vector oldforward, oldright, oldup; + local vector relforward, relright, relup, relorg; + local vector boneforward, boneright, boneup, boneorg; + local vector parentforward, parentright, parentup, parentorg; + local vector u, v; + local vector modeleyetarget; + bonenum = skel_find_bone(self.skeletonindex, bonename) - 1; + if (bonenum < 0) + return; + oldforward = v_forward; + oldright = v_right; + oldup = v_up; + v = eyetarget - self.origin; + modeleyetarget_x = v * v_forward; + modeleyetarget_y = 0-v * v_right; + modeleyetarget_z = v * v_up; + // this is an eyeball, make it point at the target location + // first get all the data we can... + relorg = skel_get_bonerel(self.skeletonindex, bonenum); + relforward = v_forward; + relright = v_right; + relup = v_up; + boneorg = skel_get_boneabs(self.skeletonindex, bonenum); + boneforward = v_forward; + boneright = v_right; + boneup = v_up; + parentorg = skel_get_boneabs(self.skeletonindex, skel_get_boneparent(self.skeletonindex, bonenum)); + parentforward = v_forward; + parentright = v_right; + parentup = v_up; + // get the vector from the eyeball to the target + u = modeleyetarget - boneorg; + // now transform it inversely by the parent matrix to produce new rel vectors + v_x = u * parentforward; + v_y = u * parentright; + v_z = u * parentup; + ang = vectoangles2(v, relup); + ang_x = 0 - ang_x; + makevectors(ang); + // set the relative bone matrix + skel_set_bone(self.skeletonindex, bonenum, relorg); + // restore caller's v_ vectors + v_forward = oldforward; + v_right = oldright; + v_up = oldup; +}; +// delete skeleton when we're done with it +// note: skeleton remains valid until next frame when it is really deleted +void() example_skel_player_delete = +{ + skel_delete(self.skeletonindex); + self.skeletonindex = 0; +}; +// +// END OF EXAMPLES FOR FTE_CSQC_SKELETONOBJECTS +// + +//KRIMZON_SV_PARSECLIENTCOMMAND +//idea: KrimZon +//darkplaces implementation: KrimZon, LordHavoc +//engine-called QC prototypes: +//void(string s) SV_ParseClientCommand; +//builtin definitions: +void(entity e, string s) clientcommand = #440; +float(string s) tokenize = #441; +string(float n) argv = #442; +//description: +//provides QC the ability to completely control server interpretation of client commands ("say" and "color" for example, clientcommand is necessary for this and substring (FRIK_FILE) is useful) as well as adding new commands (tokenize, argv, and stof (FRIK_FILE) are useful for this)), whenever a clc_stringcmd is received the QC function is called, and it is up to the QC to decide what (if anything) to do with it + +//NEH_CMD_PLAY2 +//idea: Nehahra +//darkplaces implementation: LordHavoc +//description: +//shows that the engine supports the "play2" console command (plays a sound without spatialization). + +//NEH_RESTOREGAME +//idea: Nehahra +//darkplaces implementation: LordHavoc +//engine-called QC prototypes: +//void() RestoreGame; +//description: +//when a savegame is loaded, this function is called + +//NEXUIZ_PLAYERMODEL +//idea: Nexuiz +//darkplaces implementation: Black +//console commands: +//playermodel <name> - FIXME: EXAMPLE NEEDED +//playerskin <name> - FIXME: EXAMPLE NEEDED +//field definitions: +.string playermodel; // name of player model sent by client +.string playerskin; // name of player skin sent by client +//description: +//these client properties are used by Nexuiz. + +//NXQ_GFX_LETTERBOX +//idea: nxQuake +//darkplaces implementation: LordHavoc +//description: +//shows that the engine supports the "r_letterbox" console variable, set to values in the range 0-100 this restricts the view vertically (and turns off sbar and crosshair), value is a 0-100 percentage of how much to constrict the view, <=0 = normal view height, 25 = 75% of normal view height, 50 = 50%, 75 = 25%, >=100 = no view + +//PRYDON_CLIENTCURSOR +//idea: FrikaC +//darkplaces implementation: LordHavoc +//effects bit: +float EF_SELECTABLE = 16384; // allows cursor to highlight entity (brighten) +//field definitions: +.float cursor_active; // true if cl_prydoncursor mode is on +.vector cursor_screen; // screen position of cursor as -1 to +1 in _x and _y (_z unused) +.vector cursor_trace_start; // position of camera +.vector cursor_trace_endpos; // position of cursor in world (as traced from camera) +.entity cursor_trace_ent; // entity the cursor is pointing at (server forces this to world if the entity is currently free at time of receipt) +//cvar definitions: +//cl_prydoncursor (0/1+, default 0, 1 and above use cursors named gfx/prydoncursor%03i.lmp - or .tga and such if DP_GFX_EXTERNALTEXTURES is implemented) +//description: +//shows that the engine supports the cl_prydoncursor cvar, this puts a clientside mouse pointer on the screen and feeds input to the server for the QuakeC to use as it sees fit. +//the mouse pointer triggers button4 if cursor is at left edge of screen, button5 if at right edge of screen, button6 if at top edge of screen, button7 if at bottom edge of screen. +//the clientside trace skips transparent entities (except those marked EF_SELECTABLE). +//the selected entity highlights only if EF_SELECTABLE is set, a typical selection method would be doubling the brightness of the entity by some means (such as colormod[] *= 2). +//intended to be used by Prydon Gate. + +//TENEBRAE_GFX_DLIGHTS +//idea: Tenebrae +//darkplaces implementation: LordHavoc +//fields: +.float light_lev; // radius (does not affect brightness), typical value 350 +.vector color; // color (does not affect radius), typical value '1 1 1' (bright white), can be up to '255 255 255' (nuclear blast) +.float style; // light style (like normal light entities, flickering torches or switchable, etc) +.float pflags; // flags (see PFLAGS_ constants) +.vector angles; // orientation of the light +.float skin; // cubemap filter number, can be 1-255 (0 is assumed to be none, and tenebrae only allows 16-255), this selects a projective light filter, a value of 1 loads cubemaps/1posx.tga and cubemaps/1negx.tga and posy, negy, posz, and negz, similar to skybox but some sides need to be rotated or flipped +//constants: +float PFLAGS_NOSHADOW = 1; // light does not cast shadows +float PFLAGS_CORONA = 2; // light has a corona flare +float PFLAGS_FULLDYNAMIC = 128; // light enable (without this set no light is produced!) +//description: +//more powerful dynamic light settings +//warning: it is best not to use cubemaps on a light entity that has a model, as using a skin number that a model does not have will cause issues in glquake, and produce warnings in darkplaces (use developer 1 to see them) +//changes compared to tenebrae (because they're too 'leet' for standards): +//note: networking should send entities with PFLAGS_FULLDYNAMIC set even if they have no model (lights in general do not have a model, nor should they) +//EF_FULLDYNAMIC effects flag replaced by PFLAGS_FULLDYNAMIC flag (EF_FULLDYNAMIC conflicts with EF_NODRAW) + +//TW_SV_STEPCONTROL +//idea: Transfusion +//darkplaces implementation: LordHavoc +//cvars: +//sv_jumpstep (0/1, default 1) +//sv_stepheight (default 18) +//description: +//sv_jumpstep allows stepping up onto stairs while airborn, sv_stepheight controls how high a single step can be. + +//FTE_QC_CHECKPVS +//idea: Urre +//darkplaces implementation: divVerent +//builtin definitions: +float checkpvs(vector viewpos, entity viewee) = #240; +//description: +//returns true if viewee can be seen from viewpos according to PVS data + +//FTE_STRINGS +//idea: many +//darkplaces implementation: KrimZon +//builtin definitions: +float(string str, string sub, float startpos) strstrofs = #221; // returns the offset into a string of the matching text, or -1 if not found, case sensitive +float(string str, float ofs) str2chr = #222; // returns the character at the specified offset as an integer, or 0 if an invalid index, or byte value - 256 if the engine supports UTF8 and the byte is part of an extended character +string(float c, ...) chr2str = #223; // returns a string representing the character given, if the engine supports UTF8 this may be a multi-byte sequence (length may be more than 1) for characters over 127. +string(float ccase, float calpha, float cnum, string s, ...) strconv = #224; // reformat a string with special color characters in the font, DO NOT USE THIS ON UTF8 ENGINES (if you are lucky they will emit ^4 and such color codes instead), the parameter values are 0=same/1=lower/2=upper for ccase, 0=same/1=white/2=red/5=alternate/6=alternate-alternate for redalpha, 0=same/1=white/2=red/3=redspecial/4=whitespecial/5=alternate/6=alternate-alternate for rednum. +string(float chars, string s, ...) strpad = #225; // pad string with spaces to a specified length, < 0 = left padding, > 0 = right padding +string(string info, string key, string value, ...) infoadd = #226; // sets or adds a key/value pair to an infostring - note: forbidden characters are \ and " +string(string info, string key) infoget = #227; // gets a key/value pair in an infostring, returns value or null if not found +float(string s1, string s2, float len) strncmp = #228; // compare two strings up to the specified number of characters, if their length differs and is within the specified limit the result will be negative, otherwise it is the difference in value of their first non-matching character. +float(string s1, string s2) strcasecmp = #229; // compare two strings with case-insensitive matching, characters a-z are considered equivalent to the matching A-Z character, no other differences, and this does not consider special characters equal even if they look similar +float(string s1, string s2, float len) strncasecmp = #230; // same as strcasecmp but with a length limit, see strncmp +//string(string s, float start, float length) substring = #116; // see note below +//description: +//various string manipulation functions +//note: substring also exists in FRIK_FILE but this extension adds negative start and length as valid cases (see note above), substring is consistent with the php 5.2.0 substr function (not 5.2.3 behavior) +//substring returns a section of a string as a tempstring, if given negative +// start the start is measured back from the end of the string, if given a +// negative length the length is the offset back from the end of the string to +// stop at, rather than being relative to start, if start is negative and +// larger than length it is treated as 0. +// examples of substring: +// substring("blah", -3, 3) returns "lah" +// substring("blah", 3, 3) returns "h" +// substring("blah", -10, 3) returns "bla" +// substring("blah", -10, -3) returns "b" + +//DP_CON_BESTWEAPON +//idea: many +//darkplaces implementation: divVerent +//description: +//allows QC to register weapon properties for use by the bestweapon command, for mods that change required ammo count or type for the weapons +//it is done using console commands sent via stuffcmd: +// register_bestweapon quake +// register_bestweapon clear +// register_bestweapon <shortname> <impulse> <itemcode> <activeweaponcode> <ammostat> <ammomin> +//for example, this is what Quake uses: +// register_bestweapon 1 1 4096 4096 6 0 // STAT_SHELLS is 6 +// register_bestweapon 2 2 1 1 6 1 +// register_bestweapon 3 3 2 2 6 1 +// register_bestweapon 4 4 4 4 7 1 // STAT_NAILS is 7 +// register_bestweapon 5 5 8 8 7 1 +// register_bestweapon 6 6 16 16 8 1 // STAT_ROCKETS is 8 +// register_bestweapon 7 7 32 32 8 1 +// register_bestweapon 8 8 64 64 9 1 // STAT_CELLS is 9 +//after each map client initialization, this is reset back to Quake settings. So you should send these data in ClientConnect. +//also, this extension introduces a new "cycleweapon" command to the user. + +//DP_QC_STRINGBUFFERS +//idea: ?? +//darkplaces implementation: LordHavoc +//functions to manage string buffer objects - that is, arbitrary length string arrays that are handled by the engine +float() buf_create = #460; +void(float bufhandle) buf_del = #461; +float(float bufhandle) buf_getsize = #462; +void(float bufhandle_from, float bufhandle_to) buf_copy = #463; +void(float bufhandle, float sortpower, float backward) buf_sort = #464; +string(float bufhandle, string glue) buf_implode = #465; +string(float bufhandle, float string_index) bufstr_get = #466; +void(float bufhandle, float string_index, string str) bufstr_set = #467; +float(float bufhandle, string str, float order) bufstr_add = #468; +void(float bufhandle, float string_index) bufstr_free = #469; + +//DP_QC_STRINGBUFFERS_CVARLIST +//idea: divVerent +//darkplaces implementation: divVerent +//functions to list cvars and store their names into a stringbuffer +//cvars that start with pattern but not with antipattern will be stored into the buffer +void(float bufhandle, string pattern, string antipattern) buf_cvarlist = #517; + +//DP_QC_STRREPLACE +//idea: Sajt +//darkplaces implementation: Sajt +//builtin definitions: +string(string search, string replace, string subject) strreplace = #484; +string(string search, string replace, string subject) strireplace = #485; +//description: +//strreplace replaces all occurrences of 'search' with 'replace' in the string 'subject', and returns the result as a tempstring. +//strireplace does the same but uses case-insensitive matching of the 'search' term + +//DP_SV_SHUTDOWN +//idea: divVerent +//darkplaces implementation: divVerent +//A function that gets called just before progs exit. To save persistent data from. +//It is not called on a crash or error. +//void SV_Shutdown(); + +//EXT_CSQC +// #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC) +void(float index, float type, ...) addstat = #232; + +//ZQ_PAUSE +//idea: ZQuake +//darkplaces implementation: GreEn`mArine +//builtin definitions: +void(float pause) setpause = #531; +//function definitions: +//void(float elapsedtime) SV_PausedTic; +//description: +//during pause the world is not updated (time does not advance), SV_PausedTic is the only function you can be sure will be called at regular intervals during the pause, elapsedtime is the current system time in seconds since the pause started (not affected by slowmo or anything else). +// +//calling setpause(0) will end a pause immediately. +// +//Note: it is worth considering that network-related functions may be called during the pause (including customizeentityforclient for example), and it is also important to consider the continued use of the KRIMZON_SV_PARSECLIENTCOMMAND extension while paused (chatting players, etc), players may also join/leave during the pause. In other words, the only things that are not called are think and other time-related functions. + + + + +// EXPERIMENTAL (not finalized) EXTENSIONS: + +//DP_CRYPTO +//idea: divVerent +//darkplaces implementation: divVerent +//field definitions: (SVQC) +.string crypto_keyfp; // fingerprint of CA key the player used to authenticate, or string_null if not verified +.string crypto_mykeyfp; // fingerprint of CA key the server used to authenticate to the player, or string_null if not verified +.string crypto_idfp; // fingerprint of ID used by the player entity, or string_null if not identified +.string crypto_encryptmethod; // the string "AES128" if encrypting, and string_null if plaintext +.string crypto_signmethod; // the string "HMAC-SHA256" if signing, and string_null if plaintext +// there is no field crypto_myidfp, as that info contains no additional information the QC may have a use for +//builtin definitions: (SVQC) +float(string url, float id, string content_type, string delim, float buf, float keyid) crypto_uri_postbuf = #513; +//description: +//use -1 as buffer handle to justs end delim as postdata diff --git a/qcsrc/dpdefs/keycodes.qc b/qcsrc/dpdefs/keycodes.qc new file mode 100644 index 0000000000..76945736f9 --- /dev/null +++ b/qcsrc/dpdefs/keycodes.qc @@ -0,0 +1,147 @@ +/////////////////////////// +// key constants + +// +// these are the key numbers that should be passed to Key_Event +// +float K_TAB = 9; +float K_ENTER = 13; +float K_ESCAPE = 27; +float K_SPACE = 32; + +// normal keys should be passed as lowercased ascii + +float K_BACKSPACE = 127; +float K_UPARROW = 128; +float K_DOWNARROW = 129; +float K_LEFTARROW = 130; +float K_RIGHTARROW = 131; + +float K_ALT = 132; +float K_CTRL = 133; +float K_SHIFT = 134; + +float K_F1 = 135; +float K_F2 = 136; +float K_F3 = 137; +float K_F4 = 138; +float K_F5 = 139; +float K_F6 = 140; +float K_F7 = 141; +float K_F8 = 142; +float K_F9 = 143; +float K_F10 = 144; +float K_F11 = 145; +float K_F12 = 146; + +float K_INS = 147; +float K_DEL = 148; +float K_PGDN = 149; +float K_PGUP = 150; +float K_HOME = 151; +float K_END = 152; + +float K_NUMLOCK = 154; +float K_CAPSLOCK = 155; +float K_SCROLLLOCK = 156; + +float K_KP_0 = 157; +float K_KP_INS = K_KP_0; +float K_KP_1 = 158; +float K_KP_END = K_KP_1; +float K_KP_2 = 159; +float K_KP_DOWNARROW = K_KP_2; +float K_KP_3 = 160; +float K_KP_PGDN = K_KP_3; +float K_KP_4 = 161; +float K_KP_LEFTARROW = K_KP_4; +float K_KP_5 = 162; +float K_KP_6 = 163; +float K_KP_RIGHTARROW = K_KP_6; +float K_KP_7 = 164; +float K_KP_HOME = K_KP_7; +float K_KP_8 = 165; +float K_KP_UPARROW = K_KP_8; +float K_KP_9 = 166; +float K_KP_PGUP = K_KP_9; +float K_KP_PERIOD = 167; +float K_KP_DEL = K_KP_PERIOD; +float K_KP_DIVIDE = 168; +float K_KP_SLASH = K_KP_DIVIDE; +float K_KP_MULTIPLY = 169; +float K_KP_MINUS = 170; +float K_KP_PLUS = 171; +float K_KP_ENTER = 172; +float K_KP_EQUALS = 173; + +// mouse buttons generate virtual keys +float K_PAUSE = 153; + +// +// joystick buttons +// +float K_JOY1 = 768; +float K_JOY2 = 769; +float K_JOY3 = 770; +float K_JOY4 = 771; + +// +// +// aux keys are for multi-buttoned joysticks to generate so they can use +// the normal binding process +// +float K_AUX1 = 772; +float K_AUX2 = 773; +float K_AUX3 = 774; +float K_AUX4 = 775; +float K_AUX5 = 776; +float K_AUX6 = 777; +float K_AUX7 = 778; +float K_AUX8 = 779; +float K_AUX9 = 780; +float K_AUX10 = 781; +float K_AUX11 = 782; +float K_AUX12 = 783; +float K_AUX13 = 784; +float K_AUX14 = 785; +float K_AUX15 = 786; +float K_AUX16 = 787; +float K_AUX17 = 788; +float K_AUX18 = 789; +float K_AUX19 = 790; +float K_AUX20 = 791; +float K_AUX21 = 792; +float K_AUX22 = 793; +float K_AUX23 = 794; +float K_AUX24 = 795; +float K_AUX25 = 796; +float K_AUX26 = 797; +float K_AUX27 = 798; +float K_AUX28 = 799; +float K_AUX29 = 800; +float K_AUX30 = 801; +float K_AUX31 = 802; +float K_AUX32 = 803; + +// +// mouse buttons generate virtual keys +// +float K_MOUSE1 = 512; +float K_MOUSE2 = 513; +float K_MOUSE3 = 514; +float K_MWHEELUP = 515; +float K_MWHEELDOWN = 516; +float K_MOUSE4 = 517; +float K_MOUSE5 = 518; +float K_MOUSE6 = 519; +float K_MOUSE7 = 520; +float K_MOUSE8 = 521; +float K_MOUSE9 = 522; +float K_MOUSE10 = 523; +float K_MOUSE11 = 524; +float K_MOUSE12 = 525; +float K_MOUSE13 = 526; +float K_MOUSE14 = 527; +float K_MOUSE15 = 528; +float K_MOUSE16 = 529; + diff --git a/qcsrc/dpdefs/menudefs.qc b/qcsrc/dpdefs/menudefs.qc new file mode 100644 index 0000000000..74bfdc8602 --- /dev/null +++ b/qcsrc/dpdefs/menudefs.qc @@ -0,0 +1,538 @@ +////////////////////////////////////////////////////////// +// sys globals + +entity self; + +///////////////////////////////////////////////////////// +void end_sys_globals; +///////////////////////////////////////////////////////// +// sys fields + +///////////////////////////////////////////////////////// +void end_sys_fields; +///////////////////////////////////////////////////////// +// sys functions + +void() m_init; +void(float keynr, float ascii) m_keydown; +void() m_draw; +void(float mode) m_toggle; +void() m_shutdown; + +///////////////////////////////////////////////////////// +// sys constants +/////////////////////////// +// key dest constants + +float KEY_UNKNOWN = -1; +float KEY_GAME = 0; +float KEY_MENU = 2; +float KEY_MENU_GRABBED = 3; + +/////////////////////////// +// file constants + +float FILE_READ = 0; +float FILE_APPEND = 1; +float FILE_WRITE = 2; + +/////////////////////////// +// logical constants (just for completeness) + +float TRUE = 1; +float FALSE = 0; + +/////////////////////////// +// boolean constants + +float true = 1; +float false = 0; + +/////////////////////////// +// msg constants + +float MSG_BROADCAST = 0; // unreliable to all +float MSG_ONE = 1; // reliable to one (msg_entity) +float MSG_ALL = 2; // reliable to all +float MSG_INIT = 3; // write to the init string + +///////////////////////////// +// mouse target constants + +float MT_MENU = 1; +float MT_CLIENT = 2; + +///////////////////////// +// client state constants + +float CS_DEDICATED = 0; +float CS_DISCONNECTED = 1; +float CS_CONNECTED = 2; + +/////////////////////////// +// blend flags + +float DRAWFLAG_NORMAL = 0; +float DRAWFLAG_ADDITIVE = 1; +float DRAWFLAG_MODULATE = 2; +float DRAWFLAG_2XMODULATE = 3; + +/////////////////////////// +// null entity (actually it is the same like the world entity) + +entity null_entity; + +/////////////////////////// +// error constants + +// file handling +float ERR_CANNOTOPEN = -1; // fopen +float ERR_NOTENOUGHFILEHANDLES = -2; // fopen +float ERR_INVALIDMODE = -3; // fopen +float ERR_BADFILENAME = -4; // fopen + +// drawing functions + +float ERR_NULLSTRING = -1; +float ERR_BADDRAWFLAG = -2; +float ERR_BADSCALE = -3; +float ERR_BADSIZE = ERR_BADSCALE; +float ERR_NOTCACHED = -4; + +// server list stuff +float SLIST_HOSTCACHEVIEWCOUNT = 0; +float SLIST_HOSTCACHETOTALCOUNT = 1; +float SLIST_MASTERQUERYCOUNT = 2; +float SLIST_MASTERREPLYCOUNT = 3; +float SLIST_SERVERQUERYCOUNT = 4; +float SLIST_SERVERREPLYCOUNT = 5; +float SLIST_SORTFIELD = 6; +float SLIST_SORTDESCENDING = 7; +float SLIST_LEGACY_LINE1 = 1024; +float SLIST_LEGACY_LINE2 = 1025; +float SLIST_TEST_CONTAINS = 0; +float SLIST_TEST_NOTCONTAIN = 1; +float SLIST_TEST_LESSEQUAL = 2; +float SLIST_TEST_LESS = 3; +float SLIST_TEST_EQUAL = 4; +float SLIST_TEST_GREATER = 5; +float SLIST_TEST_GREATEREQUAL = 6; +float SLIST_TEST_NOTEQUAL = 7; +float SLIST_TEST_STARTSWITH = 8; +float SLIST_TEST_NOTSTARTSWITH = 9; +float SLIST_MASK_AND = 0; +float SLIST_MASK_OR = 512; + +// font stuff +float FONT_DEFAULT = 0; +float FONT_CONSOLE = 1; +float FONT_SBAR = 2; +float FONT_NOTIFY = 3; +float FONT_CHAT = 4; +float FONT_CENTERPRINT = 5; +float FONT_INFOBAR = 6; +float FONT_MENU = 7; +float FONT_USER = 8; // add to this the index, like FONT_USER+3 = user3. At least 8 of them are supported. +float drawfont; + +/* not supported at the moment +/////////////////////////// +// os constants + +float OS_WINDOWS = 0; +float OS_LINUX = 1; +float OS_MAC = 2; +*/ + + + + + + + + + + +////////////////////////////////////////////////// +// common cmd +////////////////////////////////////////////////// +// AK FIXME: Create perhaps a special builtin file for the common cmds + +void checkextension(string ext) = #1; + +// error cmds +void error(string err,...) = #2; +void objerror(string err,...) = #3; + +// print + +void print(string text,...) = #4; +void bprint(string text,...) = #5; +void sprint(float clientnum, string text,...) = #6; +void centerprint(string text,...) = #7; + +// vector stuff + +vector normalize(vector v) = #8; +float vlen(vector v) = #9; +float vectoyaw(vector v) = #10; +vector vectoangles(vector v) = #11; + +float random(void) = #12; + +void cmd(string command, ...) = #13; + +// cvar cmds + +float cvar(string name) = #14; +const string str_cvar(string name) = #71; +void cvar_set(string name, string value) = #15; + +void dprint(string text,...) = #16; + +// conversion functions + +string ftos(float f) = #17; +float fabs(float f) = #18; +string vtos(vector v) = #19; +string etos(entity e) = #20; + +float stof(string val,...) = #21; + +entity spawn(void) = #22; +void remove(entity e) = #23; + +entity find(entity start, .string field, string match) = #24; +entity findfloat(entity start, .float field, float match) = #25; +entity findentity(entity start, .entity field, entity match) = #25; + +entity findchainstring(.string field, string match) = #26; +entity findchainfloat(.float field, float match) = #27; +entity findchainentity(.entity field, entity match) = #27; + +string precache_file(string file) = #28; +string precache_sound(string sample) = #29; + +void crash(void) = #72; +void coredump(void) = #30; +void stackdump(void) = #73; +void traceon(void) = #31; +void traceoff(void) = #32; + +void eprint(entity e) = #33; +float rint(float f) = #34; +float floor(float f) = #35; +float ceil(float f) = #36; +entity nextent(entity e) = #37; +float sin(float f) = #38; +float cos(float f) = #39; +float sqrt(float f) = #40; +vector randomvec(void) = #41; + +float registercvar(string name, string value, float flags) = #42; // returns 1 if success + +float min(float f,...) = #43; +float max(float f,...) = #44; + +float bound(float min,float value, float max) = #45; +float pow(float a, float b) = #46; + +void copyentity(entity src, entity dst) = #47; + +float fopen(string filename, float mode) = #48; +void fclose(float fhandle) = #49; +string fgets(float fhandle) = #50; +void fputs(float fhandle, string s) = #51; + +float strlen(string s) = #52; +string strcat(string s1,string s2,...) = #53; +string substring(string s, float start, float length) = #54; + +vector stov(string s) = #55; + +string strzone(string s) = #56; +void strunzone(string s) = #57; + +float tokenize(string s) = #58 +string argv(float n) = #59; + +float isserver(void) = #60; +float clientcount(void) = #61; +float clientstate(void) = #62; +void clientcommand(float client, string s) = #63; +void changelevel(string map) = #64; +void localsound(string sample) = #65; +vector getmousepos(void) = #66; +float gettime(void) = #67; +void loadfromdata(string data) = #68; +void loadfromfile(string file) = #69; + +float mod(float val, float m) = #70; + +float search_begin(string pattern, float caseinsensitive, float quiet) = #74; +void search_end(float handle) = #75; +float search_getsize(float handle) = #76; +string search_getfilename(float handle, float num) = #77; + +string chr(float ascii) = #78; + +///////////////////////////////////////////////// +// Write* Functions +///////////////////////////////////////////////// +void WriteByte(float data, float dest, float desto) = #401; +void WriteChar(float data, float dest, float desto) = #402; +void WriteShort(float data, float dest, float desto) = #403; +void WriteLong(float data, float dest, float desto) = #404; +void WriteAngle(float data, float dest, float desto) = #405; +void WriteCoord(float data, float dest, float desto) = #406; +void WriteString(string data, float dest, float desto)= #407; +void WriteEntity(entity data, float dest, float desto) = #408; + +////////////////////////////////////////////////// +// Draw funtions +////////////////////////////////////////////////// + +float iscachedpic(string name) = #451; +string precache_pic(string name) = #452; +void freepic(string name) = #453; + +float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag) = #454; + +float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag) = #455; + +float drawcolorcodedstring(vector position, string text, vector scale, float alpha, float flag) = #467; + +vector drawcolorcodedstring2(vector position, string text, vector scale, vector rgb, float alpha, float flag) = #467; + +float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag) = #456; + +float drawfill(vector position, vector size, vector rgb, float alpha, float flag) = #457; + +void drawsetcliparea(float x, float y, float width, float height) = #458; + +void drawresetcliparea(void) = #459; + +vector drawgetimagesize(string pic) = #460; + +//////////////////////////////////////////////// +// Menu functions +//////////////////////////////////////////////// + +void setkeydest(float dest) = #601; +float getkeydest(void) = #602; + +void setmousetarget(float trg) = #603; +float getmousetarget(void) = #604; + +float isfunction(string function_name) = #607; +void callfunction(...) = #605; +void writetofile(float fhandle, entity ent) = #606; +vector getresolution(float number) = #608; +string keynumtostring(float keynum) = #609; + +float gethostcachevalue(float type) = #611; +string gethostcachestring(float type, float hostnr) = #612; + +//DP_CSQC_BINDMAPS +//idea: daemon, motorsep +//darkplaces implementation: divVerent +//builtin definitions: +string(float key, float bindmap) getkeybind_bindmap = #342; +float(float key, string bind, float bindmap) setkeybind_bindmap = #630; +vector(void) getbindmaps = #631; +float(vector bm) setbindmaps = #632; +string(string command, float bindmap) findkeysforcommand = #610; +float(string key) stringtokeynum = #341; +//<also allowed builtin number to match EXT_CSQC> string(float keynum) keynumtostring = #340; +//description: key bind setting/getting including support for switchable +//bindmaps. + +//DP_CRYPTO +//idea: divVerent +//darkplaces implementation: divVerent +//field definitions: (MENUQC) +string(string serveraddress) crypto_getkeyfp = #633; // retrieves the cached host key's CA fingerprint of a server given by IP address +string(string serveraddress) crypto_getidfp = #634; // retrieves the cached host key fingerprint of a server given by IP address +string(string serveraddress) crypto_getencryptlevel = #635; // 0 if never encrypting, 1 supported, 2 requested, 3 required, appended by list of allowed methods in order of preference ("AES128"), preceded by a space each +string(float i) crypto_getmykeyfp = #636; // retrieves the CA key fingerprint of a given CA slot, or "" if slot is unused but more to come, or string_null if end of list +string(float i) crypto_getmyidfp = #637; // retrieves the ID fingerprint of a given CA slot, or "" if slot is unused but more to come, or string_null if end of list +float CRYPTO_IDSTATUS_OUTOFRANGE = -1; +float CRYPTO_IDSTATUS_EMPTY = 0; +float CRYPTO_IDSTATUS_UNSIGNED = 1; +float CRYPTO_IDSTATUS_SIGNED = 2; +float(float i) crypto_getmyidstatus = #641; // retrieves the ID's status of a given CA slot, or 0 if slot is unused but more to come, or -1 if end of list +float(string url, float id, string content_type, string delim, float buf, float keyid) crypto_uri_postbuf = #513; +//description: +//use -1 as buffer handle to justs end delim as postdata + +//DP_GECKO_SUPPORT +//idea: Res2k, BlackHC +//darkplaces implementation: Res2k, BlackHC +//constant definitions: +float GECKO_BUTTON_DOWN = 0; +float GECKO_BUTTON_UP = 1; +// either use down and up or just press but not all of them! +float GECKO_BUTTON_PRESS = 2; +// use this for mouse events if needed? +float GECKO_BUTTON_DOUBLECLICK = 3; +//builtin definitions: +float gecko_create( string name ) = #487; +void gecko_destroy( string name ) = #488; +void gecko_navigate( string name, string URI ) = #489; +float gecko_keyevent( string name, float key, float eventtype ) = #490; +void gecko_mousemove( string name, float x, float y ) = #491; +void gecko_resize( string name, float w, float h ) = #492; +vector gecko_get_texture_extent( string name ) = #493; +//engine-called QC prototypes: +//string(string name, string query) Qecko_Query; +//description: +//provides an interface to the offscreengecko library and allows for internet browsing in games + +//FTE_STRINGS +//idea: many +//darkplaces implementation: KrimZon +//description: +//various string manipulation functions +float(string str, string sub, float startpos) strstrofs = #221; +float(string str, float ofs) str2chr = #222; +string(float c, ...) chr2str = #223; +string(float ccase, float calpha, float cnum, string s, ...) strconv = #224; +string(float chars, string s, ...) strpad = #225; +string(string info, string key, string value, ...) infoadd = #226; +string(string info, string key) infoget = #227; +float(string s1, string s2, float len) strncmp = #228; +float(string s1, string s2) strcasecmp = #229; +float(string s1, string s2, float len) strncasecmp = #230; + +//DP_QC_CRC16 +//idea: div0 +//darkplaces implementation: div0 +//Some hash function to build hash tables with. This has to be be the CRC-16-CCITT that is also required for the QuakeWorld download protocol. +//When caseinsensitive is set, the CRC is calculated of the lower cased string. +float(float caseinsensitive, string s, ...) crc16 = #494; + +//DP_QC_CVAR_TYPE +float(string name) cvar_type = #495; +float CVAR_TYPEFLAG_EXISTS = 1; +float CVAR_TYPEFLAG_SAVED = 2; +float CVAR_TYPEFLAG_PRIVATE = 4; +float CVAR_TYPEFLAG_ENGINE = 8; +float CVAR_TYPEFLAG_HASDESCRIPTION = 16; +float CVAR_TYPEFLAG_READONLY = 32; + +//DP_QC_STRINGBUFFERS +//idea: ?? +//darkplaces implementation: LordHavoc +//functions to manage string buffer objects - that is, arbitrary length string arrays that are handled by the engine +float() buf_create = #440; +void(float bufhandle) buf_del = #441; +float(float bufhandle) buf_getsize = #442; +void(float bufhandle_from, float bufhandle_to) buf_copy = #443; +void(float bufhandle, float sortpower, float backward) buf_sort = #444; +string(float bufhandle, string glue) buf_implode = #445; +string(float bufhandle, float string_index) bufstr_get = #446; +void(float bufhandle, float string_index, string str) bufstr_set = #447; +float(float bufhandle, string str, float order) bufstr_add = #448; +void(float bufhandle, float string_index) bufstr_free = #449; +void(float bufhandle, string pattern, string antipattern) buf_cvarlist = #517; + +//DP_QC_STRING_CASE_FUNCTIONS +//idea: Dresk +//darkplaces implementation: LordHavoc / Dresk +//builtin definitions: +string(string s) strtolower = #480; // returns the passed in string in pure lowercase form +string(string s) strtoupper = #481; // returns the passed in string in pure uppercase form +//description: +//provides simple string uppercase and lowercase functions + +//DP_QC_CVAR_DESCRIPTION +//idea: divVerent +//DarkPlaces implementation: divVerent +//builtin definitions: +string(string name) cvar_description = #518; +//description: +//returns the description of a cvar + +//DP_QC_DIGEST +//idea: motorsep, Spike +//DarkPlaces implementation: divVerent +//builtin definitions: +string(string digest, string data, ...) digest_hex = #639; +//description: +//returns a given hex digest of given data +//the returned digest is always encoded in hexadecimal +//only the "MD4" digest is always supported! +//if the given digest is not supported, string_null is returned +//the digest string is matched case sensitively, use "MD4", not "md4"! + +//DP_QC_URI_ESCAPE +//idea: div0 +//darkplaces implementation: div0 +//URI::Escape's functionality +string(string in) uri_escape = #510; +string(string in) uri_unescape = #511; + +//DP_QC_URI_GET +//idea: divVerent +//darkplaces implementation: divVerent +//loads text from an URL into a string +//returns 1 on success of initiation, 0 if there are too many concurrent +//connections already or if the URL is invalid +//the following callback will receive the data and MUST exist! +// void(float id, float status, string data) URI_Get_Callback; +//status is either +// negative for an internal error, +// 0 for success, or +// the HTTP response code on server error (e.g. 404) +//if 1 is returned by uri_get, the callback will be called in the future +float(string url, float id) uri_get = #513; +//DP_QC_URI_POST +//idea: divVerent +//darkplaces implementation: divVerent +//loads text from an URL into a string after POSTing via HTTP +//works like uri_get, but uri_post sends data with Content-Type: content_type to the server +//and uri_post sends the string buffer buf, joined using the delimiter delim +float(string url, float id, string content_type, string data) uri_post = #513; +float(string url, float id, string content_type, string delim, float buf) uri_postbuf = #513; + +// assorted undocumented extensions +string(string, float) netaddress_resolve = #625; +string(string search, string replace, string subject) strreplace = #484; +string(float uselocaltime, string format, ...) strftime = #478; +float(string s) tokenize_console = #514; +float(float i) argv_start_index = #515; +float(float i) argv_end_index = #516; +string(float, float) getgamedirinfo = #626; +#define GETGAMEDIRINFO_NAME 0 +#define GETGAMEDIRINFO_DESCRIPTION 1 +float log(float f) = #532; +string(string format, ...) sprintf = #627; +string(string s) strdecolorize = #477; +entity findflags(entity start, .float field, float match) = #87; +entity findchainflags(.float field, float match) = #88; +float(string s, string separator1, ...) tokenizebyseparator = #479; +float etof(entity ent) = #79; +entity ftoe(float num) = #80; +float validstring(string str) = #81; +float altstr_count(string str) = #82; +string altstr_prepare(string str) = #83; +string altstr_get(string str, float num) = #84; +string altstr_set(string str, float num, string set) = #85; +string altstr_ins(string str, float num, string set) = #86; +float isdemo() = #349; +float drawsubpic(vector position, vector size, string pic, vector srcPosition, vector srcSize, vector rgb, float alpha, float flag) = #469; +//vector getresolution(float number, ...) = #608; // optional argument "isfullscreen" +void parseentitydata(entity ent, string data) = #613; +void resethostcachemasks(void) = #615; +void sethostcachemaskstring(float mask, float fld, string str, float op) = #616; +void sethostcachemasknumber(float mask, float fld, float num, float op) = #617; +void resorthostcache(void) = #618; +void sethostcachesort(float fld, float descending) = #619; +void refreshhostcache(void) = #620; +float gethostcachenumber(float fld, float hostnr) = #621; +float gethostcacheindexforkey(string key) = #622; +void addwantedhostcachekey(string key) = #623; +string getextresponse(void) = #624; +const string cvar_string(string name) = #71; +const string cvar_defstring(string name) = #89; +float stringwidth(string text, float handleColors, vector size) = #468; diff --git a/qcsrc/dpdefs/progsdefs.qc b/qcsrc/dpdefs/progsdefs.qc new file mode 100644 index 0000000000..912c3ecabe --- /dev/null +++ b/qcsrc/dpdefs/progsdefs.qc @@ -0,0 +1,507 @@ +/* +============================================================================== + + SOURCE FOR GLOBALVARS_T C STRUCTURE + MUST NOT BE MODIFIED, OR CRC ERRORS WILL APPEAR + +============================================================================== +*/ + +// +// system globals +// +entity self; +entity other; +entity world; +float time; +float frametime; + +float force_retouch; // force all entities to touch triggers + // next frame. this is needed because + // non-moving things don't normally scan + // for triggers, and when a trigger is + // created (like a teleport trigger), it + // needs to catch everything. + // decremented each frame, so set to 2 + // to guarantee everything is touched +string mapname; + +float deathmatch; +float coop; +float teamplay; + +float serverflags; // propagated from level to level, used to + // keep track of completed episodes + +float total_secrets; +float total_monsters; + +float found_secrets; // number of secrets found +float killed_monsters; // number of monsters killed + + +// spawnparms are used to encode information about clients across server +// level changes +float parm1, parm2, parm3, parm4, parm5, parm6, parm7, parm8, parm9, parm10, parm11, parm12, parm13, parm14, parm15, parm16; + +// +// global variables set by built in functions +// +vector v_forward, v_up, v_right; // set by makevectors() + +// set by traceline / tracebox +float trace_allsolid; +float trace_startsolid; +float trace_fraction; +vector trace_endpos; +vector trace_plane_normal; +float trace_plane_dist; +entity trace_ent; +float trace_inopen; +float trace_inwater; + +entity msg_entity; // destination of single entity writes + +// +// required prog functions +// +void() main; // only for testing + +void() StartFrame; + +void() PlayerPreThink; +void() PlayerPostThink; + +void() ClientKill; +void() ClientConnect; +void() PutClientInServer; // call after setting the parm1... parms +void() ClientDisconnect; + +void() SetNewParms; // called when a client first connects to + // a server. sets parms so they can be + // saved off for restarts + +void() SetChangeParms; // call to set parms for self so they can + // be saved for a level transition + + +//================================================ +void end_sys_globals; // flag for structure dumping +//================================================ + +/* +============================================================================== + + SOURCE FOR ENTVARS_T C STRUCTURE + MUST NOT BE MODIFIED, OR CRC ERRORS WILL APPEAR + +============================================================================== +*/ + +// +// system fields (*** = do not set in prog code, maintained by C code) +// +.float modelindex; // *** model index in the precached list +.vector absmin, absmax; // *** origin + mins / maxs + +.float ltime; // local time for entity +.float movetype; +.float solid; + +.vector origin; // *** +.vector oldorigin; // *** +.vector velocity; +.vector angles; +.vector avelocity; + +.vector punchangle; // temp angle adjust from damage or recoil + +.string classname; // spawn function +.string model; +.float frame; +.float skin; +.float effects; + +.vector mins, maxs; // bounding box extents reletive to origin +.vector size; // maxs - mins + +.void() touch; +.void() use; +.void() think; +.void() blocked; // for doors or plats, called when can't push other + +.float nextthink; +.entity groundentity; + +// stats +.float health; +.float frags; +.float weapon; // one of the IT_SHOTGUN, etc flags +.string weaponmodel; +.float weaponframe; +.float currentammo; +.float ammo_shells, ammo_nails, ammo_rockets, ammo_cells; + +.float items; // bit flags + +.float takedamage; +.entity chain; +.float deadflag; + +.vector view_ofs; // add to origin to get eye point + + +.float button0; // fire +.float button1; // use +.float button2; // jump + +.float impulse; // weapon changes + +.float fixangle; +.vector v_angle; // view / targeting angle for players +.float idealpitch; // calculated pitch angle for lookup up slopes + + +.string netname; + +.entity enemy; + +.float flags; + +.float colormap; +.float team; + +.float max_health; // players maximum health is stored here + +.float teleport_time; // don't back up + +.float armortype; // save this fraction of incoming damage +.float armorvalue; + +.float waterlevel; // 0 = not in, 1 = feet, 2 = wast, 3 = eyes +.float watertype; // a contents value + +.float ideal_yaw; +.float yaw_speed; + +.entity aiment; + +.entity goalentity; // a movetarget or an enemy + +.float spawnflags; + +.string target; +.string targetname; + +// damage is accumulated through a frame. and sent as one single +// message, so the super shotgun doesn't generate huge messages +.float dmg_take; +.float dmg_save; +.entity dmg_inflictor; + +.entity owner; // who launched a missile +.vector movedir; // mostly for doors, but also used for waterjump + +.string message; // trigger messages + +.float sounds; // either a cd track number or sound number + +.string noise, noise1, noise2, noise3; // contains names of wavs to play + +//================================================ +void end_sys_fields; // flag for structure dumping +//================================================ + +/* +============================================================================== + + CONSTANT DEFINITIONS + +============================================================================== +*/ + + +// +// constants +// + +float FALSE = 0; +float TRUE = 1; + +// edict.flags +float FL_FLY = 1; +float FL_SWIM = 2; +float FL_CLIENT = 8; // set for all client edicts +float FL_INWATER = 16; // for enter / leave water splash +float FL_MONSTER = 32; +float FL_GODMODE = 64; // player cheat +float FL_NOTARGET = 128; // player cheat +float FL_ITEM = 256; // extra wide size for bonus items +float FL_ONGROUND = 512; // standing on something +float FL_PARTIALGROUND = 1024; // not all corners are valid +float FL_WATERJUMP = 2048; // player jumping out of water +float FL_JUMPRELEASED = 4096; // for jump debouncing + +// edict.movetype values +float MOVETYPE_NONE = 0; // never moves +//float MOVETYPE_ANGLENOCLIP = 1; +//float MOVETYPE_ANGLECLIP = 2; +float MOVETYPE_WALK = 3; // players only +float MOVETYPE_STEP = 4; // discrete, not real time unless fall +float MOVETYPE_FLY = 5; +float MOVETYPE_TOSS = 6; // gravity +float MOVETYPE_PUSH = 7; // no clip to world, push and crush +float MOVETYPE_NOCLIP = 8; +float MOVETYPE_FLYMISSILE = 9; // fly with extra size against monsters +float MOVETYPE_BOUNCE = 10; +float MOVETYPE_BOUNCEMISSILE = 11; // bounce with extra size + +// edict.solid values +float SOLID_NOT = 0; // no interaction with other objects +float SOLID_TRIGGER = 1; // touch on edge, but not blocking +float SOLID_BBOX = 2; // touch on edge, block +float SOLID_SLIDEBOX = 3; // touch on edge, but not an onground +float SOLID_BSP = 4; // bsp clip, touch on edge, block + +// range values +float RANGE_MELEE = 0; +float RANGE_NEAR = 1; +float RANGE_MID = 2; +float RANGE_FAR = 3; + +// deadflag values + +float DEAD_NO = 0; +float DEAD_DYING = 1; +float DEAD_DEAD = 2; +float DEAD_RESPAWNABLE = 3; +float DEAD_RESPAWNING = 4; // dead, waiting for buttons to be released + +// takedamage values + +float DAMAGE_NO = 0; +float DAMAGE_YES = 1; +float DAMAGE_AIM = 2; + +// items +float IT_AXE = 4096; +float IT_SHOTGUN = 1; +float IT_SUPER_SHOTGUN = 2; +float IT_NAILGUN = 4; +float IT_SUPER_NAILGUN = 8; +float IT_GRENADE_LAUNCHER = 16; +float IT_ROCKET_LAUNCHER = 32; +float IT_LIGHTNING = 64; +float IT_EXTRA_WEAPON = 128; + +float IT_SHELLS = 256; +float IT_NAILS = 512; +float IT_ROCKETS = 1024; +float IT_CELLS = 2048; + +float IT_ARMOR1 = 8192; +float IT_ARMOR2 = 16384; +float IT_ARMOR3 = 32768; +float IT_SUPERHEALTH = 65536; + +float IT_KEY1 = 131072; +float IT_KEY2 = 262144; + +float IT_INVISIBILITY = 524288; +float IT_INVULNERABILITY = 1048576; +float IT_SUIT = 2097152; +float IT_QUAD = 4194304; + +// point content values + +float CONTENT_EMPTY = -1; +float CONTENT_SOLID = -2; +float CONTENT_WATER = -3; +float CONTENT_SLIME = -4; +float CONTENT_LAVA = -5; +float CONTENT_SKY = -6; + +float STATE_TOP = 0; +float STATE_BOTTOM = 1; +float STATE_UP = 2; +float STATE_DOWN = 3; + +vector VEC_ORIGIN = '0 0 0'; +vector VEC_HULL_MIN = '-16 -16 -24'; +vector VEC_HULL_MAX = '16 16 32'; + +vector VEC_HULL2_MIN = '-32 -32 -24'; +vector VEC_HULL2_MAX = '32 32 64'; + +// protocol bytes +float SVC_TEMPENTITY = 23; +float SVC_KILLEDMONSTER = 27; +float SVC_FOUNDSECRET = 28; +float SVC_INTERMISSION = 30; +float SVC_FINALE = 31; +float SVC_CDTRACK = 32; +float SVC_SELLSCREEN = 33; + + +float TE_SPIKE = 0; +float TE_SUPERSPIKE = 1; +float TE_GUNSHOT = 2; +float TE_EXPLOSION = 3; +float TE_TAREXPLOSION = 4; +float TE_LIGHTNING1 = 5; +float TE_LIGHTNING2 = 6; +float TE_WIZSPIKE = 7; +float TE_KNIGHTSPIKE = 8; +float TE_LIGHTNING3 = 9; +float TE_LAVASPLASH = 10; +float TE_TELEPORT = 11; + +// sound channels +// channel 0 never willingly overrides +// other channels (1-7) allways override a playing sound on that channel +float CHAN_AUTO = 0; +float CHAN_WEAPON = 1; +float CHAN_VOICE = 2; +float CHAN_ITEM = 3; +float CHAN_BODY = 4; + +float ATTN_NONE = 0; +float ATTN_NORM = 1; +float ATTN_IDLE = 2; +float ATTN_STATIC = 3; + +// update types + +float UPDATE_GENERAL = 0; +float UPDATE_STATIC = 1; +float UPDATE_BINARY = 2; +float UPDATE_TEMP = 3; + +// entity effects + +float EF_BRIGHTFIELD = 1; +float EF_MUZZLEFLASH = 2; +float EF_BRIGHTLIGHT = 4; +float EF_DIMLIGHT = 8; + + +// messages +float MSG_BROADCAST = 0; // unreliable to all +float MSG_ONE = 1; // reliable to one (msg_entity) +float MSG_ALL = 2; // reliable to all +float MSG_INIT = 3; // write to the init string + +//=========================================================================== + +// +// builtin functions +// + +void(vector ang) makevectors = #1; // sets v_forward, etc globals +void(entity e, vector o) setorigin = #2; +void(entity e, string m) setmodel = #3; // set movetype and solid first +void(entity e, vector min, vector max) setsize = #4; +// #5 was removed +void() break = #6; +float() random = #7; // returns 0 - 1 +void(entity e, float chan, string samp, float vol, float atten) sound = #8; +vector(vector v) normalize = #9; +void(string e, ...) error = #10; +void(string e, ...) objerror = #11; +float(vector v) vlen = #12; +float(vector v) vectoyaw = #13; +entity() spawn = #14; +void(entity e) remove = #15; + +// sets trace_* globals +// nomonsters can be: +// An entity will also be ignored for testing if forent == test, +// forent->owner == test, or test->owner == forent +// a forent of world is ignored +void(vector v1, vector v2, float nomonsters, entity forent) traceline = #16; + +entity() checkclient = #17; // returns a client to look for +entity(entity start, .string fld, string match) find = #18; +string(string s) precache_sound = #19; +string(string s) precache_model = #20; +void(entity client, string s, ...)stuffcmd = #21; +entity(vector org, float rad) findradius = #22; +void(string s, ...) bprint = #23; +void(entity client, string s, ...) sprint = #24; +void(string s, ...) dprint = #25; +string(float f) ftos = #26; +string(vector v) vtos = #27; +void() coredump = #28; // prints all edicts +void() traceon = #29; // turns statment trace on +void() traceoff = #30; +void(entity e) eprint = #31; // prints an entire edict +float(float yaw, float dist) walkmove = #32; // returns TRUE or FALSE +// #33 was removed +float() droptofloor= #34; // TRUE if landed on floor +void(float style, string value) lightstyle = #35; +float(float v) rint = #36; // round to nearest int +float(float v) floor = #37; // largest integer <= v +float(float v) ceil = #38; // smallest integer >= v +// #39 was removed +float(entity e) checkbottom = #40; // true if self is on ground +float(vector v) pointcontents = #41; // returns a CONTENT_* +// #42 was removed +float(float f) fabs = #43; +vector(entity e, float speed) aim = #44; // returns the shooting vector +float(string s) cvar = #45; // return cvar.value +void(string s, ...) localcmd = #46; // put string into local que +entity(entity e) nextent = #47; // for looping through all ents +void(vector o, vector d, float color, float count) particle = #48;// start a particle effect +void() ChangeYaw = #49; // turn towards self.ideal_yaw + // at self.yaw_speed +// #50 was removed +vector(vector v) vectoangles = #51; + +// +// direct client message generation +// +void(float to, float f) WriteByte = #52; +void(float to, float f) WriteChar = #53; +void(float to, float f) WriteShort = #54; +void(float to, float f) WriteLong = #55; +void(float to, float f) WriteCoord = #56; +void(float to, float f) WriteAngle = #57; +void(float to, string s, ...) WriteString = #58; +void(float to, entity s) WriteEntity = #59; + +// +// broadcast client message generation +// + +// void(float f) bWriteByte = #59; +// void(float f) bWriteChar = #60; +// void(float f) bWriteShort = #61; +// void(float f) bWriteLong = #62; +// void(float f) bWriteCoord = #63; +// void(float f) bWriteAngle = #64; +// void(string s) bWriteString = #65; +// void(entity e) bWriteEntity = #66; + +void(float step) movetogoal = #67; + +string(string s) precache_file = #68; // no effect except for -copy +void(entity e) makestatic = #69; +void(string s) changelevel = #70; + +//#71 was removed + +void(string var, string val) cvar_set = #72; // sets cvar.value + +void(entity client, string s, ...) centerprint = #73; // sprint, but in middle + +void(vector pos, string samp, float vol, float atten) ambientsound = #74; + +string(string s) precache_model2 = #75; // registered version only +string(string s) precache_sound2 = #76; // registered version only +string(string s) precache_file2 = #77; // registered version only + +void(entity e) setspawnparms = #78; // set parm1... to the + // values at level start + // for coop respawn + +//============================================================================ diff --git a/qcsrc/i18n-badwords.txt b/qcsrc/i18n-badwords.txt new file mode 100644 index 0000000000..828fe0a8b8 --- /dev/null +++ b/qcsrc/i18n-badwords.txt @@ -0,0 +1,34 @@ +# list of words that must not be used in the source as a single string; +# use ZCTX(_("CONTEXT^string")) instead +# vi macro to do it: +# :s/_("\([^"]*\)")/ZCTX(_("CONTEXT^\1"))/g +# test by: +# grep -v ^# i18n-badwords.txt | while IFS= read -r W; do grep -nri "_(\"$W\")" menu/xonotic; done | sort -n +# this is done to help with languages like Russian where these words may need +# different grammatical gender in different instances +All +Best +Disabled +Good +High +Insane +Low +Lowest +Medium +Normal +Off +Ultra +Small +Large +Custom +Very short +Short +Long +Full +Empty +None +Few +Many +Lots +Both +Ambient: diff --git a/qcsrc/i18n-guide.txt b/qcsrc/i18n-guide.txt new file mode 100644 index 0000000000..f2677fe3a3 --- /dev/null +++ b/qcsrc/i18n-guide.txt @@ -0,0 +1,31 @@ +How to make the .po template: + +find . -type f -not -name \*.po -not -name \*.txt | xgettext -LC -k_ -f- --from-code utf-8 + + +How to compare the .po template against a language file: + +msgcmp ../../menu.dat.de.po messages.po + + +How to merge the .po template into a language file: + +msgmerge -U ../../menu.dat.de.po messages.po + + +Guideline: +- do NOT translate strings in error() messages, or in dprint()! +- delete obviously useless developer prints while at it +- change obvious developer prints from print to dprint (even in comments), + unless in developer-only functions (e.g. *dumptree*) +- mark translatable strings with _() +- if a translatable string is a strcat monster, change it to sprintf +- if code loads files with text, use language_filename() +- interesting vim macros: + :map # /"<return> + :map ' i_(<esc>2f"a)<esc>/"<return> + :map " F"isprintf(_(<esc>%i), )<esc>i + +Unresolved TODO: + +- translated campaigns diff --git a/qcsrc/menu/anim/animhost.c b/qcsrc/menu/anim/animhost.c index fc345e4458..48a45bda84 100644 --- a/qcsrc/menu/anim/animhost.c +++ b/qcsrc/menu/anim/animhost.c @@ -65,6 +65,7 @@ void AnimHost_removeAnim(entity me, entity other) n.prevSibling = p; else me.lastChild = p; + remove(other); } void AnimHost_removeAllAnim(entity me) @@ -141,7 +142,6 @@ void AnimHost_finishAllAnim(entity me) { tmp = e; e = tmp.prevSibling; - me.removeAnim(me, tmp); tmp.finishAnim(tmp); } } @@ -155,7 +155,6 @@ void AnimHost_finishObjAnim(entity me, entity obj) { tmp = e; e = tmp.prevSibling; - me.removeAnim(me, tmp); tmp.finishAnim(tmp); } } @@ -167,15 +166,11 @@ void AnimHost_tickAll(entity me) for(e = me.firstChild; e; e = e.nextSibling) { e.tick(e, time); - } - for(e = me.firstChild; e; e = e.nextSibling) - { if (e.isFinished(e)) { tmp = e; e = tmp.prevSibling; me.removeAnim(me, tmp); - remove(tmp); } } } diff --git a/qcsrc/menu/classes.c b/qcsrc/menu/classes.c index 9ebcbb8f5b..c0a9780471 100644 --- a/qcsrc/menu/classes.c +++ b/qcsrc/menu/classes.c @@ -27,7 +27,9 @@ #include "xonotic/bigbutton.c" #include "xonotic/commandbutton.c" #include "xonotic/bigcommandbutton.c" +#include "xonotic/dialog_firstrun.c" #include "xonotic/dialog_teamselect.c" +#include "xonotic/dialog_sandboxtools.c" #include "xonotic/dialog_settings.c" #include "xonotic/dialog_settings_video.c" #include "xonotic/dialog_settings_effects.c" @@ -58,9 +60,10 @@ #include "xonotic/dialog_multiplayer_create_mutators.c" #include "xonotic/dialog_multiplayer_create_advanced.c" #include "xonotic/dialog_multiplayer_create_mapinfo.c" -#include "xonotic/gametypebutton.c" +#include "xonotic/gametypelist.c" #include "xonotic/maplist.c" #include "xonotic/skinlist.c" +#include "xonotic/languagelist.c" #include "xonotic/image.c" #include "xonotic/crosshairbutton.c" #include "xonotic/playermodel.c" @@ -101,4 +104,6 @@ #include "xonotic/dialog_hudpanel_engineinfo.c" #include "xonotic/dialog_hudpanel_infomessages.c" #include "xonotic/dialog_hudpanel_weapons.c" +#include "xonotic/dialog_hudpanel_physics.c" +#include "xonotic/dialog_hudpanel_centerprint.c" #include "xonotic/slider_picmip.c" diff --git a/qcsrc/menu/command/menu_cmd.qc b/qcsrc/menu/command/menu_cmd.qc new file mode 100644 index 0000000000..3be6edc662 --- /dev/null +++ b/qcsrc/menu/command/menu_cmd.qc @@ -0,0 +1,187 @@ +string _dumptree_space; +void _dumptree_open(entity pass, entity me) +{ + string s; + s = me.toString(me); + if(s == "") + s = me.classname; + else + s = strcat(me.classname, ": ", s); + print(_dumptree_space, etos(me), " (", s, ")"); + if(me.firstChild) + { + print(" {\n"); + _dumptree_space = strcat(_dumptree_space, " "); + } + else + print("\n"); +} +void _dumptree_close(entity pass, entity me) +{ + if(me.firstChild) + { + _dumptree_space = substring(_dumptree_space, 0, strlen(_dumptree_space) - 2); + print(_dumptree_space, "}\n"); + } +} + +float curl_uri_get_pos; +float curl_uri_get_exec[URI_GET_CURL_END - URI_GET_CURL + 1]; +string curl_uri_get_cvar[URI_GET_CURL_END - URI_GET_CURL + 1]; +void Curl_URI_Get_Callback(float id, float status, string data) +{ + float i; + float do_exec; + string do_cvar; + i = id - URI_GET_CURL; + do_exec = curl_uri_get_exec[i]; + do_cvar = curl_uri_get_cvar[i]; + if(status != 0) + { + print(sprintf(_("error: status is %d\n"), status)); + if(do_cvar) + strunzone(do_cvar); + return; + } + if(do_exec) + localcmd(data); + if(do_cvar) + { + cvar_set(do_cvar, data); + strunzone(do_cvar); + } + if(!do_exec && !do_cvar) + print(data); +} + +void GameCommand(string theCommand) +{ + float argc; + argc = tokenize_console(theCommand); + + if(argv(0) == "help" || argc == 0) + { + print(_("Usage: menu_cmd command..., where possible commands are:\n")); + print(_(" sync - reloads all cvars on the current menu page\n")); + print(_(" directmenu ITEM - select a menu item as main item\n")); + GenericCommand("help"); + return; + } + + if(GenericCommand(theCommand)) + return; + + if(argv(0) == "sync") + { + m_sync(); + return; + } + + if(argv(0) == "directmenu") if(argc == 2) + { + // switch to a menu item + if(!isdemo()) // don't allow this command in demos + m_goto(argv(1)); + return; + } + + if(argv(0) == "directpanelhudmenu") + { + // switch to a menu item + m_goto(strcat("HUD", argv(1))); + return; + } + + if(argv(0) == "skinselect") + { + m_goto_skin_selector(); + return; + } + + if(argv(0) == "languageselect") + { + m_goto_language_selector(); + return; + } + + if(argv(0) == "videosettings") + { + m_goto_video_settings(); + return; + } + + if(argv(0) == "dumptree") + { + _dumptree_space = ""; + depthfirst(main, parent, firstChild, nextSibling, _dumptree_open, _dumptree_close, NULL); + return; + } + + if(argv(0) == "curl") + { + float do_exec; + string do_cvar; + float key; + float i, j; + string url; + float buf; + float r; + + do_exec = FALSE; + do_cvar = string_null; + key = -1; + + for(i = 1; i+1 < argc; ++i) + { + if(argv(i) == "--cvar" && i+2 < argc) + { + ++i; + do_cvar = strzone(argv(i)); + continue; + } + if(argv(i) == "--exec") + { + do_exec = TRUE; + continue; + } + if(argv(i) == "--key" && i+2 < argc) + { + ++i; + key = stof(argv(i)); + continue; + } + break; + } + + // now, argv(i) is the URL + // following args may be POST parameters + url = argv(i); + ++i; + buf = buf_create(); + j = 0; + for(; i+1 < argc; i += 2) + bufstr_set(buf, ++j, sprintf("%s=%s", uri_escape(argv(i)), uri_escape(argv(i+1)))); + if(i < argc) + bufstr_set(buf, ++j, sprintf("submit=%s", uri_escape(argv(i)))); + + if(j == 0) // no args: GET + r = crypto_uri_postbuf(url, URI_GET_CURL + curl_uri_get_pos, string_null, string_null, -1, key); + else // with args: POST + r = crypto_uri_postbuf(url, URI_GET_CURL + curl_uri_get_pos, "application/x-www-form-urlencoded", "&", buf, key); + + if(r) + { + curl_uri_get_exec[curl_uri_get_pos] = do_exec; + curl_uri_get_cvar[curl_uri_get_pos] = do_cvar; + curl_uri_get_pos = mod(curl_uri_get_pos + 1, URI_GET_CURL_END - URI_GET_CURL + 1); + } + else + print(_("error creating curl handle\n")); + + buf_del(buf); + + return; + } + + print(_("Invalid command. For a list of supported commands, try menu_cmd help.\n")); +} diff --git a/qcsrc/menu/command/menu_cmd.qh b/qcsrc/menu/command/menu_cmd.qh new file mode 100644 index 0000000000..7a18fe2def --- /dev/null +++ b/qcsrc/menu/command/menu_cmd.qh @@ -0,0 +1 @@ +void GameCommand(string command); diff --git a/qcsrc/menu/draw.qc b/qcsrc/menu/draw.qc index a33cac9163..7fe4aea3bd 100644 --- a/qcsrc/menu/draw.qc +++ b/qcsrc/menu/draw.qc @@ -2,14 +2,6 @@ string draw_mousepointer; vector draw_mousepointer_offset; vector draw_mousepointer_size; -string draw_UseSkinFor(string pic) -{ - if(substring(pic, 0, 1) == "/") - return substring(pic, 1, strlen(pic)-1); - else - return strcat(draw_currentSkin, "/", pic); -} - void draw_setMousePointer(string pic, vector theSize, vector theOffset) { draw_mousepointer = strzone(draw_UseSkinFor(pic)); @@ -61,10 +53,10 @@ vector boxToGlobalSize(vector v, vector theScale) return v; } -void draw_PreloadPicture(string pic) +string draw_PreloadPicture(string pic) { pic = draw_UseSkinFor(pic); - precache_pic(pic); + return precache_pic(pic); } void draw_Picture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha) @@ -282,14 +274,14 @@ void draw_Text(vector theOrigin, string theText, vector theSize, vector theColor } void draw_CenterText(vector theOrigin, string theText, vector theSize, vector theColor, float theAlpha, float ICanHasKallerz) { - //print(strcat("orig = ", vtos(theOrigin) ," tx = ", ftos(draw_TextWidth(theText, ICanHasKallerz, theSize)), "\n")); + //dprint(strcat("orig = ", vtos(theOrigin) ," tx = ", ftos(draw_TextWidth(theText, ICanHasKallerz, theSize)), "\n")); draw_Text(theOrigin - eX * 0.5 * draw_TextWidth(theText, ICanHasKallerz, theSize), theText, theSize, theColor, theAlpha, ICanHasKallerz); } float draw_TextWidth(string theText, float ICanHasKallerz, vector SizeThxBye) { //return strlen(theText); - //print("draw_TextWidth \"", theText, "\"\n"); + //dprint("draw_TextWidth \"", theText, "\"\n"); vector v; v = '0 0 0'; //float r; diff --git a/qcsrc/menu/draw.qh b/qcsrc/menu/draw.qh index 63e22bd635..0f5811713d 100644 --- a/qcsrc/menu/draw.qh +++ b/qcsrc/menu/draw.qh @@ -14,7 +14,7 @@ void draw_reset(float cw, float ch, float ox, float oy); void draw_setMousePointer(string pic, vector theSize, vector theOffset); void draw_drawMousePointer(vector where); -void draw_PreloadPicture(string pic); +string draw_PreloadPicture(string pic); void draw_ButtonPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha); void draw_VertButtonPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha); void draw_BorderPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha, vector theBorderSize); @@ -38,7 +38,5 @@ vector globalToBoxSize(vector v, vector scale); float draw_NeedResizeNotify; -string draw_currentSkin; - float draw_TextWidth_WithColors(string s, vector size); float draw_TextWidth_WithoutColors(string s, vector size); diff --git a/qcsrc/menu/gamecommand.qc b/qcsrc/menu/gamecommand.qc deleted file mode 100644 index 104c8840e5..0000000000 --- a/qcsrc/menu/gamecommand.qc +++ /dev/null @@ -1,233 +0,0 @@ -void GameCommand_Init() -{ - // make gg call menu QC theCommands - localcmd("alias qc_cmd \"menu_cmd $*\"\n"); -} - -string _dumptree_space; -void _dumptree_open(entity pass, entity me) -{ - string s; - s = me.toString(me); - if(s == "") - s = me.classname; - else - s = strcat(me.classname, ": ", s); - print(_dumptree_space, etos(me), " (", s, ")"); - if(me.firstChild) - { - print(" {\n"); - _dumptree_space = strcat(_dumptree_space, " "); - } - else - print("\n"); -} -void _dumptree_close(entity pass, entity me) -{ - if(me.firstChild) - { - _dumptree_space = substring(_dumptree_space, 0, strlen(_dumptree_space) - 2); - print(_dumptree_space, "}\n"); - } -} - -float curl_uri_get_pos; -float curl_uri_get_exec[URI_GET_CURL_END - URI_GET_CURL + 1]; -string curl_uri_get_cvar[URI_GET_CURL_END - URI_GET_CURL + 1]; -void Curl_URI_Get_Callback(float id, float status, string data) -{ - float i; - float do_exec; - string do_cvar; - i = id - URI_GET_CURL; - do_exec = curl_uri_get_exec[i]; - do_cvar = curl_uri_get_cvar[i]; - if(status != 0) - { - print("error: status is ", ftos(status), "\n"); - return; - } - if(do_exec) - localcmd(data); - if(do_cvar) - cvar_set(do_cvar, data); - if(!do_exec && !do_cvar) - print(data); -} - -void GameCommand(string theCommand) -{ - float argc; - argc = tokenize_console(theCommand); - - if(argv(0) == "help" || argc == 0) - { - print("Usage: menu_cmd theCommand..., where possible theCommands are:\n"); - print(" sync - reloads all cvars on the current menu page\n"); - print(" directmenu ITEM - select a menu item as main item\n"); - GameCommand_Generic("help"); - return; - } - - if(GameCommand_Generic(theCommand)) - return; - - if(argv(0) == "sync") - { - loadAllCvars(main); - return; - } - - if(argv(0) == "directmenu") if(argc == 2) - { - // switch to a menu item - if(!isdemo()) // don't allow this command in demos - m_goto(argv(1)); - return; - } - - if(argv(0) == "directpanelhudmenu") - { - // switch to a menu item - m_goto(strcat("HUD", argv(1))); - return; - } - - if(argv(0) == "skinselect") - { - m_goto_skin_selector(); - return; - } - - if(argv(0) == "videosettings") - { - m_goto_video_settings(); - return; - } - - if(argv(0) == "dumptree") - { - _dumptree_space = ""; - depthfirst(main, parent, firstChild, nextSibling, _dumptree_open, _dumptree_close, NULL); - return; - } - - if(argv(0) == "setresolution") - { - updateConwidths(); - return; - } - - if(argv(0) == "setcompression") - { - updateCompression(); - return; - } - - if(argv(0) == "curl") - { - float do_exec; - string do_cvar; - float key; - float i, j; - string url; - float buf; - float r; - - do_exec = FALSE; - do_cvar = string_null; - key = -1; - - for(i = 1; i+1 < argc; ++i) - { - if(argv(i) == "--cvar" && i+2 < argc) - { - ++i; - do_cvar = argv(i); - continue; - } - if(argv(i) == "--exec") - { - do_exec = TRUE; - continue; - } - if(argv(i) == "--key" && i+2 < argc) - { - ++i; - key = stof(argv(i)); - continue; - } - break; - } - - // now, argv(i) is the URL - // following args may be POST parameters - url = argv(i); - ++i; - buf = buf_create(); - j = 0; - for(; i+1 < argc; i += 2) - bufstr_set(buf, ++j, sprintf("%s=%s", uri_escape(argv(i)), uri_escape(argv(i+1)))); - if(i < argc) - bufstr_set(buf, ++j, sprintf("submit=%s", uri_escape(argv(i)))); - - if(j == 0) // no args: GET - r = crypto_uri_postbuf(url, URI_GET_CURL + curl_uri_get_pos, string_null, string_null, -1, key); - else // with args: POST - r = crypto_uri_postbuf(url, URI_GET_CURL + curl_uri_get_pos, "application/x-www-form-urlencoded", "&", buf, key); - - if(r) - { - curl_uri_get_exec[curl_uri_get_pos] = do_exec; - curl_uri_get_cvar[curl_uri_get_pos] = do_cvar; - curl_uri_get_pos = mod(curl_uri_get_pos + 1, URI_GET_CURL_END - URI_GET_CURL + 1); - } - else - print("error creating curl handle\n"); - - buf_del(buf); - - return; - } - -#if 0 - if(argv(0) == "tokentest") - { - string s; - float i, n; - - print("SANE tokenizer:\n"); - s = cvar_string("tokentest"); - n = tokenize_console_force_builtin(s); - for(i = -n; i < n; ++i) - { - print("token ", ftos(i), ": '", argv(i), "' = "); - print(ftos(argv_start_index(i)), " to ", ftos(argv_end_index(i)), "\n"); - } - print(".\n"); - - print("INSANE tokenizer:\n"); - s = cvar_string("tokentest"); - n = tokenize(s); - for(i = -n; i < n; ++i) - { - print("token ", ftos(i), ": '", argv(i), "' = "); - print(ftos(argv_start_index(i)), " to ", ftos(argv_end_index(i)), "\n"); - } - print(".\n"); - - print("EMULATED tokenizer:\n"); - s = cvar_string("tokentest"); - n = tokenize_console_force_emulation(s); - for(i = -n; i < n; ++i) - { - print("token ", ftos(i), ": '", argv(i), "' = "); - print(ftos(argv_start_index(i)), " to ", ftos(argv_end_index(i)), "\n"); - } - print(".\n"); - return; - } -#endif - - print("Invalid theCommand. For a list of supported theCommands, try menu_cmd help.\n"); -} diff --git a/qcsrc/menu/gamecommand.qh b/qcsrc/menu/gamecommand.qh deleted file mode 100644 index 33eb053714..0000000000 --- a/qcsrc/menu/gamecommand.qh +++ /dev/null @@ -1,2 +0,0 @@ -void GameCommand_Init(); -void GameCommand(string command); diff --git a/qcsrc/menu/item.c b/qcsrc/menu/item.c index 497d1cf661..52b960e456 100644 --- a/qcsrc/menu/item.c +++ b/qcsrc/menu/item.c @@ -42,7 +42,6 @@ void Item_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOr { me.origin = absOrigin; me.size = absSize; - // me.tooltip = "The quick brown fox jumped over the lazy sleeping dog's back then sat on a tack. Franz jagt im komplett verwahrlosten Taxi quer durch Bayern."; } void Item_draw(entity me) diff --git a/qcsrc/menu/item/borderimage.c b/qcsrc/menu/item/borderimage.c index 236b235222..bdeed2bb16 100644 --- a/qcsrc/menu/item/borderimage.c +++ b/qcsrc/menu/item/borderimage.c @@ -57,8 +57,6 @@ void BorderImage_configureBorderImage(entity me, string theTitle, float sz, vect } void BorderImage_draw(entity me) { - //print(vtos(me.borderVec), "\n"); - if(me.src) draw_BorderPicture('0 0 0', me.src, '1 1 0', me.color, 1, me.borderVec); if(me.fontSize > 0) @@ -87,5 +85,5 @@ void BorderImage_draw(entity me) draw_fontscale = df; } } -}; +} #endif diff --git a/qcsrc/menu/item/button.c b/qcsrc/menu/item/button.c index 3d91229ec6..71ca11c7c3 100644 --- a/qcsrc/menu/item/button.c +++ b/qcsrc/menu/item/button.c @@ -8,6 +8,7 @@ CLASS(Button) EXTENDS(Label) METHOD(Button, mousePress, float(entity, vector)) METHOD(Button, mouseDrag, float(entity, vector)) METHOD(Button, mouseRelease, float(entity, vector)) + METHOD(Button, focusEnter, void(entity)) ATTRIB(Button, onClick, void(entity, entity), SUB_Null) ATTRIB(Button, onClickEntity, entity, NULL) ATTRIB(Button, src, string, string_null) @@ -69,8 +70,6 @@ float Button_mouseDrag(entity me, vector pos) float Button_mousePress(entity me, vector pos) { me.mouseDrag(me, pos); // verify coordinates - if(cvar("menu_sounds")) - localsound("sound/misc/menu2.wav"); return 1; } float Button_mouseRelease(entity me, vector pos) @@ -79,7 +78,11 @@ float Button_mouseRelease(entity me, vector pos) if(me.pressed) { if not(me.disabled) + { + if(cvar("menu_sounds")) + localsound("sound/misc/menu2.wav"); me.onClick(me, me.onClickEntity); + } me.pressed = 0; } return 1; @@ -88,7 +91,12 @@ void Button_showNotify(entity me) { me.focusable = !me.disabled; } -.float playedfocus; +void Button_focusEnter(entity me) +{ + if(cvar("menu_sounds") > 1) + localsound("sound/misc/menu1.wav"); + SUPER(Button).focusEnter(me); +} void Button_draw(entity me) { vector bOrigin, bSize; @@ -159,14 +167,5 @@ void Button_draw(entity me) me.onClick(me, me.onClickEntity); } me.clickTime -= frametime; - - if(cvar("menu_sounds") > 1) - if(me.focused && !me.playedfocus) - { - localsound("sound/misc/menu1.wav"); - me.playedfocus = 1; - } - else if(!me.focused && me.playedfocus) - me.playedfocus = 0; } -#endif \ No newline at end of file +#endif diff --git a/qcsrc/menu/item/container.c b/qcsrc/menu/item/container.c index d10e6a486d..5e924a0eeb 100644 --- a/qcsrc/menu/item/container.c +++ b/qcsrc/menu/item/container.c @@ -177,7 +177,7 @@ void Container_draw(entity me) e.draw(e); me.leaveSubitem(me); } -}; +} void Container_focusLeave(entity me) { diff --git a/qcsrc/menu/item/dialog.c b/qcsrc/menu/item/dialog.c index 3d537bfb92..da6a4013ce 100644 --- a/qcsrc/menu/item/dialog.c +++ b/qcsrc/menu/item/dialog.c @@ -78,7 +78,6 @@ void Dialog_fill(entity me) void Dialog_addItemSimple(entity me, float row, float col, float rowspan, float colspan, entity e, vector v) { - //print(vtos(me.itemSpacing), " ", vtos(me.itemSize), "\n"); vector o, s; o = me.itemOrigin + eX * ( col * me.itemSpacing_x) + eY * ( row * me.itemSpacing_y); s = me.itemSize + eX * ((colspan - 1) * me.itemSpacing_x) + eY * ((rowspan - 1) * me.itemSpacing_y); @@ -153,10 +152,10 @@ void Dialog_configureDialog(entity me) me.fill(me); - if(me.closable) + if(me.closable && me.borderLines > 0) { closebutton = me.closeButton = spawnButton(); - closebutton.configureButton(closebutton, "Close", 0, me.closeButtonImage); + closebutton.configureButton(closebutton, "", 0, me.closeButtonImage); closebutton.onClick = Dialog_Close; closebutton.onClickEntity = me; closebutton.srcMulti = 0; me.addItem(me, closebutton, '0 0 0', '1 1 0', 1); // put it as LAST diff --git a/qcsrc/menu/item/gecko.c b/qcsrc/menu/item/gecko.c index 139e87e1a0..a47e5d6b4d 100644 --- a/qcsrc/menu/item/gecko.c +++ b/qcsrc/menu/item/gecko.c @@ -43,10 +43,10 @@ void Gecko_draw(entity me) draw_Picture( '0 0 0', strcat( "/", me.texturePath ), drawSize, '1 1 1', 1.0 ); } else { - local vector fontsize; + vector fontsize; fontsize_x = fontsize_y = 1.0 / 30.0; fontsize_z = 0.0; - draw_Text( '0 0 0', "Browser not initialized!", fontsize, '1 1 1', 1.0, 0 ); + draw_Text( '0 0 0', _("Browser not initialized!"), fontsize, '1 1 1', 1.0, 0 ); } } diff --git a/qcsrc/menu/item/inputbox.c b/qcsrc/menu/item/inputbox.c index 750bc83b89..5b07afd4ee 100644 --- a/qcsrc/menu/item/inputbox.c +++ b/qcsrc/menu/item/inputbox.c @@ -272,35 +272,6 @@ void InputBox_draw(entity me) draw_Text(p, substring(me.text, i, 2), me.realFontSize, '1 1 1', theAlpha, 0); } } - /*else if(ch2 == "a") // ^a found - { - draw_Fill(p, eX * w + eY * me.realFontSize_y, '1 1 1', 0.5); - draw_Text(p, substring(me.text, i, 2), me.realFontSize, theColor, 0.8, 0); - - component = str2chr(me.text, i+2); - if (component >= '0' && component <= '9') - component = component - '0'; - else if (component >= 'a' && component <= 'f') - component = component - 87; - else if (component >= 'A' && component <= 'F') - component = component - 55; - else - component = -1; - - if (component >= 0) // ^ah found - { - // FIX ME: overflow here - if (component == 20 && theVariableAlpha <= 0.97) - theVariableAlpha = theVariableAlpha + 0.0625; - else if (component == 30 && theVariableAlpha >= 0.03) - theVariableAlpha = theVariableAlpha - 0.0625; - else - theVariableAlpha = component*0.0625; - - draw_Fill(p, eX * draw_TextWidth(substring(me.text, i, 3), 0, me.realFontSize) + eY * me.realFontSize_y, '0.8 0.8 0.8', 0.5); - draw_Text(p, strcat(ch, ch2), me.realFontSize, theColor, 0.8, 0); - } - }*/ else { draw_Fill(p, eX * w + eY * me.realFontSize_y, '1 1 1', 0.5); diff --git a/qcsrc/menu/item/label.c b/qcsrc/menu/item/label.c index 7ed6e4f68e..e3a6bee409 100644 --- a/qcsrc/menu/item/label.c +++ b/qcsrc/menu/item/label.c @@ -5,6 +5,7 @@ CLASS(Label) EXTENDS(Item) METHOD(Label, resizeNotify, void(entity, vector, vector, vector, vector)) METHOD(Label, setText, void(entity, string)) METHOD(Label, toString, string(entity)) + METHOD(Label, recalcPosition, void(entity)) ATTRIB(Label, text, string, string_null) ATTRIB(Label, fontSize, float, 8) ATTRIB(Label, align, float, 0.5) @@ -23,6 +24,7 @@ CLASS(Label) EXTENDS(Item) ATTRIB(Label, textEntity, entity, NULL) ATTRIB(Label, allowWrap, float, 0) ATTRIB(Label, recalcPos, float, 0) + ATTRIB(Label, condenseFactor, float, 1) ENDCLASS(Label) #endif @@ -36,6 +38,32 @@ void Label_setText(entity me, string txt) me.text = txt; me.recalcPos = 1; } +void Label_recalcPosition(entity me) +{ + float spaceAvail; + spaceAvail = 1 - me.keepspaceLeft - me.keepspaceRight; + + float spaceUsed; + spaceUsed = draw_TextWidth(me.text, me.allowColors, me.realFontSize); + + if(spaceUsed <= spaceAvail) + { + me.realOrigin_x = me.align * (spaceAvail - spaceUsed) + me.keepspaceLeft; + me.condenseFactor = 1; + } + else if(me.allowCut || me.allowWrap) + { + me.realOrigin_x = me.keepspaceLeft; + me.condenseFactor = 1; + } + else + { + me.realOrigin_x = me.keepspaceLeft; + me.condenseFactor = spaceAvail / spaceUsed; + dprint(sprintf(_("NOTE: label text %s too wide for label, condensed by factor %f\n"), me.text, me.condenseFactor)); + } + me.recalcPos = 0; +} void Label_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize) { SUPER(Label).resizeNotify(me, relOrigin, relSize, absOrigin, absSize); @@ -46,9 +74,42 @@ void Label_resizeNotify(entity me, vector relOrigin, vector relSize, vector absO me.keepspaceLeft = me.marginLeft * me.realFontSize_x; if(me.marginRight) me.keepspaceRight = me.marginRight * me.realFontSize_x; - me.realOrigin_y = 0.5 * (1 - me.realFontSize_y); - me.realOrigin_x = me.align * (1 - me.keepspaceLeft - me.keepspaceRight - min(draw_TextWidth(me.text, me.allowColors, me.realFontSize), (1 - me.keepspaceLeft - me.keepspaceRight))) + me.keepspaceLeft; - me.recalcPos = 0; + + me.recalcPosition(me); + + float lines; + + vector dfs; + vector fs; + + // set up variables to draw in condensed size, but use hinting for original size + fs = me.realFontSize; + fs_x *= me.condenseFactor; + + dfs = draw_fontscale; + draw_fontscale_x *= me.condenseFactor; + + if(me.allowCut) // FIXME allowCut incompatible with align != 0 + lines = 1; + else if(me.allowWrap) // FIXME allowWrap incompatible with align != 0 + { + getWrappedLine_remaining = me.text; + lines = 0; + while(getWrappedLine_remaining) + { + if (me.allowColors) + getWrappedLine((1 - me.keepspaceLeft - me.keepspaceRight), fs, draw_TextWidth_WithColors); + else + getWrappedLine((1 - me.keepspaceLeft - me.keepspaceRight), fs, draw_TextWidth_WithoutColors); + ++lines; + } + } + else + lines = 1; + + draw_fontscale = dfs; + + me.realOrigin_y = 0.5 * (1 - lines * me.realFontSize_y); } void Label_configureLabel(entity me, string txt, float sz, float algn) { @@ -72,17 +133,23 @@ void Label_draw(entity me) t = me.text; if(me.recalcPos) - me.realOrigin_x = me.align * (1 - me.keepspaceLeft - me.keepspaceRight - min(draw_TextWidth(t, me.allowColors, me.realFontSize), (1 - me.keepspaceLeft - me.keepspaceRight))) + me.keepspaceLeft; - me.recalcPos = 0; + me.recalcPosition(me); - //if(me.text == "Bookmark") - // draw_Fill(me.realOrigin, '0 1 0' + '1 0 0' * draw_TextWidth(t, me.allowColors, me.realFontSize), '1 0 1', 1); - if(me.fontSize) if(t) { + vector dfs; + vector fs; + + // set up variables to draw in condensed size, but use hinting for original size + fs = me.realFontSize; + fs_x *= me.condenseFactor; + + dfs = draw_fontscale; + draw_fontscale_x *= me.condenseFactor; + if(me.allowCut) // FIXME allowCut incompatible with align != 0 - draw_Text(me.realOrigin, draw_TextShortenToWidth(t, (1 - me.keepspaceLeft - me.keepspaceRight), me.allowColors, me.realFontSize), me.realFontSize, me.colorL, me.alpha, me.allowColors); + draw_Text(me.realOrigin, draw_TextShortenToWidth(t, (1 - me.keepspaceLeft - me.keepspaceRight), me.allowColors, fs), fs, me.colorL, me.alpha, me.allowColors); else if(me.allowWrap) // FIXME allowWrap incompatible with align != 0 { getWrappedLine_remaining = t; @@ -90,15 +157,17 @@ void Label_draw(entity me) while(getWrappedLine_remaining) { if (me.allowColors) - t = getWrappedLine((1 - me.keepspaceLeft - me.keepspaceRight), me.realFontSize, draw_TextWidth_WithColors); + t = getWrappedLine((1 - me.keepspaceLeft - me.keepspaceRight), fs, draw_TextWidth_WithColors); else - t = getWrappedLine((1 - me.keepspaceLeft - me.keepspaceRight), me.realFontSize, draw_TextWidth_WithoutColors); - draw_Text(o, t, me.realFontSize, me.colorL, me.alpha, me.allowColors); + t = getWrappedLine((1 - me.keepspaceLeft - me.keepspaceRight), fs, draw_TextWidth_WithoutColors); + draw_Text(o, t, fs, me.colorL, me.alpha, me.allowColors); o_y += me.realFontSize_y; } } else - draw_Text(me.realOrigin, t, me.realFontSize, me.colorL, me.alpha, me.allowColors); + draw_Text(me.realOrigin, t, fs, me.colorL, me.alpha, me.allowColors); + + draw_fontscale = dfs; } } #endif diff --git a/qcsrc/menu/item/listbox.c b/qcsrc/menu/item/listbox.c index ba3fa6a9f2..9664e93765 100644 --- a/qcsrc/menu/item/listbox.c +++ b/qcsrc/menu/item/listbox.c @@ -277,6 +277,7 @@ void ListBox_draw(entity me) oldshift = draw_shift; oldscale = draw_scale; absSize = boxToGlobalSize(me.size, eX * (1 - me.controlWidth) + eY * me.itemHeight); + draw_scale = boxToGlobalSize(eX * (1 - me.controlWidth) + eY * me.itemHeight, oldscale); for(i = floor(me.scrollPos / me.itemHeight); i < me.nItems; ++i) { float y; @@ -284,7 +285,6 @@ void ListBox_draw(entity me) if(y >= 1) break; draw_shift = boxToGlobal(eY * y, oldshift, oldscale); - draw_scale = boxToGlobalSize(eY * me.itemHeight + eX * (1 - me.controlWidth), oldscale); me.drawListBoxItem(me, i, absSize, (me.selectedItem == i)); } draw_ClearClip(); @@ -297,6 +297,6 @@ void ListBox_clickListBoxItem(entity me, float i, vector where) void ListBox_drawListBoxItem(entity me, float i, vector absSize, float selected) { - draw_Text('0 0 0', strcat("Item ", ftos(i)), eX * (8 / absSize_x) + eY * (8 / absSize_y), (selected ? '0 1 0' : '1 1 1'), 1, 0); + draw_Text('0 0 0', sprintf(_("Item %d"), i), eX * (8 / absSize_x) + eY * (8 / absSize_y), (selected ? '0 1 0' : '1 1 1'), 1, 0); } #endif diff --git a/qcsrc/menu/item/modalcontroller.c b/qcsrc/menu/item/modalcontroller.c index 82bd6f62b8..4f1ff4e9ed 100644 --- a/qcsrc/menu/item/modalcontroller.c +++ b/qcsrc/menu/item/modalcontroller.c @@ -227,7 +227,7 @@ void ModalController_draw(entity me) else me.setFocus(me, front); SUPER(ModalController).draw(me); -}; +} void ModalController_addTab(entity me, entity other, entity tabButton) { diff --git a/qcsrc/menu/item/nexposee.c b/qcsrc/menu/item/nexposee.c index 2369a41077..02f1224252 100644 --- a/qcsrc/menu/item/nexposee.c +++ b/qcsrc/menu/item/nexposee.c @@ -149,8 +149,6 @@ void Nexposee_draw(entity me) me.animationState = 0; } - //print(ftos(me.animationState), "\n"); - f = min(1, frametime * 5); switch(me.animationState) { @@ -211,7 +209,7 @@ void Nexposee_draw(entity me) } SUPER(Nexposee).draw(me); -}; +} float Nexposee_mousePress(entity me, vector pos) { diff --git a/qcsrc/menu/item/slider.c b/qcsrc/menu/item/slider.c index c8bab9bf80..8861357b77 100644 --- a/qcsrc/menu/item/slider.c +++ b/qcsrc/menu/item/slider.c @@ -10,6 +10,7 @@ CLASS(Slider) EXTENDS(Label) METHOD(Slider, mousePress, float(entity, vector)) METHOD(Slider, mouseDrag, float(entity, vector)) METHOD(Slider, mouseRelease, float(entity, vector)) + METHOD(Slider, focusEnter, void(entity)) METHOD(Slider, valueToText, string(entity, float)) METHOD(Slider, toString, string(entity)) METHOD(Slider, setValue, void(entity, float)) @@ -47,7 +48,6 @@ ENDCLASS(Slider) void Slider_setValue(entity me, float val) { if (me.animated) { - anim.stopObjAnim(anim, me); anim.removeObjAnim(anim, me); makeHostedEasing(me, Slider_setSliderValue, easingQuadInOut, 1, me.sliderValue, val); } else { @@ -61,7 +61,7 @@ void Slider_setSliderValue(entity me, float val) } string Slider_toString(entity me) { - return strcat(ftos(me.value), " (", me.valueToText(me, me.value), ")"); + return sprintf(_("%d (%s)"), me.value, me.valueToText(me, me.value)); } void Slider_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize) { @@ -156,7 +156,7 @@ float Slider_mouseDrag(entity me, vector pos) if(me.disabled) return 0; - anim.finishObjAnim(anim, me); + anim.removeObjAnim(anim, me); animed = me.animated; me.animated = false; @@ -235,8 +235,6 @@ float Slider_mousePress(entity me, vector pos) //me.mouseDrag(me, pos); } } - if(cvar("menu_sounds")) - localsound("sound/misc/menu2.wav"); return 1; } float Slider_mouseRelease(entity me, vector pos) @@ -244,12 +242,20 @@ float Slider_mouseRelease(entity me, vector pos) me.pressed = 0; if(me.disabled) return 0; + if(cvar("menu_sounds")) + localsound("sound/misc/menu2.wav"); return 1; } void Slider_showNotify(entity me) { me.focusable = !me.disabled; } +void Slider_focusEnter(entity me) +{ + if(cvar("menu_sounds") > 1) + localsound("sound/misc/menu1.wav"); + SUPER(Slider).focusEnter(me); +} void Slider_draw(entity me) { float controlLeft; diff --git a/qcsrc/menu/item/textslider.c b/qcsrc/menu/item/textslider.c index c4a7af7a89..028a1603a1 100644 --- a/qcsrc/menu/item/textslider.c +++ b/qcsrc/menu/item/textslider.c @@ -26,9 +26,9 @@ string TextSlider_valueToIdentifier(entity me, float val) string TextSlider_valueToText(entity me, float val) { if(val >= me.nValues) - return "custom"; + return _("custom"); if(val < 0) - return "custom"; + return _("custom"); return me.(valueStrings[val]); } void TextSlider_setValueFromIdentifier(entity me, string id) diff --git a/qcsrc/menu/mbuiltin.qh b/qcsrc/menu/mbuiltin.qh deleted file mode 100644 index 761b63a83b..0000000000 --- a/qcsrc/menu/mbuiltin.qh +++ /dev/null @@ -1,385 +0,0 @@ -////////////////////////////////////////////////// -// common cmd -////////////////////////////////////////////////// -// AK FIXME: Create perhaps a special builtin file for the common cmds - -//#define PROFILESTRZONE -//#define FIXEDFOPEN - -float checkextension(string ext) = #1; - -// error cmds -void error(string err,...) = #2; -void objerror(string err,...) = #3; - -// print - -void print(string text,...) = #4; -void bprint(string text,...) = #5; -void sprint(float clientnum, string text,...) = #6; -void centerprint(string text,...) = #7; - -// vector stuff - -vector normalize(vector v) = #8; -float vlen(vector v) = #9; -float vectoyaw(vector v) = #10; -vector vectoangles(vector v) = #11; - -float random(void) = #12; - -void cmd(string command, ...) = #13; - -// cvar cmds - -float cvar(string name) = #14; -const string cvar_string(string name) = #71; -const string cvar_defstring(string name) = #89; -void cvar_set(string name, string value) = #15; - -void dprint(string text,...) = #16; - -// conversion functions - -string ftos(float f) = #17; -float fabs(float f) = #18; -string vtos(vector v) = #19; -string etos(entity e) = #20; - -float stof(string val,...) = #21; - -entity spawn(void) = #22; -void remove(entity e) = #23; - -entity findstring(entity start, .string _field, string match) = #24; -entity findfloat(entity start, .float _field, float match) = #25; -entity findentity(entity start, .entity _field, entity match) = #25; - -entity findchainstring(.string _field, string match) = #26; -entity findchainfloat(.float _field, float match) = #27; -entity findchainentity(.entity _field, entity match) = #27; - -entity findflags(entity start, .float field, float match) = #87; -entity findchainflags(.float field, float match) = #88; - -string precache_file(string file) = #28; -string precache_sound(string sample) = #29; - -void crash(void) = #72; -void coredump(void) = #30; -void stackdump(void) = #73; -void traceon(void) = #31; -void traceoff(void) = #32; - -void eprint(entity e) = #33; -float rint(float f) = #34; -float floor(float f) = #35; -float ceil(float f) = #36; -entity nextent(entity e) = #37; -float sin(float f) = #38; -float cos(float f) = #39; -float sqrt(float f) = #40; -vector randomvec(void) = #41; - -float registercvar(string name, string value, float flags) = #42; // returns 1 if success -float min(float f,...) = #43; -float (float a, float b, float c) min3 = #43; -float (float a, float b, float c, float d) min4 = #43; -float (float a, float b, float c, float d, float e) min5 = #43; -float (float a, float b, float c, float d, float e, float f) min6 = #43; -float (float a, float b, float c, float d, float e, float f, float g) min7 = #43; -float (float a, float b, float c, float d, float e, float f, float g, float h) min8 = #43; -float max(float f,...) = #44; -float (float a, float b, float c) max3 = #44; -float (float a, float b, float c, float d) max4 = #44; -float (float a, float b, float c, float d, float e) max5 = #44; -float (float a, float b, float c, float d, float e, float f) max6 = #44; -float (float a, float b, float c, float d, float e, float f, float g) max7 = #44; -float (float a, float b, float c, float d, float e, float f, float g, float h) max8 = #44; -float bound(float min,float value, float max) = #45; -float pow(float a, float b) = #46; -void copyentity(entity src, entity dst) = #47; - -#ifdef FIXEDFOPEN -float _fopen( string filename, float mode ) = #48; -#else -float fopen(string filename, float mode) = #48; -#endif -void fclose(float fhandle) = #49; -string fgets(float fhandle) = #50; -void fputs(float fhandle, string s) = #51; - -float strlen(string s) = #52; -//string strcat(string s1,string s2,...) = #53; -string strcat(string s1, ...) = #53; -string substring(string s, float start, float length) = #54; - -vector stov(string s) = #55; - -#ifdef PROFILESTRZONE -string _strzone(string s) = #56; -void _strunzone(string s) = #57; - -string( string s ) strzone = -{ - return _strzone( s ); -}; - -void( string s ) strunzone = -{ - return _strunzone( s ); -}; -#else -string strzone(string s) = #56; -void strunzone(string s) = #57; -#endif - -float tokenize(string s) = #58; -float(string s, string separator1, ...) tokenizebyseparator = #479; -string argv(float n) = #59; - -float isserver(void) = #60; -float clientcount(void) = #61; -float clientstate(void) = #62; -void clientcommand(float client, string s) = #63; -void changelevel(string map) = #64; -void localsound(string sample) = #65; -vector getmousepos(void) = #66; -float gettime(void) = #67; -void loadfromdata(string data) = #68; -void loadfromfile(string file) = #69; - -float mod(float val, float m) = #70; - -float search_begin(string pattern, float caseinsensitive, float quiet) = #74; -void search_end(float handle) = #75; -float search_getsize(float handle) = #76; -string search_getfilename(float handle, float num) = #77; - -string chr(float ascii) = #78; - -float etof(entity ent) = #79; -entity ftoe(float num) = #80; - -float validstring(string str) = #81; - -float altstr_count(string str) = #82; -string altstr_prepare(string str) = #83; -string altstr_get(string str, float num) = #84; -string altstr_set(string str, float num, string set) = #85; -string altstr_ins(string str, float num, string set) = #86; - -float isdemo() = #349; - -///////////////////////////////////////////////// -// Write* Functions -///////////////////////////////////////////////// -void WriteByte(float data, float dest, float desto) = #401; -void WriteChar(float data, float dest, float desto) = #402; -void WriteShort(float data, float dest, float desto) = #403; -void WriteLong(float data, float dest, float desto) = #404; -void WriteAngle(float data, float dest, float desto) = #405; -void WriteCoord(float data, float dest, float desto) = #406; -void WriteString(string data, float dest, float desto)= #407; -void WriteEntity(entity data, float dest, float desto) = #408; - -////////////////////////////////////////////////// -// Draw funtions -////////////////////////////////////////////////// - -float iscachedpic(string name) = #451; -string precache_pic(string name) = #452; -void freepic(string name) = #453; - -float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag) = #454; - -float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag) = #455; -float drawcolorcodedstring(vector position, string text, vector scale, float alpha, float flag) = #467; -float stringwidth(string text, float handleColors, vector size) = #468; - -float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag) = #456; -float drawsubpic(vector position, vector size, string pic, vector srcPosition, vector srcSize, vector rgb, float alpha, float flag) = #469; - -float drawfill(vector position, vector size, vector rgb, float alpha, float flag) = #457; - -void drawsetcliparea(float x, float y, float width, float height) = #458; - -void drawresetcliparea(void) = #459; - -vector drawgetimagesize(string pic) = #460; - -float cin_open(string file, string name) = #461; -void cin_close(string name) = #462; -void cin_setstate(string name, float type) = #463; -float cin_getstate(string name) = #464; - -//////////////////////////////////////////////// -// Menu functions -//////////////////////////////////////////////// - -void setkeydest(float dest) = #601; -float getkeydest(void) = #602; - -void setmousetarget(float trg) = #603; -float getmousetarget(void) = #604; - -float isfunction(string function_name) = #607; -void callfunction(...) = #605; -void writetofile(float fhandle, entity ent) = #606; -vector getresolution(float number, ...) = #608; // optional argument "isfullscreen" -string keynumtostring(float keynum) = #609; -string findkeysforcommand(string command) = #610; - -float gethostcachevalue(float type) = #611; -string gethostcachestring(float type, float hostnr) = #612; - -void parseentitydata(entity ent, string data) = #613; - -float stringtokeynum(string key) = #614; - -void resethostcachemasks(void) = #615; -void sethostcachemaskstring(float mask, float fld, string str, float op) = #616; -void sethostcachemasknumber(float mask, float fld, float num, float op) = #617; -void resorthostcache(void) = #618; -void sethostcachesort(float fld, float descending) = #619; -void refreshhostcache(void) = #620; -float gethostcachenumber(float fld, float hostnr) = #621; -float gethostcacheindexforkey(string key) = #622; -void addwantedhostcachekey(string key) = #623; -string getextresponse(void) = #624; - -// AK the builtin numbers may change - the code might be removed again -float gecko_create( string name ) = #487; -void gecko_destroy( string name ) = #488; -void gecko_navigate( string name, string URI ) = #489; -float gecko_keyevent( string name, float key, float eventtype ) = #490; -void gecko_mousemove( string name, float x, float y ) = #491; -void gecko_resize( string name, float w, float h ) = #492; -vector gecko_get_texture_extent( string name ) = #493; - -//FTE_STRINGS -//idea: many -//darkplaces implementation: KrimZon -//description: -//various string manipulation functions -float(string str, string sub, float startpos) strstrofs = #221; -float(string str, float ofs) str2chr = #222; -string(float c, ...) chr2str = #223; -string(float ccase, float calpha, float cnum, string s, ...) strconv = #224; -string(float chars, string s, ...) strpad = #225; -string(string info, string key, string value, ...) infoadd = #226; -string(string info, string key) infoget = #227; -float(string s1, string s2, float len) strncmp = #228; -float(string s1, string s2) strcasecmp = #229; -float(string s1, string s2, float len) strncasecmp = #230; - -string(string s) strdecolorize = #477; - -//DP_QC_STRINGBUFFERS -//idea: ?? -//darkplaces implementation: LordHavoc -//functions to manage string buffer objects - that is, arbitrary length string arrays that are handled by the engine -float() buf_create = #440; -void(float bufhandle) buf_del = #441; -float(float bufhandle) buf_getsize = #442; -void(float bufhandle_from, float bufhandle_to) buf_copy = #443; -void(float bufhandle, float sortpower, float backward) buf_sort = #444; -string(float bufhandle, string glue) buf_implode = #445; -string(float bufhandle, float string_index) bufstr_get = #446; -void(float bufhandle, float string_index, string str) bufstr_set = #447; -float(float bufhandle, string str, float order) bufstr_add = #448; -void(float bufhandle, float string_index) bufstr_free = #449; -void(float bufhandle, string pattern, string antipattern) buf_cvarlist = #517; -string(string name) cvar_description = #518; - -//DP_QC_CRC16 -//idea: div0 -//darkplaces implementation: div0 -//Some hash function to build hash tables with. This has to be be the CRC-16-CCITT that is also required for the QuakeWorld download protocol. -//When caseinsensitive is set, the CRC is calculated of the lower cased string. -float(float caseinsensitive, string s, ...) crc16 = #494; - -//DP_QC_CVAR_TYPE -float(string name) cvar_type = #495; -float CVAR_TYPEFLAG_EXISTS = 1; -float CVAR_TYPEFLAG_SAVED = 2; -float CVAR_TYPEFLAG_PRIVATE = 4; -float CVAR_TYPEFLAG_ENGINE = 8; -float CVAR_TYPEFLAG_HASDESCRIPTION = 16; -float CVAR_TYPEFLAG_READONLY = 32; - -//DP_QC_URI_ESCAPE -//idea: div0 -//darkplaces implementation: div0 -//URI::Escape's functionality -string(string in) uri_escape = #510; -string(string in) uri_unescape = #511; - -//DP_QC_URI_GET -//idea: divVerent -//darkplaces implementation: divVerent -//loads text from an URL into a string -//returns 1 on success of initiation, 0 if there are too many concurrent -//connections already or if the URL is invalid -//the following callback will receive the data and MUST exist! -// void(float id, float status, string data) URI_Get_Callback; -//status is either -// negative for an internal error, -// 0 for success, or -// the HTTP response code on server error (e.g. 404) -//if 1 is returned by uri_get, the callback will be called in the future -float(string url, float id) uri_get = #513; -//DP_QC_URI_POST -//idea: divVerent -//darkplaces implementation: divVerent -//loads text from an URL into a string after POSTing via HTTP -//works like uri_get, but uri_post sends data with Content-Type: content_type to the server -//and uri_post sends the string buffer buf, joined using the delimiter delim -float(string url, float id, string content_type, string data) uri_post = #513; -float(string url, float id, string content_type, string delim, float buf) uri_postbuf = #513; - -string(string, float) netaddress_resolve = #625; -string(string search, string replace, string subject) strreplace = #484; - -string(float uselocaltime, string format, ...) strftime = #478; - -#ifdef FIXEDFOPEN -float fopen( string filename, float mode ) = -{ - local float handle; - if( mode == FILE_READ ) { - return _fopen( filename, mode ); - } - - // check for data/ - filename = strzone( filename ); - if( substring( filename, 0, 5 ) != "data/" ) { - print( "menu: fopen: all output must go into data/!\n" ); - return -1; - } - handle = _fopen( substring( filename, 5, 10000 ), mode ); - strunzone( filename ); - return handle; -}; -#endif - -float(string s) tokenize_console = #514; -float(float i) argv_start_index = #515; -float(float i) argv_end_index = #516; - -string(float, float) getgamedirinfo = #626; -#define GETGAMEDIRINFO_NAME 0 -#define GETGAMEDIRINFO_DESCRIPTION 1 -float log(float f) = #532; - -string(string format, ...) sprintf = #627; - -//DP_CRYPTO -//idea: divVerent -//darkplaces implementation: divVerent -//field definitions: (MENUQC) -string crypto_getkeyfp(string serveraddress) = #633; // retrieves the cached host key's CA fingerprint of a server given by IP address -string crypto_getidfp(string serveraddress) = #634; // retrieves the cached host key fingerprint of a server given by IP address -string crypto_getencryptlevel(string serveraddress) = #635; // 0 if never encrypting, 1 supported, 2 requested, 3 required, appended by list of allowed methods in order of preference ("AES128"), preceded by a space each -float(string url, float id, string content_type, string delim, float buf, float keyid) crypto_uri_postbuf = #513; -//description: diff --git a/qcsrc/menu/menu.qc b/qcsrc/menu/menu.qc index 7bec34ea0b..536295fc2f 100644 --- a/qcsrc/menu/menu.qc +++ b/qcsrc/menu/menu.qc @@ -16,16 +16,25 @@ float menuInitialized; float menuNotTheFirstFrame; float menuMouseMode; -void SUB_Null() { }; +void SUB_Null() { } -void() m_init = +void m_sync() +{ + updateCompression(); + updateConwidths(); + + loadAllCvars(main); +} + +void m_init() { cvar_set("_menu_alpha", "0"); + prvm_language = strzone(cvar_string("prvm_language")); check_unacceptable_compiler_bugs(); #ifdef WATERMARK - print("^4MQC Build information: ", WATERMARK(), "\n"); + print(sprintf(_("^4MQC Build information: ^1%s\n"), WATERMARK())); #endif // list all game dirs (TEST) @@ -38,9 +47,13 @@ void() m_init = s = getgamedirinfo(i, GETGAMEDIRINFO_NAME); if not(s) break; - print(s, ": ", getgamedirinfo(i, GETGAMEDIRINFO_DESCRIPTION)); + dprint(s, ": ", getgamedirinfo(i, GETGAMEDIRINFO_DESCRIPTION)); } } + + // needs to be done so early because of the constants they create + RegisterWeapons(); + RegisterGametypes(); } float MENU_ASPECT = 1.25; // 1280x1024 @@ -94,7 +107,7 @@ void UpdateConWidthHeight() } } -void() m_init_delayed = +void m_init_delayed() { float fh, glob, n, i; string s; @@ -107,26 +120,28 @@ void() m_init_delayed = if(!preMenuInit()) return; menuInitialized = 1; - GameCommand_Init(); - - RegisterWeapons(); fh = -1; if(cvar_string("menu_skin") != "") { draw_currentSkin = strcat("gfx/menu/", cvar_string("menu_skin")); - fh = fopen(strcat(draw_currentSkin, "/skinvalues.txt"), FILE_READ); + fh = fopen(language_filename(strcat(draw_currentSkin, "/skinvalues.txt")), FILE_READ); } if(fh < 0) if(cvar_defstring("menu_skin") != "") { - draw_currentSkin = strcat("gfx/menu/", cvar_defstring("menu_skin")); - fh = fopen(strcat(draw_currentSkin, "/skinvalues.txt"), FILE_READ); + cvar_set("menu_skin", cvar_defstring("menu_skin")); + draw_currentSkin = strcat("gfx/menu/", cvar_string("menu_skin")); + fh = fopen(language_filename(strcat(draw_currentSkin, "/skinvalues.txt")), FILE_READ); } if(fh < 0) { draw_currentSkin = "gfx/menu/default"; - fh = fopen(strcat(draw_currentSkin, "/skinvalues.txt"), FILE_READ); + fh = fopen(language_filename(strcat(draw_currentSkin, "/skinvalues.txt")), FILE_READ); + } + if(fh < 0) + { + error("cannot load any menu skin\n"); } draw_currentSkin = strzone(draw_currentSkin); while((s = fgets(fh))) @@ -163,11 +178,13 @@ void() m_init_delayed = menuShiftState = 0; menuMousePos = '0.5 0.5 0'; + m_sync(); + if(Menu_Active) m_display(); // delayed menu display -}; +} -void(float key, float ascii) m_keyup = +void m_keyup (float key, float ascii) { if(!menuInitialized) return; @@ -183,15 +200,15 @@ void(float key, float ascii) m_keyup = if(mouseButtonsPressed < 0) { mouseButtonsPressed = 0; - print("Warning: released an already released button\n"); + dprint("Warning: released an already released button\n"); } } if(key == K_ALT) menuShiftState -= (menuShiftState & S_ALT); if(key == K_CTRL) menuShiftState -= (menuShiftState & S_CTRL); if(key == K_SHIFT) menuShiftState -= (menuShiftState & S_SHIFT); -}; +} -void(float key, float ascii) m_keydown = +void m_keydown(float key, float ascii) { if(!menuInitialized) return; @@ -221,13 +238,13 @@ void(float key, float ascii) m_keydown = if(mouseButtonsPressed > 10) { mouseButtonsPressed = 10; - print("Warning: pressed an already pressed button\n"); + dprint("Warning: pressed an already pressed button\n"); } } if(key == K_ALT) menuShiftState |= S_ALT; if(key == K_CTRL) menuShiftState |= S_CTRL; if(key == K_SHIFT) menuShiftState |= S_SHIFT; -}; +} float SCALEMODE_CROP = 0; float SCALEMODE_LETTERBOX = 1; @@ -241,8 +258,8 @@ void draw_Picture_Aligned(vector algn, float scalemode, string img, float a) sz = draw_PictureSize(img); width_is_larger = (sz_x * draw_scale_y >= sz_y * draw_scale_x); - isz_w = '1 0 0' + '0 1 0' * ((sz_y / sz_x) * (draw_scale_x / draw_scale_y)); - isz_h = '0 1 0' + '1 0 0' * ((sz_x / sz_y) * (draw_scale_y / draw_scale_x)); + isz_w = '1 0 0' + '0 1 0' * ((sz_y / sz_x) * (draw_scale_x / draw_scale_y)); + isz_h = '0 1 0' + '1 0 0' * ((sz_x / sz_y) * (draw_scale_y / draw_scale_x)); switch(scalemode) { @@ -268,7 +285,7 @@ void draw_Picture_Aligned(vector algn, float scalemode, string img, float a) draw_Picture(org, img, isz, '1 1 1', a); } -void(string img, float a, string algn, float force1) drawBackground = +void drawBackground(string img, float a, string algn, float force1) { if(main.mainNexposee.ModalController_state == 0) return; @@ -318,12 +335,15 @@ void(string img, float a, string algn, float force1) drawBackground = } } +float menu_tooltips; +float menu_tooltips_old; vector menuTooltipAveragedMousePos; entity menuTooltipItem; vector menuTooltipOrigin; vector menuTooltipSize; float menuTooltipAlpha; -float menuTooltipState; // 0: no tooltip, 1: fading in, 2: displaying, 3: fading out +string menuTooltipText; +float menuTooltipState; // 0: static, 1: fading in, 2: fading out float m_testmousetooltipbox(vector pos) { if(pos_x >= menuTooltipOrigin_x && pos_x < menuTooltipOrigin_x + menuTooltipSize_x) @@ -341,11 +361,6 @@ float m_testtooltipbox(vector tooltippos) return FALSE; if(tooltippos_y + menuTooltipSize_y > 1) return FALSE; - /* - menuTooltipOrigin_x = rint(tooltippos_x * cvar("vid_width")) / cvar("vid_width"); - menuTooltipOrigin_y = rint(tooltippos_y * cvar("vid_height")) / cvar("vid_height"); - menuTooltipOrigin_z = 0; - */ menuTooltipOrigin = tooltippos; return TRUE; } @@ -354,12 +369,12 @@ float m_allocatetooltipbox(vector pos) vector avoidplus, avoidminus; vector v; - avoidplus_x = (SKINAVOID_TOOLTIP_x + SKINSIZE_CURSOR_x - SKINOFFSET_CURSOR_x) / conwidth; - avoidplus_y = (SKINAVOID_TOOLTIP_y + SKINSIZE_CURSOR_y - SKINOFFSET_CURSOR_y) / conheight; + avoidplus_x = (SKINAVOID_TOOLTIP_x + SKINSIZE_CURSOR_x - SKINOFFSET_CURSOR_x * SKINSIZE_CURSOR_x) / conwidth; + avoidplus_y = (SKINAVOID_TOOLTIP_y + SKINSIZE_CURSOR_y - SKINOFFSET_CURSOR_y * SKINSIZE_CURSOR_y) / conheight; avoidplus_z = 0; - avoidminus_x = (SKINAVOID_TOOLTIP_x + SKINOFFSET_CURSOR_x) / conwidth + menuTooltipSize_x; - avoidminus_y = (SKINAVOID_TOOLTIP_y + SKINOFFSET_CURSOR_y) / conheight + menuTooltipSize_y; + avoidminus_x = (SKINAVOID_TOOLTIP_x + SKINOFFSET_CURSOR_x * SKINSIZE_CURSOR_x) / conwidth + menuTooltipSize_x; + avoidminus_y = (SKINAVOID_TOOLTIP_y + SKINOFFSET_CURSOR_y * SKINSIZE_CURSOR_y) / conheight + menuTooltipSize_y; avoidminus_z = 0; // bottom right @@ -414,6 +429,8 @@ entity m_findtooltipitem(entity root, vector pos) it = it.itemFromPoint(it, pos); if(it.tooltip) best = it; + else if(menu_tooltips == 2 && (it.cvarName || it.onClickCommand)) + best = it; it = world; } else if(it.instanceOfModalController) @@ -424,11 +441,35 @@ entity m_findtooltipitem(entity root, vector pos) break; if(it.tooltip) best = it; + else if(menu_tooltips == 2 && (it.cvarName || it.onClickCommand)) + best = it; pos = globalToBox(pos, it.Container_origin, it.Container_size); } return best; } +string gettooltip() +{ + if (menu_tooltips == 2) + { + string s; + if (menuTooltipItem.cvarName) + { + if (getCvarsMulti(menuTooltipItem)) + s = strcat("[", menuTooltipItem.cvarName, " ", getCvarsMulti(menuTooltipItem), "]"); + else + s = strcat("[", menuTooltipItem.cvarName, "]"); + } + else if (menuTooltipItem.onClickCommand) + s = strcat("<", menuTooltipItem.onClickCommand, ">"); + else + return menuTooltipItem.tooltip; + if (menuTooltipItem.tooltip) + return strcat(menuTooltipItem.tooltip, " ", s); + return s; + } + return menuTooltipItem.tooltip; +} void m_tooltip(vector pos) { float f, i, w; @@ -436,16 +477,26 @@ void m_tooltip(vector pos) vector fontsize, p; string s; - fontsize = '1 0 0' * (SKINFONTSIZE_TOOLTIP / conwidth) + '0 1 0' * (SKINFONTSIZE_TOOLTIP / conheight); - - f = bound(0, frametime * 2, 1); - menuTooltipAveragedMousePos = menuTooltipAveragedMousePos * (1 - f) + pos * f; - f = vlen(pos - menuTooltipAveragedMousePos); - - if(f < 0.01) - it = m_findtooltipitem(main, pos); - else + menu_tooltips = cvar("menu_tooltips"); + if (!menu_tooltips) + { + // don't return immediately, fade out the active tooltip first + if (menuTooltipItem == world) + return; it = world; + menu_tooltips_old = menu_tooltips; + } + else + { + f = bound(0, frametime * 2, 1); + menuTooltipAveragedMousePos = menuTooltipAveragedMousePos * (1 - f) + pos * f; + f = vlen(pos - menuTooltipAveragedMousePos); + if(f < 0.01) + it = m_findtooltipitem(main, pos); + else + it = world; + } + fontsize = '1 0 0' * (SKINFONTSIZE_TOOLTIP / conwidth) + '0 1 0' * (SKINFONTSIZE_TOOLTIP / conheight); // float menuTooltipState; // 0: static, 1: fading in, 2: fading out if(it != menuTooltipItem) @@ -465,9 +516,14 @@ void m_tooltip(vector pos) menuTooltipItem = it; menuTooltipOrigin_x = -1; // unallocated + + if (menuTooltipText) + strunzone(menuTooltipText); + menuTooltipText = strzone(gettooltip()); + i = 0; - w = 0; - getWrappedLine_remaining = it.tooltip; + w = 0; + getWrappedLine_remaining = menuTooltipText; while(getWrappedLine_remaining) { s = getWrappedLine(SKINWIDTH_TOOLTIP, fontsize, draw_TextWidth_WithoutColors); @@ -514,9 +570,24 @@ void m_tooltip(vector pos) break; } - if(menuTooltipItem) + if(menuTooltipItem == world) { - if(menuTooltipOrigin_x < 0) // unallocated? + if (menuTooltipText) + { + strunzone(menuTooltipText); + menuTooltipText = string_null; + } + return; + } + else + { + if(menu_tooltips != menu_tooltips_old) + { + if (menu_tooltips != 0 && menu_tooltips_old != 0) + menuTooltipItem = world; // reload tooltip next frame + menu_tooltips_old = menu_tooltips; + } + else if(menuTooltipOrigin_x < 0) // unallocated? m_allocatetooltipbox(pos); if(menuTooltipOrigin_x >= 0) @@ -529,7 +600,7 @@ void m_tooltip(vector pos) p = menuTooltipOrigin; p_x += SKINMARGIN_TOOLTIP_x / conwidth; p_y += SKINMARGIN_TOOLTIP_y / conheight; - getWrappedLine_remaining = menuTooltipItem.tooltip; + getWrappedLine_remaining = menuTooltipText; while(getWrappedLine_remaining) { s = getWrappedLine(SKINWIDTH_TOOLTIP, fontsize, draw_TextWidth_WithoutColors); @@ -540,7 +611,7 @@ void m_tooltip(vector pos) } } -void() m_draw = +void m_draw() { float t; float realFrametime; @@ -565,9 +636,11 @@ void() m_draw = if(Menu_Active) if(!cvar("menu_video_played")) { - localcmd("set menu_video_played 1; cd loop $menu_cdtrack; play sound/announcer/default/welcome.ogg\n"); - menuLogoAlpha = -0.8; // no idea why, but when I start this at zero, it jumps instead of fading + localcmd("cd loop $menu_cdtrack; play sound/announcer/default/welcome.ogg\n"); + menuLogoAlpha = -0.8; // no idea why, but when I start this at zero, it jumps instead of fading FIXME } + // ALWAYS set this cvar; if we start but menu is not active, this means we want no background music! + localcmd("set menu_video_played 1\n"); } t = gettime(); @@ -715,9 +788,9 @@ void() m_draw = postMenuDraw(); frametime = 0; -}; +} -void() m_display = +void m_display() { Menu_Active = true; setkeydest(KEY_MENU); @@ -732,9 +805,9 @@ void() m_display = main.focusEnter(main); main.showNotify(main); -}; +} -void() m_hide = +void m_hide() { Menu_Active = false; setkeydest(KEY_GAME); @@ -745,17 +818,25 @@ void() m_hide = main.focusLeave(main); main.hideNotify(main); -}; +} -void() m_toggle = +void m_toggle(float mode) { if(Menu_Active) + { + if (mode == 1) + return; m_hide(); + } else + { + if (mode == 0) + return; m_display(); -}; + } +} -void() m_shutdown = +void Shutdown() { entity e; @@ -766,7 +847,7 @@ void() m_shutdown = if(e.destroy) e.destroy(e); } -}; +} void m_focus_item_chain(entity outermost, entity innermost) { @@ -822,7 +903,7 @@ void m_setpointerfocus(entity wnd) } } -void(string itemname) m_goto = +void m_goto(string itemname) { entity e; if(!menuInitialized) @@ -839,7 +920,9 @@ void(string itemname) m_goto = } else { - e = findstring(NULL, name, itemname); + for(e = NULL; (e = find(e, name, itemname)); ) + if(e.classname != "vtbl") + break; if(e) { m_hide(); @@ -850,7 +933,7 @@ void(string itemname) m_goto = } } -void() m_goto_skin_selector = +void m_goto_skin_selector() { if(!menuInitialized) return; @@ -858,10 +941,18 @@ void() m_goto_skin_selector = m_goto("skinselector"); } -void() m_goto_video_settings = +void m_goto_language_selector() { if(!menuInitialized) return; - // TODO add code to switch back to the skin selector (no idea how to do it now) + // TODO add code to switch back to the language selector (no idea how to do it now) + m_goto("languageselector"); +} + +void m_goto_video_settings() +{ + if(!menuInitialized) + return; + // TODO add code to switch back to the video settings (no idea how to do it now) m_goto("videosettings"); } diff --git a/qcsrc/menu/menu.qh b/qcsrc/menu/menu.qh index 903700d5d5..ab812437a0 100644 --- a/qcsrc/menu/menu.qh +++ b/qcsrc/menu/menu.qh @@ -27,6 +27,7 @@ void m_hide(); void m_display(); void m_goto(string name); void m_goto_skin_selector(); +void m_goto_language_selector(); void m_goto_video_settings(); .string name; @@ -40,3 +41,5 @@ void SUB_Null(); float preMenuInit(); // you have to define this for pre-menu initialization. Return 0 if initialization needs to be retried a frame later, 1 if it succeeded. void preMenuDraw(); // this is run before the menu is drawn. You may put some stuff there that has to be done every frame. void postMenuDraw(); // this is run just after the menu is drawn (or not). Useful to draw something over everything else. + +void m_sync(); diff --git a/qcsrc/menu/msys.qh b/qcsrc/menu/msys.qh deleted file mode 100644 index f2fa30e743..0000000000 --- a/qcsrc/menu/msys.qh +++ /dev/null @@ -1,173 +0,0 @@ -#pragma flag off fastarrays // make dp behave with new fteqcc versions. remove when dp bug with fteqcc fastarrays is fixed - -////////////////////////////////////////////////////////// -// sys globals - -entity self; - -///////////////////////////////////////////////////////// -void end_sys_globals; -///////////////////////////////////////////////////////// -// sys fields - -///////////////////////////////////////////////////////// -void end_sys_fields; -///////////////////////////////////////////////////////// -// sys functions - -void() m_init; -void(float keynr, float ascii) m_keydown; -void() m_draw; -void() m_display; // old NG Menu -void() m_toggle; -void() m_hide; // old NG Menu -void() m_shutdown; - -///////////////////////////////////////////////////////// -// sys constants - -/////////////////////////// -// key dest constants - -float KEY_UNKNOWN = -1; -float KEY_GAME = 0; -float KEY_MENU = 2; -float KEY_MENU_GRABBED = 3; - -/////////////////////////// -// file constants - -float FILE_READ = 0; -float FILE_APPEND = 1; -float FILE_WRITE = 2; - -/////////////////////////// -// logical constants (just for completeness) - -float TRUE = 1; -float FALSE = 0; - -/////////////////////////// -// boolean constants - -float true = 1; -float false = 0; - -/////////////////////////// -// msg constants - -float MSG_BROADCAST = 0; // unreliable to all -float MSG_ONE = 1; // reliable to one (msg_entity) -float MSG_ALL = 2; // reliable to all -float MSG_INIT = 3; // write to the init string - -///////////////////////////// -// mouse target constants - -float MT_MENU = 1; -float MT_CLIENT = 2; - -///////////////////////// -// client state constants - -float CS_DEDICATED = 0; -float CS_DISCONNECTED = 1; -float CS_CONNECTED = 2; - -/////////////////////////// -// blend flags - -float DRAWFLAG_NORMAL = 0; -float DRAWFLAG_ADDITIVE = 1; -float DRAWFLAG_MODULATE = 2; -float DRAWFLAG_2XMODULATE = 3; - - -/////////////////////////// -// server list constants - -float SLIST_HOSTCACHEVIEWCOUNT = 0; -float SLIST_HOSTCACHETOTALCOUNT = 1; -float SLIST_MASTERQUERYCOUNT = 2; -float SLIST_MASTERREPLYCOUNT = 3; -float SLIST_SERVERQUERYCOUNT = 4; -float SLIST_SERVERREPLYCOUNT = 5; -float SLIST_SORTFIELD = 6; -float SLIST_SORTDESCENDING = 7; - -float SLIST_LEGACY_LINE1 = 1024; -float SLIST_LEGACY_LINE2 = 1025; - -float SLIST_TEST_CONTAINS = 0; -float SLIST_TEST_NOTCONTAIN = 1; -float SLIST_TEST_LESSEQUAL = 2; -float SLIST_TEST_LESS = 3; -float SLIST_TEST_EQUAL = 4; -float SLIST_TEST_GREATER = 5; -float SLIST_TEST_GREATEREQUAL = 6; -float SLIST_TEST_NOTEQUAL = 7; -float SLIST_TEST_STARTSWITH = 8; -float SLIST_TEST_NOTSTARTSWITH = 9; - -float SLIST_MASK_AND = 0; -float SLIST_MASK_OR = 512; - -float NET_CURRENTPROTOCOL = 3; - -//////////////////////////////// -// cinematic action constants - -float CINE_PLAY = 1; -float CINE_LOOP = 2; -float CINE_PAUSE = 3; -float CINE_FIRSTFRAME = 4; -float CINE_RESETONWAKEUP= 5; - -/////////////////////////// -// null entity (actually it is the same like the world entity) - -entity null_entity; - -/////////////////////////// -// error constants - -// file handling -float ERR_CANNOTOPEN = -1; // fopen -float ERR_NOTENOUGHFILEHANDLES = -2; // fopen -float ERR_INVALIDMODE = -3; // fopen -float ERR_BADFILENAME = -4; // fopen - -// drawing functions - -float ERR_NULLSTRING = -1; -float ERR_BADDRAWFLAG = -2; -float ERR_BADSCALE = -3; -//float ERR_BADSIZE = ERR_BADSCALE; -float ERR_NOTCACHED = -4; - -float GECKO_BUTTON_DOWN = 0; -float GECKO_BUTTON_UP = 1; -// either use down and up or just press but not all of them! -float GECKO_BUTTON_PRESS = 2; -// use this for mouse events if needed? -float GECKO_BUTTON_DOUBLECLICK = 3; - -/* not supported at the moment -/////////////////////////// -// os constants - -float OS_WINDOWS = 0; -float OS_LINUX = 1; -float OS_MAC = 2; -*/ - -float drawfont; // set this to one of the following for draw text routines to work with another font -float FONT_DEFAULT = 0; -float FONT_CONSOLE = 1; -float FONT_SBAR = 2; -float FONT_NOTIFY = 3; -float FONT_CHAT = 4; -float FONT_CENTERPRINT = 5; -float FONT_INFOBAR = 6; -float FONT_MENU = 7; -float FONT_USER = 8; // add to this the index, like FONT_USER+3 = user3. At least 8 of them are supported. diff --git a/qcsrc/menu/oo/base.h b/qcsrc/menu/oo/base.h index 3553d447a8..ed4eba5a12 100644 --- a/qcsrc/menu/oo/base.h +++ b/qcsrc/menu/oo/base.h @@ -2,6 +2,7 @@ entity Object_vtbl; .string vtblname; .entity vtblbase; +// THIS LINE INTENTIONALLY LEFT BLANK entity spawnVtbl(entity e, entity b) { entity v; diff --git a/qcsrc/menu/oo/classdefs.h b/qcsrc/menu/oo/classdefs.h deleted file mode 100644 index 85bc6c2afa..0000000000 --- a/qcsrc/menu/oo/classdefs.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef INTERFACE -#define INTERFACE -#endif - -#ifdef IMPLEMENTATION -#undef IMPLEMENTATION -#endif - -#ifdef CLASS -#undef CLASS -#undef EXTENDS -#undef METHOD -#undef ATTRIB -#undef ATTRIBARRAY -#undef ENDCLASS -#undef SUPER -#endif - -#define CLASS(cname) entity spawn##cname(); entity cname##_vtbl; -#define EXTENDS(base) -#define METHOD(cname,name,prototype) prototype cname##_##name; .prototype name; -#define ATTRIB(cname,name,type,val) .type name; -#define ATTRIBARRAY(cname,name,type,cnt) .type name[cnt]; -#define ENDCLASS(cname) .float instanceOf##cname; -#define SUPER(cname) diff --git a/qcsrc/menu/oo/constructors.h b/qcsrc/menu/oo/constructors.h deleted file mode 100644 index 4e758dd472..0000000000 --- a/qcsrc/menu/oo/constructors.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef INTERFACE -#define INTERFACE -#endif - -#ifdef IMPLEMENTATION -#undef IMPLEMENTATION -#endif - -#ifdef CLASS -#undef CLASS -#undef EXTENDS -#undef METHOD -#undef ATTRIB -#undef ATTRIBARRAY -#undef ENDCLASS -#undef SUPER -#endif - -#define CLASS(cname) entity spawn##cname() { entity me; -#define EXTENDS(base) me = spawn##base (); entity basevtbl; basevtbl = base##_vtbl; -#define METHOD(cname,name,prototype) me.name = cname##_##name; -#define ATTRIB(cname,name,type,val) me.name = val; -#define ATTRIBARRAY(cname,name,type,cnt) me.name = me.name; -#define ENDCLASS(cname) me.instanceOf##cname = 1; me.classname = #cname; if(!cname##_vtbl) cname##_vtbl = spawnVtbl(me, basevtbl); return me; } -#define SUPER(cname) diff --git a/qcsrc/menu/oo/implementation.h b/qcsrc/menu/oo/implementation.h index ed6bd71f36..34f32e306a 100644 --- a/qcsrc/menu/oo/implementation.h +++ b/qcsrc/menu/oo/implementation.h @@ -1,5 +1,5 @@ -#ifdef INTERFACE -#undef INTERFACE +#ifndef INTERFACE +#define INTERFACE #endif #ifndef IMPLEMENTATION @@ -16,4 +16,13 @@ #undef SUPER #endif +// for the constructor +#define CLASS(cname) entity spawn##cname() { entity me; +#define EXTENDS(base) me = spawn##base (); entity basevtbl; basevtbl = base##_vtbl; +#define METHOD(cname,name,prototype) me.name = cname##_##name; +#define ATTRIB(cname,name,type,val) me.name = val; +#define ATTRIBARRAY(cname,name,type,cnt) me.name = me.name; +#define ENDCLASS(cname) me.instanceOf##cname = 1; me.classname = #cname; if(!cname##_vtbl) cname##_vtbl = spawnVtbl(me, basevtbl); return me; } + +// for the implementation #define SUPER(cname) (cname##_vtbl.vtblbase) diff --git a/qcsrc/menu/oo/interface.h b/qcsrc/menu/oo/interface.h new file mode 100644 index 0000000000..85bc6c2afa --- /dev/null +++ b/qcsrc/menu/oo/interface.h @@ -0,0 +1,25 @@ +#ifndef INTERFACE +#define INTERFACE +#endif + +#ifdef IMPLEMENTATION +#undef IMPLEMENTATION +#endif + +#ifdef CLASS +#undef CLASS +#undef EXTENDS +#undef METHOD +#undef ATTRIB +#undef ATTRIBARRAY +#undef ENDCLASS +#undef SUPER +#endif + +#define CLASS(cname) entity spawn##cname(); entity cname##_vtbl; +#define EXTENDS(base) +#define METHOD(cname,name,prototype) prototype cname##_##name; .prototype name; +#define ATTRIB(cname,name,type,val) .type name; +#define ATTRIBARRAY(cname,name,type,cnt) .type name[cnt]; +#define ENDCLASS(cname) .float instanceOf##cname; +#define SUPER(cname) diff --git a/qcsrc/menu/progs.src b/qcsrc/menu/progs.src index 254a9238bb..1f70e0e7be 100644 --- a/qcsrc/menu/progs.src +++ b/qcsrc/menu/progs.src @@ -1,9 +1,11 @@ ../../menu.dat +../dpdefs/menudefs.qc +../dpdefs/keycodes.qc + config.qh ../common/util-pre.qh -msys.qh -mbuiltin.qh + ../warpzonelib/mathlib.qh ../common/util.qh @@ -13,24 +15,27 @@ oo/base.h ../common/mapinfo.qh ../common/campaign_common.qh ../common/items.qh +../common/command/markup.qh +../common/command/rpn.qh +../common/command/generic.qh +../common/command/shared_defs.qh -gamecommand.qh +command/menu_cmd.qh menu.qh draw.qh skin.qh xonotic/util.qh -oo/classdefs.h - classes.c - -oo/constructors.h +oo/interface.h classes.c oo/implementation.h classes.c ../common/util.qc -../common/gamecommand.qc -gamecommand.qc +../common/command/markup.qc +../common/command/rpn.qc +../common/command/generic.qc +command/menu_cmd.qc menu.qc draw.qc xonotic/util.qc @@ -41,3 +46,5 @@ xonotic/util.qc ../common/items.qc ../warpzonelib/mathlib.qc + +../common/if-this-file-errors-scroll-up-and-fix-the-warnings.fteqccfail diff --git a/qcsrc/menu/skin-customizables.inc b/qcsrc/menu/skin-customizables.inc index afea3e752f..e8cfba3689 100644 --- a/qcsrc/menu/skin-customizables.inc +++ b/qcsrc/menu/skin-customizables.inc @@ -6,7 +6,7 @@ print "\n"; while(<DATA>) { chomp; - if(/^\s*(?:SKINFLOAT|SKINVECTOR)\(([A-Z_]+), ([-'0-9. ]+)\);$/) + if(/^\s*(?:SKINFLOAT|SKINVECTOR)\(([A-Z_]+), ([-'0-9. ]+)\);$/) #' { printf "%-31s %s\n", $1, $2; } @@ -51,9 +51,11 @@ SKINBEGIN SKINVECTOR(AVOID_TOOLTIP, '8 8 0'); // the individual dialog background colors + SKINVECTOR(COLOR_DIALOG_FIRSTRUN, '0.7 0.7 1'); SKINVECTOR(COLOR_DIALOG_MULTIPLAYER, '0.7 0.7 1'); SKINVECTOR(COLOR_DIALOG_SETTINGS, '0.7 0.7 1'); SKINVECTOR(COLOR_DIALOG_TEAMSELECT, '1 1 1'); + SKINVECTOR(COLOR_DIALOG_SANDBOXTOOLS, '1 1 1'); SKINVECTOR(COLOR_DIALOG_QUIT, '1 0 0'); SKINVECTOR(COLOR_DIALOG_ADVANCED, '0.7 0.7 1'); SKINVECTOR(COLOR_DIALOG_MUTATORS, '0.7 0.7 1'); @@ -62,7 +64,7 @@ SKINBEGIN SKINVECTOR(COLOR_DIALOG_SINGLEPLAYER, '1 1 0.7'); SKINVECTOR(COLOR_DIALOG_CREDITS, '0.7 0.7 1'); SKINVECTOR(COLOR_DIALOG_WEAPONS, '1 0.7 0.7'); - SKINVECTOR(COLOR_DIALOG_RADAR, '0.7 0.7 1'); + SKINVECTOR(COLOR_DIALOG_WAYPOINTS, '0.7 0.7 1'); SKINVECTOR(COLOR_DIALOG_SERVERINFO, '0.7 0.7 1'); SKINVECTOR(COLOR_DIALOG_CVARS, '1 0 0'); @@ -101,6 +103,7 @@ SKINBEGIN SKINVECTOR(COLOR_BUTTON_C, '1 1 1'); SKINVECTOR(COLOR_BUTTON_F, '1 1 1'); SKINVECTOR(COLOR_BUTTON_D, '1 1 1'); + SKINFLOAT(MARGIN_BUTTON, 0.5); // item: campaign SKINFLOAT(ALPHA_CAMPAIGN_SELECTABLE, 0.8); diff --git a/qcsrc/menu/skin.qh b/qcsrc/menu/skin.qh index 20da37d24e..437c49bf72 100644 --- a/qcsrc/menu/skin.qh +++ b/qcsrc/menu/skin.qh @@ -17,7 +17,7 @@ //#define SKINSTRING(name,def) case #name: break #define SKINSTRING(name,def) case #name: SKIN##name = strzone(value); break // I know this leaks memory when skin is read multiple times. Screw it. -#define SKINEND case "": break; case "//": break; default: print("Invalid key in skin file: ", key, "\n"); } } +#define SKINEND case "": break; case "//": break; default: dprint("Invalid key in skin file: ", key, "\n"); } } #include "skin-customizables.inc" #undef SKINEND #undef SKINSTRING diff --git a/qcsrc/menu/xonotic/button.c b/qcsrc/menu/xonotic/button.c index 5522905bc2..cbc7c47c40 100644 --- a/qcsrc/menu/xonotic/button.c +++ b/qcsrc/menu/xonotic/button.c @@ -10,6 +10,8 @@ CLASS(XonoticButton) EXTENDS(Button) ATTRIB(XonoticButton, colorD, vector, SKINCOLOR_BUTTON_D) ATTRIB(XonoticButton, alpha, float, SKINALPHA_TEXT) ATTRIB(XonoticButton, disabledAlpha, float, SKINALPHA_DISABLED) + ATTRIB(XonoticButton, marginLeft, float, SKINMARGIN_BUTTON) // chars + ATTRIB(XonoticButton, marginRight, float, SKINMARGIN_BUTTON) // chars ENDCLASS(XonoticButton) entity makeXonoticButton(string theText, vector theColor); #endif diff --git a/qcsrc/menu/xonotic/campaign.c b/qcsrc/menu/xonotic/campaign.c index e7667f69cf..0537967bd6 100644 --- a/qcsrc/menu/xonotic/campaign.c +++ b/qcsrc/menu/xonotic/campaign.c @@ -275,14 +275,18 @@ void XonoticCampaignList_drawListBoxItem(entity me, float i, vector absSize, flo draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED); s = ftos(p); - draw_Picture(me.columnPreviewOrigin * eX, strcat("/maps/", campaign_mapname[i]), me.columnPreviewSize * eX + eY, '1 1 1', theAlpha); + if(draw_PictureSize(strcat("/maps/", campaign_mapname[i])) == '0 0 0') + draw_Picture(me.columnPreviewOrigin * eX, "nopreview_map", me.columnPreviewSize * eX + eY, '1 1 1', theAlpha); + else + draw_Picture(me.columnPreviewOrigin * eX, strcat("/maps/", campaign_mapname[i]), me.columnPreviewSize * eX + eY, '1 1 1', theAlpha); + if(i < me.campaignIndex) draw_Picture(me.checkMarkOrigin, "checkmark", me.checkMarkSize, '1 1 1', 1); if(i <= me.campaignIndex) s = campaign_shortdesc[i]; // fteqcc sucks else - s = "???"; - s = draw_TextShortenToWidth(strcat("Level ", ftos(i + 1), ": ", s), me.columnNameSize, 0, me.realFontSize); + s = _("???"); + s = draw_TextShortenToWidth(sprintf(_("Level %d: %s"), 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) diff --git a/qcsrc/menu/xonotic/checkbox_slider_invalid.c b/qcsrc/menu/xonotic/checkbox_slider_invalid.c index a9d2becc3d..c5500394bd 100644 --- a/qcsrc/menu/xonotic/checkbox_slider_invalid.c +++ b/qcsrc/menu/xonotic/checkbox_slider_invalid.c @@ -42,6 +42,7 @@ void XonoticSliderCheckBox_configureXonoticSliderCheckBox(entity me, float theOf me.controlledSlider = theControlledSlider; me.configureCheckBox(me, theText, me.fontSize, me.image); me.tooltip = theControlledSlider.tooltip; + me.cvarName = theControlledSlider.cvarName; // in case we want to display the cvar in the tooltip } void XonoticSliderCheckBox_draw(entity me) { diff --git a/qcsrc/menu/xonotic/colorbutton.c b/qcsrc/menu/xonotic/colorbutton.c index 2ca8c86c40..4e81a4acc2 100644 --- a/qcsrc/menu/xonotic/colorbutton.c +++ b/qcsrc/menu/xonotic/colorbutton.c @@ -28,6 +28,27 @@ entity makeXonoticColorButton(float theGroup, float theColor, float theValue) } void XonoticColorButton_configureXonoticColorButton(entity me, float theGroup, float theColor, float theValue) { + switch(theValue) + { + // rearrange 1..14 for rainbow order + case 1: theValue = 10; break; + case 2: theValue = 4; break; + case 3: theValue = 1; break; + case 4: theValue = 14; break; + case 5: theValue = 12; break; + case 6: theValue = 7; break; + case 7: theValue = 3; break; + case 8: theValue = 2; break; + case 9: theValue = 6; break; + case 10: theValue = 5; break; + case 11: theValue = 13; break; + case 12: theValue = 11; break; + case 13: theValue = 8; break; + case 14: theValue = 9; break; + default: + // no change + break; + } me.cvarName = "_cl_color"; me.cvarValueFloat = theValue; me.cvarPart = theColor; diff --git a/qcsrc/menu/xonotic/credits.c b/qcsrc/menu/xonotic/credits.c index 86609a6598..0d998d7de9 100644 --- a/qcsrc/menu/xonotic/credits.c +++ b/qcsrc/menu/xonotic/credits.c @@ -30,7 +30,7 @@ void XonoticCreditsList_configureXonoticCreditsList(entity me) { me.configureXonoticListBox(me); // load the file - me.bufferIndex = buf_load("xonotic-credits.txt"); + me.bufferIndex = buf_load(language_filename("xonotic-credits.txt")); me.nItems = buf_getsize(me.bufferIndex); } void XonoticCreditsList_destroy(entity me) diff --git a/qcsrc/menu/xonotic/crosshairbutton.c b/qcsrc/menu/xonotic/crosshairbutton.c index 434a7bc87f..9456cd66da 100644 --- a/qcsrc/menu/xonotic/crosshairbutton.c +++ b/qcsrc/menu/xonotic/crosshairbutton.c @@ -34,7 +34,7 @@ void XonoticCrosshairButton_configureXonoticCrosshairButton(entity me, float the me.configureRadioButton(me, string_null, me.fontSize, me.image, theGroup, 0); me.srcMulti = 1; if(me.cvarValueFloat == -1) - me.src3 = strzone(strcat("/gfx/crosshair", cvar("crosshair"))); + me.src3 = strzone(strcat("/gfx/crosshair", cvar_string("crosshair"))); else me.src3 = strzone(strcat("/gfx/crosshair", ftos(me.cvarValueFloat))); me.src4 = "/gfx/crosshairdot"; @@ -69,12 +69,20 @@ void XonoticCrosshairButton_draw(entity me) vector sz, rgb; float a; - rgb = stov(cvar_string("crosshair_color")); - a = cvar("crosshair_alpha"); - if(!me.checked && !me.focused && me.cvarValueFloat != -1) + if(me.cvarValueFloat == -1) + { + rgb = stov(cvar_string("crosshair_color")); + a = cvar("crosshair_alpha"); + } + else if(me.checked || me.focused) + { + a = 1; + rgb = '1 1 1'; + } + else { - a *= me.disabledAlpha; + a = me.disabledAlpha; rgb = '1 1 1'; } @@ -90,17 +98,23 @@ void XonoticCrosshairButton_draw(entity me) SUPER(XonoticCrosshairButton).draw(me); sz = draw_PictureSize(me.src3); - sz = globalToBoxSize(sz, draw_scale); + sz = globalToBoxSize(sz, me.size); if(me.cvarValueFloat == -1) { - sz = (6 * '1 1 0' + sz * cvar("crosshair_size")) * 0.08; // (6 * '1 1 0' + ...) * 0.08 here to make visible size changes happen also at bigger sizes + sz = sz * cvar("crosshair_size"); // (6 * '1 1 0' + ...) * 0.08 here to make visible size changes happen also at bigger sizes + /* if(sz_x > 0.95) sz = sz * (0.95 / sz_x); if(sz_y > 0.95) sz = sz * (0.95 / sz_y); + */ } else // show the crosshair picker at full size - sz = '0.95 0.95 0'; + { + sz = sz * (0.95 / sz_x); + if(sz_y > 0.95) + sz = sz * (0.95 / sz_y); + } draw_Picture('0.5 0.5 0' - 0.5 * sz, me.src3, sz, rgb, a); if(cvar("crosshair_dot")) diff --git a/qcsrc/menu/xonotic/cvarlist.c b/qcsrc/menu/xonotic/cvarlist.c index 3eaf2677e9..03898a3f8b 100644 --- a/qcsrc/menu/xonotic/cvarlist.c +++ b/qcsrc/menu/xonotic/cvarlist.c @@ -35,6 +35,7 @@ entity makeXonoticCvarList(); void CvarList_Filter_Change(entity box, entity me); void CvarList_Value_Change(entity box, entity me); void CvarList_Revert_Click(entity btn, entity me); +void CvarList_End_Editing(entity box, entity me); #endif #ifdef IMPLEMENTATION @@ -81,15 +82,15 @@ void XonoticCvarList_setSelected(entity me, float i) t = cvar_type(me.cvarName); me.cvarType = ""; if(t & CVAR_TYPEFLAG_SAVED) - me.cvarType = strcat(me.cvarType, ", will be saved to config.cfg"); + me.cvarType = strcat(me.cvarType, ", ", _("will be saved to config.cfg")); else - me.cvarType = strcat(me.cvarType, ", will not be saved"); + me.cvarType = strcat(me.cvarType, ", ", _("will not be saved")); if(t & CVAR_TYPEFLAG_PRIVATE) - me.cvarType = strcat(me.cvarType, ", private"); + me.cvarType = strcat(me.cvarType, ", ", _("private")); if(t & CVAR_TYPEFLAG_ENGINE) - me.cvarType = strcat(me.cvarType, ", engine setting"); + me.cvarType = strcat(me.cvarType, ", ", _("engine setting")); if(t & CVAR_TYPEFLAG_READONLY) - me.cvarType = strcat(me.cvarType, ", read only"); + me.cvarType = strcat(me.cvarType, ", ", _("read only")); me.cvarType = strzone(substring(me.cvarType, 2, strlen(me.cvarType) - 2)); me.cvarNameBox.setText(me.cvarNameBox, me.cvarName); @@ -192,4 +193,9 @@ void CvarList_Revert_Click(entity btn, entity me) me.cvarValueBox.cursorPos = strlen(me.cvarDefault); } +void CvarList_End_Editing(entity box, entity me) +{ + box.parent.setFocus(box.parent, me); +} + #endif diff --git a/qcsrc/menu/xonotic/dialog.c b/qcsrc/menu/xonotic/dialog.c index 7087d83cb9..f18658c715 100644 --- a/qcsrc/menu/xonotic/dialog.c +++ b/qcsrc/menu/xonotic/dialog.c @@ -3,7 +3,7 @@ CLASS(XonoticDialog) EXTENDS(Dialog) // still to be customized by user /* ATTRIB(XonoticDialog, closable, float, 1) - ATTRIB(XonoticDialog, title, string, "Form1") // ;) + ATTRIB(XonoticDialog, title, string, _("Form1")) // ;) ATTRIB(XonoticDialog, color, vector, '1 0.5 1') ATTRIB(XonoticDialog, intendedWidth, float, 0) ATTRIB(XonoticDialog, rows, float, 3) diff --git a/qcsrc/menu/xonotic/dialog_credits.c b/qcsrc/menu/xonotic/dialog_credits.c index 07c2fc4f29..e90ae4b425 100644 --- a/qcsrc/menu/xonotic/dialog_credits.c +++ b/qcsrc/menu/xonotic/dialog_credits.c @@ -2,7 +2,7 @@ CLASS(XonoticCreditsDialog) EXTENDS(XonoticDialog) METHOD(XonoticCreditsDialog, fill, void(entity)) METHOD(XonoticCreditsDialog, focusEnter, void(entity)) - ATTRIB(XonoticCreditsDialog, title, string, "Credits") + ATTRIB(XonoticCreditsDialog, title, string, _("Credits")) ATTRIB(XonoticCreditsDialog, color, vector, SKINCOLOR_DIALOG_CREDITS) ATTRIB(XonoticCreditsDialog, intendedWidth, float, SKINWIDTH_CREDITS) ATTRIB(XonoticCreditsDialog, rows, float, SKINROWS_CREDITS) @@ -18,7 +18,7 @@ void XonoticCreditsDialog_fill(entity me) me.TR(me); me.TD(me, me.rows - 1, me.columns, me.creditsList = makeXonoticCreditsList()); me.gotoRC(me, me.rows - 1, 0); - me.TD(me, 1, me.columns, e = makeXonoticButton("OK", '0 0 0')); + me.TD(me, 1, me.columns, e = makeXonoticButton(_("OK"), '0 0 0')); e.onClick = Dialog_Close; e.onClickEntity = me; } diff --git a/qcsrc/menu/xonotic/dialog_firstrun.c b/qcsrc/menu/xonotic/dialog_firstrun.c new file mode 100644 index 0000000000..6568a7198f --- /dev/null +++ b/qcsrc/menu/xonotic/dialog_firstrun.c @@ -0,0 +1,72 @@ +#ifdef INTERFACE +CLASS(XonoticFirstRunDialog) EXTENDS(XonoticRootDialog) + METHOD(XonoticFirstRunDialog, fill, void(entity)) // to be overridden by user to fill the dialog with controls + ATTRIB(XonoticFirstRunDialog, title, string, _("Welcome")) + ATTRIB(XonoticFirstRunDialog, color, vector, SKINCOLOR_DIALOG_FIRSTRUN) + ATTRIB(XonoticFirstRunDialog, intendedWidth, float, 0.6) + ATTRIB(XonoticFirstRunDialog, rows, float, 15) + ATTRIB(XonoticFirstRunDialog, columns, float, 3) + ATTRIB(XonoticFirstRunDialog, name, string, "FirstRun") + ATTRIB(XonoticFirstRunDialog, playerNameLabel, entity, NULL) + ATTRIB(XonoticFirstRunDialog, playerNameLabelAlpha, float, 0) + + ATTRIB(XonoticFirstRunDialog, closable, float, 0) +ENDCLASS(XonoticFirstRunDialog) +#endif + +#ifdef IMPLEMENTATION +float CheckFirstRunButton(entity me) +{ + if(cvar_string("_cl_name") != "Player") + return 1; + if(cvar_string("prvm_language") != prvm_language) + return 1; // OK will then reopen the dialog in another language + return 0; +} + +void XonoticFirstRunDialog_fill(entity me) +{ + entity e; + entity label, box; + + me.TR(me); + me.TD(me, 2, 3, e = makeXonoticTextLabel(0, _("Welcome to Xonotic, please select your language preference and enter your player name to get started. You can change these options later through the menu system."))); + e.allowWrap = 1; + me.TR(me); + + me.TR(me); + me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Text language:"))); + me.TR(me); + me.TD(me, 3, 3, e = makeXonoticLanguageList()); + e.name = "languageselector_firstrun"; + e.doubleClickCommand = "saveconfig; menu_restart; togglemenu"; + me.TR(me); + me.TR(me); + + me.TR(me); + me.TD(me, 1, 0.5, me.playerNameLabel = makeXonoticTextLabel(0, _("Name:"))); + me.playerNameLabelAlpha = me.playerNameLabel.alpha; + me.TD(me, 1, 2.5, label = makeXonoticTextLabel(0, string_null)); + label.allowCut = 1; + label.allowColors = 1; + label.alpha = 1; + me.TR(me); + me.TD(me, 1, 3.0, box = makeXonoticInputBox(1, "_cl_name")); + box.forbiddenCharacters = "\r\n\\\"$"; // don't care, isn't getting saved + box.maxLength = -127; // negative means encoded length in bytes + box.saveImmediately = 1; + label.textEntity = box; + me.TR(me); + me.TD(me, 5, 1, e = makeXonoticColorpicker(box)); + me.TD(me, 5, 2, e = makeXonoticCharmap(box)); + me.TR(me); + me.TR(me); + me.TR(me); + me.TR(me); + + // because of the language selector, this is a menu_restart! + me.gotoRC(me, me.rows - 1, 0); + me.TD(me, 1, me.columns, e = makeXonoticCommandButton(_("Save settings"), '0 0 0', "saveconfig; menu_restart; togglemenu", COMMANDBUTTON_APPLY)); + setDependentWeird(e, CheckFirstRunButton); +} +#endif diff --git a/qcsrc/menu/xonotic/dialog_hudpanel_ammo.c b/qcsrc/menu/xonotic/dialog_hudpanel_ammo.c index 256dbe7df0..0725769643 100644 --- a/qcsrc/menu/xonotic/dialog_hudpanel_ammo.c +++ b/qcsrc/menu/xonotic/dialog_hudpanel_ammo.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticHUDAmmoDialog) EXTENDS(XonoticRootDialog) METHOD(XonoticHUDAmmoDialog, fill, void(entity)) - ATTRIB(XonoticHUDAmmoDialog, title, string, "Ammo Panel") + ATTRIB(XonoticHUDAmmoDialog, title, string, _("Ammo Panel")) ATTRIB(XonoticHUDAmmoDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT) ATTRIB(XonoticHUDAmmoDialog, intendedWidth, float, 0.4) ATTRIB(XonoticHUDAmmoDialog, rows, float, 15) @@ -15,71 +15,18 @@ void XonoticHUDAmmoDialog_fill(entity me) { entity e; string panelname = "ammo"; - float i; + + DIALOG_HUDPANEL_COMMON(); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_ammo", "Enable panel")); - me.TR(me); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "Background:")); - me.TD(me, 1, 1.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - e.addValue(e, strzone(strcat("border_", panelname)), strzone(strcat("border_", panelname))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Color:")); - me.TD(me, 2, 2.4, e = makeXonoticColorpickerString(strzone(strcat("hud_panel_", panelname, "_bg_color")), "hud_panel_bg_color")); - setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_bg_color")), ""); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticCheckBoxString("", "1 1 1", strzone(strcat("hud_panel_", panelname, "_bg_color")), "Use default")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Border size:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_border")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i * 2, 0)), strzone(ftos(i * 2))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Alpha:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_alpha")))); - e.addValue(e, "Default", ""); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Team Color:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_color_team")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.4); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_configure_teamcolorforced", "Test the team color in HUD configure mode")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Padding:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_padding")))); - e.addValue(e, "Default", ""); - for(i = 0; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i - 5, 0)), strzone(ftos(i - 5))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TD(me, 1, 2, e = makeXonoticTextLabel(0, "Ammunition display:")); + me.TD(me, 1, 4, e = makeXonoticTextLabel(0, _("Ammunition display:"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "hud_panel_ammo_onlycurrent", "Show only current ammo type")); + me.TD(me, 1, 3.8, e = makeXonoticCheckBox(0, "hud_panel_ammo_onlycurrent", _("Show only current ammo type"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "Align icon:")); - me.TD(me, 1, 0.8, e = makeXonoticRadioButton(2, "hud_panel_ammo_iconalign", "0", "Left")); - me.TD(me, 1, 0.8, e = makeXonoticRadioButton(2, "hud_panel_ammo_iconalign", "1", "Right")); + me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, _("Align icon:"))); + me.TD(me, 1, 2.4/2, e = makeXonoticRadioButton(2, "hud_panel_ammo_iconalign", "0", _("Left"))); + me.TD(me, 1, 2.4/2, e = makeXonoticRadioButton(2, "hud_panel_ammo_iconalign", "1", _("Right"))); } #endif diff --git a/qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c b/qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c new file mode 100644 index 0000000000..9628783b14 --- /dev/null +++ b/qcsrc/menu/xonotic/dialog_hudpanel_centerprint.c @@ -0,0 +1,44 @@ +#ifdef INTERFACE +CLASS(XonoticHUDCenterprintDialog) EXTENDS(XonoticRootDialog) + METHOD(XonoticHUDCenterprintDialog, fill, void(entity)) + ATTRIB(XonoticHUDCenterprintDialog, title, string, _("Centerprint")) + ATTRIB(XonoticHUDCenterprintDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT) + ATTRIB(XonoticHUDCenterprintDialog, intendedWidth, float, 0.4) + ATTRIB(XonoticHUDCenterprintDialog, rows, float, 15) + ATTRIB(XonoticHUDCenterprintDialog, columns, float, 4) + ATTRIB(XonoticHUDCenterprintDialog, name, string, "HUDcenterprint") +ENDCLASS(XonoticHUDCenterprintDialog) +#endif + +#ifdef IMPLEMENTATION +void XonoticHUDCenterprintDialog_fill(entity me) +{ + entity e; + string panelname = "centerprint"; + + DIALOG_HUDPANEL_COMMON(); + + me.TR(me); + me.TDempty(me, 0.2); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Message duration:"))); + me.TD(me, 1, 2.6, e = makeXonoticSlider(1, 10, 1, "hud_panel_centerprint_time")); + me.TR(me); + me.TDempty(me, 0.2); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Fade time:"))); + me.TD(me, 1, 2.6, e = makeXonoticSlider(0, 1, 0.05, "hud_panel_centerprint_fadetime")); + me.TR(me); + me.TDempty(me, 0.2); + me.TD(me, 1, 3.8, e = makeXonoticCheckBox(0, "hud_panel_centerprint_flip", _("Flip messages order"))); + me.TR(me); + me.TD(me, 1, 4, e = makeXonoticTextLabel(0, _("Text alignment:"))); + me.TR(me); + me.TDempty(me, 0.2); + me.TD(me, 1, 3.8/3, e = makeXonoticRadioButton(3, "hud_panel_centerprint_align", "0", _("Left"))); + me.TD(me, 1, 3.8/3, e = makeXonoticRadioButton(3, "hud_panel_centerprint_align", "0.5", _("Center"))); + me.TD(me, 1, 3.8/3, e = makeXonoticRadioButton(3, "hud_panel_centerprint_align", "1", _("Right"))); + me.TR(me); + me.TDempty(me, 0.2); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Font scale:"))); + me.TD(me, 1, 2.6, e = makeXonoticSlider(0.5, 2, 0.1, "hud_panel_centerprint_fontscale")); +} +#endif diff --git a/qcsrc/menu/xonotic/dialog_hudpanel_chat.c b/qcsrc/menu/xonotic/dialog_hudpanel_chat.c index c9a4eae6e8..ba3f0d0090 100644 --- a/qcsrc/menu/xonotic/dialog_hudpanel_chat.c +++ b/qcsrc/menu/xonotic/dialog_hudpanel_chat.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticHUDChatDialog) EXTENDS(XonoticRootDialog) METHOD(XonoticHUDChatDialog, fill, void(entity)) - ATTRIB(XonoticHUDChatDialog, title, string, "Chat Panel") + ATTRIB(XonoticHUDChatDialog, title, string, _("Chat Panel")) ATTRIB(XonoticHUDChatDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT) ATTRIB(XonoticHUDChatDialog, intendedWidth, float, 0.4) ATTRIB(XonoticHUDChatDialog, rows, float, 15) @@ -15,74 +15,21 @@ void XonoticHUDChatDialog_fill(entity me) { entity e; string panelname = "chat"; - float i; + + DIALOG_HUDPANEL_COMMON(); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_chat", "Enable panel")); - me.TR(me); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "Background:")); - me.TD(me, 1, 1.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - e.addValue(e, strzone(strcat("border_", panelname)), strzone(strcat("border_", panelname))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Color:")); - me.TD(me, 2, 2.4, e = makeXonoticColorpickerString(strzone(strcat("hud_panel_", panelname, "_bg_color")), "hud_panel_bg_color")); - setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_bg_color")), ""); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticCheckBoxString("", "1 1 1", strzone(strcat("hud_panel_", panelname, "_bg_color")), "Use default")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Border size:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_border")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i * 2, 0)), strzone(ftos(i * 2))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Alpha:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_alpha")))); - e.addValue(e, "Default", ""); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Team Color:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_color_team")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.4); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_configure_teamcolorforced", "Test the team color in HUD configure mode")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Padding:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_padding")))); - e.addValue(e, "Default", ""); - for(i = 0; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i - 5, 0)), strzone(ftos(i - 5))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TD(me, 1, 2, e = makeXonoticTextLabel(0, "Chat entries:")); + me.TD(me, 1, 2, e = makeXonoticTextLabel(0, _("Chat entries:"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Chat size:")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Chat size:"))); me.TD(me, 1, 2.6, e = makeXonoticSlider(6, 20, 1, "con_chatsize")); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Chat lifetime:")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Chat lifetime:"))); me.TD(me, 1, 2.6, e = makeXonoticSlider(5, 60, 5, "con_chattime")); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "con_chatsound", "Chat beep sound")); + me.TD(me, 1, 3.8, e = makeXonoticCheckBox(0, "con_chatsound", _("Chat beep sound"))); } #endif diff --git a/qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c b/qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c index 03ef106c7d..b3cc7b423a 100644 --- a/qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c +++ b/qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticHUDEngineInfoDialog) EXTENDS(XonoticRootDialog) METHOD(XonoticHUDEngineInfoDialog, fill, void(entity)) - ATTRIB(XonoticHUDEngineInfoDialog, title, string, "Engine Info Panel") + ATTRIB(XonoticHUDEngineInfoDialog, title, string, _("Engine Info Panel")) ATTRIB(XonoticHUDEngineInfoDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT) ATTRIB(XonoticHUDEngineInfoDialog, intendedWidth, float, 0.4) ATTRIB(XonoticHUDEngineInfoDialog, rows, float, 15) @@ -15,66 +15,13 @@ void XonoticHUDEngineInfoDialog_fill(entity me) { entity e; string panelname = "engineinfo"; - float i; + + DIALOG_HUDPANEL_COMMON(); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_engineinfo", "Enable panel")); - me.TR(me); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "Background:")); - me.TD(me, 1, 1.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - e.addValue(e, strzone(strcat("border_", panelname)), strzone(strcat("border_", panelname))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Color:")); - me.TD(me, 2, 2.4, e = makeXonoticColorpickerString(strzone(strcat("hud_panel_", panelname, "_bg_color")), "hud_panel_bg_color")); - setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_bg_color")), ""); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticCheckBoxString("", "1 1 1", strzone(strcat("hud_panel_", panelname, "_bg_color")), "Use default")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Border size:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_border")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i * 2, 0)), strzone(ftos(i * 2))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Alpha:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_alpha")))); - e.addValue(e, "Default", ""); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Team Color:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_color_team")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.4); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_configure_teamcolorforced", "Test the team color in HUD configure mode")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Padding:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_padding")))); - e.addValue(e, "Default", ""); - for(i = 0; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i - 5, 0)), strzone(ftos(i - 5))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TD(me, 1, 2, e = makeXonoticTextLabel(0, "Engine info:")); + me.TD(me, 1, 4, e = makeXonoticTextLabel(0, _("Engine info:"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_engineinfo_framecounter_exponentialmovingaverage", "Use an averaging algorithm for fps")); + me.TD(me, 1, 3.8, e = makeXonoticCheckBox(0, "hud_panel_engineinfo_framecounter_exponentialmovingaverage", _("Use an averaging algorithm for fps"))); } #endif diff --git a/qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c b/qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c index 3e8a43aeb3..5eaf1d9405 100644 --- a/qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c +++ b/qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticHUDHealthArmorDialog) EXTENDS(XonoticRootDialog) METHOD(XonoticHUDHealthArmorDialog, fill, void(entity)) - ATTRIB(XonoticHUDHealthArmorDialog, title, string, "Health/Armor Panel") + ATTRIB(XonoticHUDHealthArmorDialog, title, string, _("Health/Armor Panel")) ATTRIB(XonoticHUDHealthArmorDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT) ATTRIB(XonoticHUDHealthArmorDialog, intendedWidth, float, 0.4) ATTRIB(XonoticHUDHealthArmorDialog, rows, float, 15) @@ -15,86 +15,33 @@ void XonoticHUDHealthArmorDialog_fill(entity me) { entity e; string panelname = "healtharmor"; - float i; + + DIALOG_HUDPANEL_COMMON(); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_healtharmor", "Enable panel")); - me.TR(me); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "Background:")); - me.TD(me, 1, 1.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - e.addValue(e, strzone(strcat("border_", panelname)), strzone(strcat("border_", panelname))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Color:")); - me.TD(me, 2, 2.4, e = makeXonoticColorpickerString(strzone(strcat("hud_panel_", panelname, "_bg_color")), "hud_panel_bg_color")); - setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_bg_color")), ""); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticCheckBoxString("", "1 1 1", strzone(strcat("hud_panel_", panelname, "_bg_color")), "Use default")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Border size:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_border")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i * 2, 0)), strzone(ftos(i * 2))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Alpha:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_alpha")))); - e.addValue(e, "Default", ""); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Team Color:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_color_team")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.4); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_configure_teamcolorforced", "Test the team color in HUD configure mode")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Padding:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_padding")))); - e.addValue(e, "Default", ""); - for(i = 0; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i - 5, 0)), strzone(ftos(i - 5))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_healtharmor_progressbar", "Enable status bar")); + me.TD(me, 1, 4, e = makeXonoticCheckBox(0, "hud_panel_healtharmor_progressbar", _("Enable status bar"))); me.TR(me); - me.TD(me, 1, 2, e = makeXonoticTextLabel(0, "Status bar alignment:")); + me.TD(me, 1, 4, e = makeXonoticTextLabel(0, _("Status bar alignment:"))); setDependent(e, "hud_panel_healtharmor_progressbar", 1, 1); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 0.95, e = makeXonoticRadioButton(2, "hud_panel_healtharmor_baralign", "0", "Left")); + me.TD(me, 1, 0.95, e = makeXonoticRadioButton(2, "hud_panel_healtharmor_baralign", "0", _("Left"))); setDependent(e, "hud_panel_healtharmor_progressbar", 1, 1); - me.TD(me, 1, 0.95, e = makeXonoticRadioButton(2, "hud_panel_healtharmor_baralign", "1", "Right")); + me.TD(me, 1, 0.95, e = makeXonoticRadioButton(2, "hud_panel_healtharmor_baralign", "1", _("Right"))); setDependent(e, "hud_panel_healtharmor_progressbar", 1, 1); - me.TD(me, 1, 0.95, e = makeXonoticRadioButton(2, "hud_panel_healtharmor_baralign", "3", "Inward")); + me.TD(me, 1, 0.95, e = makeXonoticRadioButton(2, "hud_panel_healtharmor_baralign", "2", _("Inward"))); setDependent(e, "hud_panel_healtharmor_progressbar", 1, 1); - me.TD(me, 1, 0.95, e = makeXonoticRadioButton(2, "hud_panel_healtharmor_baralign", "4", "Outward")); + me.TD(me, 1, 0.95, e = makeXonoticRadioButton(2, "hud_panel_healtharmor_baralign", "3", _("Outward"))); setDependent(e, "hud_panel_healtharmor_progressbar", 1, 1); me.TR(me); - me.TD(me, 1, 2, e = makeXonoticTextLabel(0, "Icon alignment:")); + me.TD(me, 1, 4, e = makeXonoticTextLabel(0, _("Icon alignment:"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 0.95, e = makeXonoticRadioButton(3, "hud_panel_healtharmor_iconalign", "0", "Left")); - me.TD(me, 1, 0.95, e = makeXonoticRadioButton(3, "hud_panel_healtharmor_iconalign", "1", "Right")); - me.TD(me, 1, 0.95, e = makeXonoticRadioButton(3, "hud_panel_healtharmor_iconalign", "3", "Inward")); - me.TD(me, 1, 0.95, e = makeXonoticRadioButton(3, "hud_panel_healtharmor_iconalign", "4", "Outward")); + me.TD(me, 1, 0.95, e = makeXonoticRadioButton(3, "hud_panel_healtharmor_iconalign", "0", _("Left"))); + me.TD(me, 1, 0.95, e = makeXonoticRadioButton(3, "hud_panel_healtharmor_iconalign", "1", _("Right"))); + me.TD(me, 1, 0.95, e = makeXonoticRadioButton(3, "hud_panel_healtharmor_iconalign", "2", _("Inward"))); + me.TD(me, 1, 0.95, e = makeXonoticRadioButton(3, "hud_panel_healtharmor_iconalign", "3", _("Outward"))); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_healtharmor_flip", "Flip health and armor positions")); + me.TD(me, 1, 4, e = makeXonoticCheckBox(0, "hud_panel_healtharmor_flip", _("Flip health and armor positions"))); } #endif diff --git a/qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c b/qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c index d8534a20e9..da63a1e163 100644 --- a/qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c +++ b/qcsrc/menu/xonotic/dialog_hudpanel_infomessages.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticHUDInfoMessagesDialog) EXTENDS(XonoticRootDialog) METHOD(XonoticHUDInfoMessagesDialog, fill, void(entity)) - ATTRIB(XonoticHUDInfoMessagesDialog, title, string, "Info Messages Panel") + ATTRIB(XonoticHUDInfoMessagesDialog, title, string, _("Info Messages Panel")) ATTRIB(XonoticHUDInfoMessagesDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT) ATTRIB(XonoticHUDInfoMessagesDialog, intendedWidth, float, 0.4) ATTRIB(XonoticHUDInfoMessagesDialog, rows, float, 15) @@ -15,66 +15,13 @@ void XonoticHUDInfoMessagesDialog_fill(entity me) { entity e; string panelname = "infomessages"; - float i; + + DIALOG_HUDPANEL_COMMON(); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_infomessages", "Enable panel")); - me.TR(me); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "Background:")); - me.TD(me, 1, 1.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - e.addValue(e, strzone(strcat("border_", panelname)), strzone(strcat("border_", panelname))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Color:")); - me.TD(me, 2, 2.4, e = makeXonoticColorpickerString(strzone(strcat("hud_panel_", panelname, "_bg_color")), "hud_panel_bg_color")); - setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_bg_color")), ""); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticCheckBoxString("", "1 1 1", strzone(strcat("hud_panel_", panelname, "_bg_color")), "Use default")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Border size:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_border")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i * 2, 0)), strzone(ftos(i * 2))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Alpha:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_alpha")))); - e.addValue(e, "Default", ""); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Team Color:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_color_team")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.4); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_configure_teamcolorforced", "Test the team color in HUD configure mode")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Padding:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_padding")))); - e.addValue(e, "Default", ""); - for(i = 0; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i - 5, 0)), strzone(ftos(i - 5))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TD(me, 1, 2, e = makeXonoticTextLabel(0, "Info messages:")); + me.TD(me, 1, 4, e = makeXonoticTextLabel(0, _("Info messages:"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_infomessages_flip", "Flip align")); + me.TD(me, 1, 3.8, e = makeXonoticCheckBox(0, "hud_panel_infomessages_flip", _("Flip align"))); } #endif diff --git a/qcsrc/menu/xonotic/dialog_hudpanel_modicons.c b/qcsrc/menu/xonotic/dialog_hudpanel_modicons.c index d60a72473f..fd5d233dcf 100644 --- a/qcsrc/menu/xonotic/dialog_hudpanel_modicons.c +++ b/qcsrc/menu/xonotic/dialog_hudpanel_modicons.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticHUDModIconsDialog) EXTENDS(XonoticRootDialog) METHOD(XonoticHUDModIconsDialog, fill, void(entity)) - ATTRIB(XonoticHUDModIconsDialog, title, string, "Mod Icons Panel") + ATTRIB(XonoticHUDModIconsDialog, title, string, _("Mod Icons Panel")) ATTRIB(XonoticHUDModIconsDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT) ATTRIB(XonoticHUDModIconsDialog, intendedWidth, float, 0.4) ATTRIB(XonoticHUDModIconsDialog, rows, float, 15) @@ -15,61 +15,7 @@ void XonoticHUDModIconsDialog_fill(entity me) { entity e; string panelname = "modicons"; - float i; - me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_modicons", "Enable panel")); - me.TR(me); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "Background:")); - me.TD(me, 1, 1.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - e.addValue(e, strzone(strcat("border_", panelname)), strzone(strcat("border_", panelname))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Color:")); - me.TD(me, 2, 2.4, e = makeXonoticColorpickerString(strzone(strcat("hud_panel_", panelname, "_bg_color")), "hud_panel_bg_color")); - setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_bg_color")), ""); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticCheckBoxString("", "1 1 1", strzone(strcat("hud_panel_", panelname, "_bg_color")), "Use default")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Border size:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_border")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i * 2, 0)), strzone(ftos(i * 2))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Alpha:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_alpha")))); - e.addValue(e, "Default", ""); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Team Color:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_color_team")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.4); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_configure_teamcolorforced", "Test the team color in HUD configure mode")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Padding:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_padding")))); - e.addValue(e, "Default", ""); - for(i = 0; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i - 5, 0)), strzone(ftos(i - 5))); - e.configureXonoticTextSliderValues(e); + DIALOG_HUDPANEL_COMMON(); } #endif diff --git a/qcsrc/menu/xonotic/dialog_hudpanel_notification.c b/qcsrc/menu/xonotic/dialog_hudpanel_notification.c index 3eeaff284d..936a0fcb59 100644 --- a/qcsrc/menu/xonotic/dialog_hudpanel_notification.c +++ b/qcsrc/menu/xonotic/dialog_hudpanel_notification.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticHUDNotificationDialog) EXTENDS(XonoticRootDialog) METHOD(XonoticHUDNotificationDialog, fill, void(entity)) - ATTRIB(XonoticHUDNotificationDialog, title, string, "Notification Panel") + ATTRIB(XonoticHUDNotificationDialog, title, string, _("Notification Panel")) ATTRIB(XonoticHUDNotificationDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT) ATTRIB(XonoticHUDNotificationDialog, intendedWidth, float, 0.4) ATTRIB(XonoticHUDNotificationDialog, rows, float, 15) @@ -15,77 +15,24 @@ void XonoticHUDNotificationDialog_fill(entity me) { entity e; string panelname = "notify"; - float i; + + DIALOG_HUDPANEL_COMMON(); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_healtharmor", "Enable panel")); - me.TR(me); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "Background:")); - me.TD(me, 1, 1.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - e.addValue(e, strzone(strcat("border_", panelname)), strzone(strcat("border_", panelname))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Color:")); - me.TD(me, 2, 2.4, e = makeXonoticColorpickerString(strzone(strcat("hud_panel_", panelname, "_bg_color")), "hud_panel_bg_color")); - setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_bg_color")), ""); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticCheckBoxString("", "1 1 1", strzone(strcat("hud_panel_", panelname, "_bg_color")), "Use default")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Border size:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_border")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i * 2, 0)), strzone(ftos(i * 2))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Alpha:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_alpha")))); - e.addValue(e, "Default", ""); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Team Color:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_color_team")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.4); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_configure_teamcolorforced", "Test the team color in HUD configure mode")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Padding:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_padding")))); - e.addValue(e, "Default", ""); - for(i = 0; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i - 5, 0)), strzone(ftos(i - 5))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TD(me, 1, 2, e = makeXonoticTextLabel(0, "Notifications:")); + me.TD(me, 1, 4, e = makeXonoticTextLabel(0, _("Notifications:"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_notify_print", "Also print notifications to the console")); + me.TD(me, 1, 3.8, e = makeXonoticCheckBox(0, "hud_panel_notify_print", _("Also print notifications to the console"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_notify_flip", "Flip notify order")); + me.TD(me, 1, 3.8, e = makeXonoticCheckBox(0, "hud_panel_notify_flip", _("Flip notify order"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Entry lifetime:")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Entry lifetime:"))); me.TD(me, 1, 2.6, e = makeXonoticSlider(3, 15, 1, "hud_panel_notify_time")); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Entry fadetime:")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Entry fadetime:"))); me.TD(me, 1, 2.6, e = makeXonoticSlider(0.5, 5, 0.5, "hud_panel_notify_fadetime")); } #endif diff --git a/qcsrc/menu/xonotic/dialog_hudpanel_physics.c b/qcsrc/menu/xonotic/dialog_hudpanel_physics.c new file mode 100644 index 0000000000..aeedc492df --- /dev/null +++ b/qcsrc/menu/xonotic/dialog_hudpanel_physics.c @@ -0,0 +1,82 @@ +#ifdef INTERFACE +CLASS(XonoticHUDPhysicsDialog) EXTENDS(XonoticRootDialog) + METHOD(XonoticHUDPhysicsDialog, fill, void(entity)) + ATTRIB(XonoticHUDPhysicsDialog, title, string, _("Physics Panel")) + ATTRIB(XonoticHUDPhysicsDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT) + ATTRIB(XonoticHUDPhysicsDialog, intendedWidth, float, 0.4) + ATTRIB(XonoticHUDPhysicsDialog, rows, float, 15) + ATTRIB(XonoticHUDPhysicsDialog, columns, float, 4) + ATTRIB(XonoticHUDPhysicsDialog, name, string, "HUDphysics") + ATTRIB(XonoticHUDPhysicsDialog, sliderTopspeedTime, entity, NULL) +ENDCLASS(XonoticHUDPhysicsDialog) +#endif + +#ifdef IMPLEMENTATION +void XonoticHUDPhysicsDialog_fill(entity me) +{ + entity e; + string panelname = "physics"; + + me.TR(me); + me.TD(me, 1, 4, e = makeXonoticTextSlider("hud_panel_physics")); + e.addValue(e, _("Panel disabled"), "0"); + e.addValue(e, _("Panel enabled"), "1"); + e.addValue(e, _("Panel enabled even observing"), "2"); + e.addValue(e, _("Panel enabled only in Race/CTS"), "3"); + e.configureXonoticTextSliderValues(e); + + DIALOG_HUDPANEL_COMMON_NOTOGGLE(); + + me.TR(me); + me.TD(me, 1, 1.4, e = makeXonoticCheckBox(0, "hud_panel_physics_progressbar", _("Status bar"))); + me.TD(me, 1, 2.6, e = makeXonoticTextSlider("hud_panel_physics_baralign")); + e.addValue(e, _("Left align") , "0"); + e.addValue(e, _("Right align") , "1"); + e.addValue(e, _("Inward align") , "2"); + e.addValue(e, _("Outward align"), "3"); + e.configureXonoticTextSliderValues(e); + setDependent(e, "hud_panel_physics_progressbar", 1, 3); + me.TR(me); + me.TD(me, 1, 4, e = makeXonoticCheckBox(0, "hud_panel_physics_flip", _("Flip speed/acceleration positions"))); + +//speed + me.TR(me); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Speed:"))); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_physics_speed_vertical", _("Include vertical speed"))); + // me.TR(me); + // me.TDempty(me, 0.2); + // me.TD(me, 1, 1.8, e = makeXonoticTextLabel(0, _("Full status bar at:"))); + // setDependent(e, "hud_panel_physics_progressbar", 1, 1); + // me.TD(me, 1, 1, e = makeXonoticInputBox(1, "hud_panel_physics_speed_max")); + // setDependent(e, "hud_panel_physics_progressbar", 1, 1); + // me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("qu/s"))); + // setDependent(e, "hud_panel_physics_progressbar", 1, 1); + me.TR(me); + me.TDempty(me, 0.2); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Speed unit:"))); + me.TD(me, 1, 2.6/3*2, e = makeXonoticTextSlider("hud_panel_physics_speed_unit")); + e.addValue(e, _("qu/s") , "1"); + e.addValue(e, _("m/s") , "2"); + e.addValue(e, _("km/h") , "3"); + e.addValue(e, _("mph") , "4"); + e.addValue(e, _("knots"), "5"); + e.configureXonoticTextSliderValues(e); + me.TD(me, 1, 2.6/3, e = makeXonoticCheckBox(0, "hud_panel_physics_speed_unit_show", _("Show"))); + me.TR(me); + me.TDempty(me, 0.2); + me.TD(me, 1, 3.8/2, e = makeXonoticCheckBox(0, "hud_panel_physics_topspeed", _("Top speed"))); + me.TD(me, 1, 3.8/2, e = makeXonoticSlider(1, 10, 1, "hud_panel_physics_topspeed_time")); + setDependent(e, "hud_panel_physics_topspeed", 1, 1); + +//acceleration + me.TR(me); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Acceleration:"))); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_physics_acceleration_vertical", _("Include vertical acceleration"))); + // me.TR(me); + // me.TDempty(me, 0.2); + // me.TD(me, 1, 1.8, e = makeXonoticTextLabel(0, _("Full status bar at:"))); + // setDependent(e, "hud_panel_physics_progressbar", 1, 1); + // me.TD(me, 1, 0.6, e = makeXonoticInputBox(1, "hud_panel_physics_acceleration_max")); + // setDependent(e, "hud_panel_physics_progressbar", 1, 1); +} +#endif diff --git a/qcsrc/menu/xonotic/dialog_hudpanel_powerups.c b/qcsrc/menu/xonotic/dialog_hudpanel_powerups.c index 5d4e14c08b..abab5d1f0d 100644 --- a/qcsrc/menu/xonotic/dialog_hudpanel_powerups.c +++ b/qcsrc/menu/xonotic/dialog_hudpanel_powerups.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticHUDPowerupsDialog) EXTENDS(XonoticRootDialog) METHOD(XonoticHUDPowerupsDialog, fill, void(entity)) - ATTRIB(XonoticHUDPowerupsDialog, title, string, "Powerups Panel") + ATTRIB(XonoticHUDPowerupsDialog, title, string, _("Powerups Panel")) ATTRIB(XonoticHUDPowerupsDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT) ATTRIB(XonoticHUDPowerupsDialog, intendedWidth, float, 0.4) ATTRIB(XonoticHUDPowerupsDialog, rows, float, 15) @@ -15,86 +15,33 @@ void XonoticHUDPowerupsDialog_fill(entity me) { entity e; string panelname = "powerups"; - float i; + + DIALOG_HUDPANEL_COMMON(); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_powerups", "Enable panel")); - me.TR(me); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "Background:")); - me.TD(me, 1, 1.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - e.addValue(e, strzone(strcat("border_", panelname)), strzone(strcat("border_", panelname))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Color:")); - me.TD(me, 2, 2.4, e = makeXonoticColorpickerString(strzone(strcat("hud_panel_", panelname, "_bg_color")), "hud_panel_bg_color")); - setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_bg_color")), ""); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticCheckBoxString("", "1 1 1", strzone(strcat("hud_panel_", panelname, "_bg_color")), "Use default")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Border size:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_border")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i * 2, 0)), strzone(ftos(i * 2))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Alpha:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_alpha")))); - e.addValue(e, "Default", ""); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Team Color:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_color_team")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.4); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_configure_teamcolorforced", "Test the team color in HUD configure mode")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Padding:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_padding")))); - e.addValue(e, "Default", ""); - for(i = 0; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i - 5, 0)), strzone(ftos(i - 5))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_powerups_progressbar", "Enable status bar")); + me.TD(me, 1, 4, e = makeXonoticCheckBox(0, "hud_panel_powerups_progressbar", _("Enable status bar"))); me.TR(me); - me.TD(me, 1, 2, e = makeXonoticTextLabel(0, "Status bar alignment:")); + me.TD(me, 1, 4, e = makeXonoticTextLabel(0, _("Status bar alignment:"))); setDependent(e, "hud_panel_powerups_progressbar", 1, 1); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 0.95, e = makeXonoticRadioButton(2, "hud_panel_powerups_baralign", "0", "Left")); + me.TD(me, 1, 0.95, e = makeXonoticRadioButton(2, "hud_panel_powerups_baralign", "0", _("Left"))); setDependent(e, "hud_panel_powerups_progressbar", 1, 1); - me.TD(me, 1, 0.95, e = makeXonoticRadioButton(2, "hud_panel_powerups_baralign", "1", "Right")); + me.TD(me, 1, 0.95, e = makeXonoticRadioButton(2, "hud_panel_powerups_baralign", "1", _("Right"))); setDependent(e, "hud_panel_powerups_progressbar", 1, 1); - me.TD(me, 1, 0.95, e = makeXonoticRadioButton(2, "hud_panel_powerups_baralign", "3", "Inward")); + me.TD(me, 1, 0.95, e = makeXonoticRadioButton(2, "hud_panel_powerups_baralign", "2", _("Inward"))); setDependent(e, "hud_panel_powerups_progressbar", 1, 1); - me.TD(me, 1, 0.95, e = makeXonoticRadioButton(2, "hud_panel_powerups_baralign", "4", "Outward")); + me.TD(me, 1, 0.95, e = makeXonoticRadioButton(2, "hud_panel_powerups_baralign", "3", _("Outward"))); setDependent(e, "hud_panel_powerups_progressbar", 1, 1); me.TR(me); - me.TD(me, 1, 2, e = makeXonoticTextLabel(0, "Icon alignment:")); + me.TD(me, 1, 4, e = makeXonoticTextLabel(0, _("Icon alignment:"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 0.95, e = makeXonoticRadioButton(3, "hud_panel_powerups_iconalign", "0", "Left")); - me.TD(me, 1, 0.95, e = makeXonoticRadioButton(3, "hud_panel_powerups_iconalign", "1", "Right")); - me.TD(me, 1, 0.95, e = makeXonoticRadioButton(3, "hud_panel_powerups_iconalign", "3", "Inward")); - me.TD(me, 1, 0.95, e = makeXonoticRadioButton(3, "hud_panel_powerups_iconalign", "4", "Outward")); + me.TD(me, 1, 0.95, e = makeXonoticRadioButton(3, "hud_panel_powerups_iconalign", "0", _("Left"))); + me.TD(me, 1, 0.95, e = makeXonoticRadioButton(3, "hud_panel_powerups_iconalign", "1", _("Right"))); + me.TD(me, 1, 0.95, e = makeXonoticRadioButton(3, "hud_panel_powerups_iconalign", "2", _("Inward"))); + me.TD(me, 1, 0.95, e = makeXonoticRadioButton(3, "hud_panel_powerups_iconalign", "3", _("Outward"))); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_powerups_flip", "Flip strength and shield positions")); + me.TD(me, 1, 4, e = makeXonoticCheckBox(0, "hud_panel_powerups_flip", _("Flip strength and shield positions"))); } #endif diff --git a/qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c b/qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c index 30f6bfc1f2..b01ec1c980 100644 --- a/qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c +++ b/qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticHUDPressedKeysDialog) EXTENDS(XonoticRootDialog) METHOD(XonoticHUDPressedKeysDialog, fill, void(entity)) - ATTRIB(XonoticHUDPressedKeysDialog, title, string, "Pressed Keys Panel") + ATTRIB(XonoticHUDPressedKeysDialog, title, string, _("Pressed Keys Panel")) ATTRIB(XonoticHUDPressedKeysDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT) ATTRIB(XonoticHUDPressedKeysDialog, intendedWidth, float, 0.4) ATTRIB(XonoticHUDPressedKeysDialog, rows, float, 15) @@ -15,69 +15,19 @@ void XonoticHUDPressedKeysDialog_fill(entity me) { entity e; string panelname = "pressedkeys"; - float i; me.TR(me); - me.TD(me, 1, 2, e = makeXonoticTextSlider("hud_panel_pressedkeys")); - e.addValue(e, "Panel disabled", "0"); - e.addValue(e, "Panel enabled when spectating", "1"); - e.addValue(e, "Panel always enabled", "2"); + me.TD(me, 1, 4, e = makeXonoticTextSlider("hud_panel_pressedkeys")); + e.addValue(e, _("Panel disabled"), "0"); + e.addValue(e, _("Panel enabled when spectating"), "1"); + e.addValue(e, _("Panel always enabled"), "2"); e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "Background:")); - me.TD(me, 1, 1.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - e.addValue(e, strzone(strcat("border_", panelname)), strzone(strcat("border_", panelname))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Color:")); - me.TD(me, 2, 2.4, e = makeXonoticColorpickerString(strzone(strcat("hud_panel_", panelname, "_bg_color")), "hud_panel_bg_color")); - setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_bg_color")), ""); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticCheckBoxString("", "1 1 1", strzone(strcat("hud_panel_", panelname, "_bg_color")), "Use default")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Border size:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_border")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i * 2, 0)), strzone(ftos(i * 2))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Alpha:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_alpha")))); - e.addValue(e, "Default", ""); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Team Color:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_color_team")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.4); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_configure_teamcolorforced", "Test the team color in HUD configure mode")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Padding:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_padding")))); - e.addValue(e, "Default", ""); - for(i = 0; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i - 5, 0)), strzone(ftos(i - 5))); - e.configureXonoticTextSliderValues(e); + + DIALOG_HUDPANEL_COMMON_NOTOGGLE(); + me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Forced aspect:")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Forced aspect:"))); me.TD(me, 1, 2.6, e = makeXonoticSlider(0.2, 4, 0.1, "hud_panel_pressedkeys_aspect")); } #endif diff --git a/qcsrc/menu/xonotic/dialog_hudpanel_racetimer.c b/qcsrc/menu/xonotic/dialog_hudpanel_racetimer.c index 35fdc55f3c..015979b21e 100644 --- a/qcsrc/menu/xonotic/dialog_hudpanel_racetimer.c +++ b/qcsrc/menu/xonotic/dialog_hudpanel_racetimer.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticHUDRaceTimerDialog) EXTENDS(XonoticRootDialog) METHOD(XonoticHUDRaceTimerDialog, fill, void(entity)) - ATTRIB(XonoticHUDRaceTimerDialog, title, string, "Race Timer Panel") + ATTRIB(XonoticHUDRaceTimerDialog, title, string, _("Race Timer Panel")) ATTRIB(XonoticHUDRaceTimerDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT) ATTRIB(XonoticHUDRaceTimerDialog, intendedWidth, float, 0.4) ATTRIB(XonoticHUDRaceTimerDialog, rows, float, 15) @@ -15,61 +15,7 @@ void XonoticHUDRaceTimerDialog_fill(entity me) { entity e; string panelname = "racetimer"; - float i; - me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_racetimer", "Enable panel")); - me.TR(me); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "Background:")); - me.TD(me, 1, 1.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - e.addValue(e, strzone(strcat("border_", panelname)), strzone(strcat("border_", panelname))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Color:")); - me.TD(me, 2, 2.4, e = makeXonoticColorpickerString(strzone(strcat("hud_panel_", panelname, "_bg_color")), "hud_panel_bg_color")); - setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_bg_color")), ""); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticCheckBoxString("", "1 1 1", strzone(strcat("hud_panel_", panelname, "_bg_color")), "Use default")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Border size:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_border")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i * 2, 0)), strzone(ftos(i * 2))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Alpha:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_alpha")))); - e.addValue(e, "Default", ""); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Team Color:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_color_team")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.4); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_configure_teamcolorforced", "Test the team color in HUD configure mode")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Padding:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_padding")))); - e.addValue(e, "Default", ""); - for(i = 0; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i - 5, 0)), strzone(ftos(i - 5))); - e.configureXonoticTextSliderValues(e); + DIALOG_HUDPANEL_COMMON(); } #endif diff --git a/qcsrc/menu/xonotic/dialog_hudpanel_radar.c b/qcsrc/menu/xonotic/dialog_hudpanel_radar.c index d1202846e2..3e72acc8b0 100644 --- a/qcsrc/menu/xonotic/dialog_hudpanel_radar.c +++ b/qcsrc/menu/xonotic/dialog_hudpanel_radar.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticHUDRadarDialog) EXTENDS(XonoticRootDialog) METHOD(XonoticHUDRadarDialog, fill, void(entity)) - ATTRIB(XonoticHUDRadarDialog, title, string, "Radar Panel") + ATTRIB(XonoticHUDRadarDialog, title, string, _("Radar Panel")) ATTRIB(XonoticHUDRadarDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT) ATTRIB(XonoticHUDRadarDialog, intendedWidth, float, 0.4) ATTRIB(XonoticHUDRadarDialog, rows, float, 15) @@ -15,94 +15,44 @@ void XonoticHUDRadarDialog_fill(entity me) { entity e; string panelname = "radar"; - float i; me.TR(me); - me.TD(me, 1, 2, e = makeXonoticTextSlider("hud_panel_radar")); - e.addValue(e, "Panel disabled", "0"); - e.addValue(e, "Panel enabled in teamgames", "1"); - e.addValue(e, "Panel always enabled", "2"); + me.TD(me, 1, 4, e = makeXonoticTextSlider("hud_panel_radar")); + e.addValue(e, _("Panel disabled"), "0"); + e.addValue(e, _("Panel enabled in teamgames"), "1"); + e.addValue(e, _("Panel always enabled"), "2"); e.configureXonoticTextSliderValues(e); + + DIALOG_HUDPANEL_COMMON_NOTOGGLE(); + me.TR(me); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "Background:")); - me.TD(me, 1, 1.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - e.addValue(e, strzone(strcat("border_", panelname)), strzone(strcat("border_", panelname))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Color:")); - me.TD(me, 2, 2.4, e = makeXonoticColorpickerString(strzone(strcat("hud_panel_", panelname, "_bg_color")), "hud_panel_bg_color")); - setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_bg_color")), ""); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticCheckBoxString("", "1 1 1", strzone(strcat("hud_panel_", panelname, "_bg_color")), "Use default")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Border size:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_border")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i * 2, 0)), strzone(ftos(i * 2))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Alpha:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_alpha")))); - e.addValue(e, "Default", ""); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Team Color:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_color_team")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.4); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_configure_teamcolorforced", "Test the team color in HUD configure mode")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Padding:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_padding")))); - e.addValue(e, "Default", ""); - for(i = 0; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i - 5, 0)), strzone(ftos(i - 5))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TD(me, 1, 2, e = makeXonoticTextLabel(0, "Radar:")); + me.TD(me, 1, 4, e = makeXonoticTextLabel(0, _("Radar:"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Alpha:")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Alpha:"))); me.TD(me, 1, 2.6, e = makeXonoticSlider(0.1, 1, 0.1, "hud_panel_radar_foreground_alpha")); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Rotation:")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Rotation:"))); me.TD(me, 1, 2.6, e = makeXonoticTextSlider("hud_panel_radar_rotation")); - e.addValue(e, "Forward", "0"); - e.addValue(e, "West", "1"); - e.addValue(e, "South", "2"); - e.addValue(e, "East", "3"); - e.addValue(e, "North", "4"); + e.addValue(e, _("Forward"), "0"); + e.addValue(e, _("West"), "1"); + e.addValue(e, _("South"), "2"); + e.addValue(e, _("East"), "3"); + e.addValue(e, _("North"), "4"); e.configureXonoticTextSliderValues(e); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Scale:")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Scale:"))); me.TD(me, 1, 2.6, e = makeXonoticSlider(1024, 8192, 512, "hud_panel_radar_scale")); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Zoom mode:")); - me.TD(me, 1, 1.6, e = makeXonoticTextSlider("hud_panel_radar_zoommode")); - e.addValue(e, "Zoomed in", "0"); - e.addValue(e, "Zoomed out", "1"); - e.addValue(e, "Always zoomed", "2"); - e.addValue(e, "Never zoomed", "3"); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Zoom mode:"))); + me.TD(me, 1, 2.6, e = makeXonoticTextSlider("hud_panel_radar_zoommode")); + e.addValue(e, _("Zoomed in"), "0"); + e.addValue(e, _("Zoomed out"), "1"); + e.addValue(e, _("Always zoomed"), "2"); + e.addValue(e, _("Never zoomed"), "3"); e.configureXonoticTextSliderValues(e); } #endif diff --git a/qcsrc/menu/xonotic/dialog_hudpanel_score.c b/qcsrc/menu/xonotic/dialog_hudpanel_score.c index fc51921e23..778172aa14 100644 --- a/qcsrc/menu/xonotic/dialog_hudpanel_score.c +++ b/qcsrc/menu/xonotic/dialog_hudpanel_score.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticHUDScoreDialog) EXTENDS(XonoticRootDialog) METHOD(XonoticHUDScoreDialog, fill, void(entity)) - ATTRIB(XonoticHUDScoreDialog, title, string, "Score Panel") + ATTRIB(XonoticHUDScoreDialog, title, string, _("Score Panel")) ATTRIB(XonoticHUDScoreDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT) ATTRIB(XonoticHUDScoreDialog, intendedWidth, float, 0.4) ATTRIB(XonoticHUDScoreDialog, rows, float, 15) @@ -15,61 +15,16 @@ void XonoticHUDScoreDialog_fill(entity me) { entity e; string panelname = "score"; - float i; + + DIALOG_HUDPANEL_COMMON(); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_score", "Enable panel")); - me.TR(me); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "Background:")); - me.TD(me, 1, 1.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - e.addValue(e, strzone(strcat("border_", panelname)), strzone(strcat("border_", panelname))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Color:")); - me.TD(me, 2, 2.4, e = makeXonoticColorpickerString(strzone(strcat("hud_panel_", panelname, "_bg_color")), "hud_panel_bg_color")); - setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_bg_color")), ""); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticCheckBoxString("", "1 1 1", strzone(strcat("hud_panel_", panelname, "_bg_color")), "Use default")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Border size:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_border")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i * 2, 0)), strzone(ftos(i * 2))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Alpha:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_alpha")))); - e.addValue(e, "Default", ""); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Team Color:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_color_team")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.4); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_configure_teamcolorforced", "Test the team color in HUD configure mode")); + me.TD(me, 1, 4, e = makeXonoticTextLabel(0, _("Score:"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Padding:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_padding")))); - e.addValue(e, "Default", ""); - for(i = 0; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i - 5, 0)), strzone(ftos(i - 5))); - e.configureXonoticTextSliderValues(e); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Rankings:"))); + me.TD(me, 1, 2.6/3, e = makeXonoticRadioButton(1, "hud_panel_score_rankings", "0", _("Off"))); + me.TD(me, 1, 2.6/3, e = makeXonoticRadioButton(1, "hud_panel_score_rankings", "1", _("And me"))); + me.TD(me, 1, 2.6/3, e = makeXonoticRadioButton(1, "hud_panel_score_rankings", "2", _("Pure"))); } #endif diff --git a/qcsrc/menu/xonotic/dialog_hudpanel_timer.c b/qcsrc/menu/xonotic/dialog_hudpanel_timer.c index 96dc4aa695..c1e9626dd9 100644 --- a/qcsrc/menu/xonotic/dialog_hudpanel_timer.c +++ b/qcsrc/menu/xonotic/dialog_hudpanel_timer.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticHUDTimerDialog) EXTENDS(XonoticRootDialog) METHOD(XonoticHUDTimerDialog, fill, void(entity)) - ATTRIB(XonoticHUDTimerDialog, title, string, "Timer Panel") + ATTRIB(XonoticHUDTimerDialog, title, string, _("Timer Panel")) ATTRIB(XonoticHUDTimerDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT) ATTRIB(XonoticHUDTimerDialog, intendedWidth, float, 0.4) ATTRIB(XonoticHUDTimerDialog, rows, float, 15) @@ -15,66 +15,13 @@ void XonoticHUDTimerDialog_fill(entity me) { entity e; string panelname = "timer"; - float i; + + DIALOG_HUDPANEL_COMMON(); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_timer", "Enable panel")); - me.TR(me); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "Background:")); - me.TD(me, 1, 1.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - e.addValue(e, strzone(strcat("border_", panelname)), strzone(strcat("border_", panelname))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Color:")); - me.TD(me, 2, 2.4, e = makeXonoticColorpickerString(strzone(strcat("hud_panel_", panelname, "_bg_color")), "hud_panel_bg_color")); - setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_bg_color")), ""); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticCheckBoxString("", "1 1 1", strzone(strcat("hud_panel_", panelname, "_bg_color")), "Use default")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Border size:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_border")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i * 2, 0)), strzone(ftos(i * 2))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Alpha:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_alpha")))); - e.addValue(e, "Default", ""); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Team Color:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_color_team")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.4); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_configure_teamcolorforced", "Test the team color in HUD configure mode")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Padding:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_padding")))); - e.addValue(e, "Default", ""); - for(i = 0; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i - 5, 0)), strzone(ftos(i - 5))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TD(me, 1, 2, e = makeXonoticTextLabel(0, "Timer:")); + me.TD(me, 1, 4, e = makeXonoticTextLabel(0, _("Timer:"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_timer_increment", "Show elapsed time")); + me.TD(me, 1, 3.8, e = makeXonoticCheckBox(0, "hud_panel_timer_increment", _("Show elapsed time"))); } #endif diff --git a/qcsrc/menu/xonotic/dialog_hudpanel_vote.c b/qcsrc/menu/xonotic/dialog_hudpanel_vote.c index b5f5b6e27b..0b2c0ac078 100644 --- a/qcsrc/menu/xonotic/dialog_hudpanel_vote.c +++ b/qcsrc/menu/xonotic/dialog_hudpanel_vote.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticHUDVoteDialog) EXTENDS(XonoticRootDialog) METHOD(XonoticHUDVoteDialog, fill, void(entity)) - ATTRIB(XonoticHUDVoteDialog, title, string, "Vote Panel") + ATTRIB(XonoticHUDVoteDialog, title, string, _("Vote Panel")) ATTRIB(XonoticHUDVoteDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT) ATTRIB(XonoticHUDVoteDialog, intendedWidth, float, 0.4) ATTRIB(XonoticHUDVoteDialog, rows, float, 15) @@ -15,64 +15,11 @@ void XonoticHUDVoteDialog_fill(entity me) { entity e; string panelname = "vote"; - float i; + + DIALOG_HUDPANEL_COMMON(); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_vote", "Enable panel")); - me.TR(me); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "Background:")); - me.TD(me, 1, 1.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - e.addValue(e, strzone(strcat("border_", panelname)), strzone(strcat("border_", panelname))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Color:")); - me.TD(me, 2, 2.4, e = makeXonoticColorpickerString(strzone(strcat("hud_panel_", panelname, "_bg_color")), "hud_panel_bg_color")); - setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_bg_color")), ""); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticCheckBoxString("", "1 1 1", strzone(strcat("hud_panel_", panelname, "_bg_color")), "Use default")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Border size:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_border")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i * 2, 0)), strzone(ftos(i * 2))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Alpha:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_alpha")))); - e.addValue(e, "Default", ""); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Team Color:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_color_team")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.4); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_configure_teamcolorforced", "Test the team color in HUD configure mode")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Padding:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_padding")))); - e.addValue(e, "Default", ""); - for(i = 0; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i - 5, 0)), strzone(ftos(i - 5))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "Alpha after voting:")); - me.TD(me, 1, 2.6, e = makeXonoticSlider(0.1, 1, 0.1, "hud_panel_vote_alreadyvoted_alpha")); + me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, _("Alpha after voting:"))); + me.TD(me, 1, 2.6, e = makeXonoticSlider(0.1, 1, 0.1, "hud_panel_vote_alreadyvoted_alpha")); } #endif diff --git a/qcsrc/menu/xonotic/dialog_hudpanel_weapons.c b/qcsrc/menu/xonotic/dialog_hudpanel_weapons.c index ad3d080415..b31622f673 100644 --- a/qcsrc/menu/xonotic/dialog_hudpanel_weapons.c +++ b/qcsrc/menu/xonotic/dialog_hudpanel_weapons.c @@ -1,10 +1,10 @@ #ifdef INTERFACE CLASS(XonoticHUDWeaponsDialog) EXTENDS(XonoticRootDialog) METHOD(XonoticHUDWeaponsDialog, fill, void(entity)) - ATTRIB(XonoticHUDWeaponsDialog, title, string, "Weapons Panel") + ATTRIB(XonoticHUDWeaponsDialog, title, string, _("Weapons Panel")) ATTRIB(XonoticHUDWeaponsDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT) ATTRIB(XonoticHUDWeaponsDialog, intendedWidth, float, 0.4) - ATTRIB(XonoticHUDWeaponsDialog, rows, float, 17) + ATTRIB(XonoticHUDWeaponsDialog, rows, float, 18) ATTRIB(XonoticHUDWeaponsDialog, columns, float, 4) ATTRIB(XonoticHUDWeaponsDialog, name, string, "HUDweapons") ENDCLASS(XonoticHUDWeaponsDialog) @@ -17,99 +17,52 @@ void XonoticHUDWeaponsDialog_fill(entity me) string panelname = "weapons"; float i; - me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_weapons", "Enable panel")); - me.TR(me); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "Background:")); - me.TD(me, 1, 1.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - e.addValue(e, strzone(strcat("border_", panelname)), strzone(strcat("border_", panelname))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Color:")); - me.TD(me, 2, 2.4, e = makeXonoticColorpickerString(strzone(strcat("hud_panel_", panelname, "_bg_color")), "hud_panel_bg_color")); - setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_bg_color")), ""); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticCheckBoxString("", cvar_string("hud_panel_bg_color"), strzone(strcat("hud_panel_", panelname, "_bg_color")), "Use default")); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Border size:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_border")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i * 2, 0)), strzone(ftos(i * 2))); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Alpha:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_alpha")))); - e.addValue(e, "Default", ""); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); - e.configureXonoticTextSliderValues(e); + DIALOG_HUDPANEL_COMMON(); + me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Team Color:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_color_team")))); - e.addValue(e, "Default", ""); - e.addValue(e, "Disable", "0"); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Fade out after:"))); + me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_timeout")))); + e.addValue(e, _("Never"), "0"); for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); + e.addValue(e, strzone(sprintf(_("%ds"), i)), strzone(ftos(i))); e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TDempty(me, 0.4); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_configure_teamcolorforced", "Test the team color in HUD configure mode")); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Padding:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_padding")))); - e.addValue(e, "Default", ""); - for(i = 0; i <= 10; ++i) - e.addValue(e, strzone(ftos_decimals(i - 5, 0)), strzone(ftos(i - 5))); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Fade effect:"))); + setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_timeout")), "0"); + me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_timeout_effect")))); + e.addValue(e, ZCTX(_("EF^None")), "0"); + e.addValue(e, _("Slide"), "1"); + e.addValue(e, _("Alpha"), "2"); + e.addValue(e, ZCTX(_("EF^Both")), "3"); e.configureXonoticTextSliderValues(e); + setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_timeout")), "0"); me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Fade out after:")); - me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_timeout")))); - e.addValue(e, "Never", "0"); - for(i = 1; i <= 10; ++i) - e.addValue(e, strzone(strcat(ftos_decimals(i, 0), "s")), strzone(ftos(i))); - e.configureXonoticTextSliderValues(e); + me.TD(me, 1, 4, e = makeXonoticTextLabel(0, _("Weapon icons:"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "Fade effect:")); - me.TD(me, 1, 0.8, e = makeXonoticRadioButton(3, "hud_panel_weapons_timeout_effect", "0", "None")); - setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_timeout")), "0"); - me.TD(me, 1, 0.8, e = makeXonoticRadioButton(3, "hud_panel_weapons_timeout_effect", "1", "Slide")); - setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_timeout")), "0"); - me.TD(me, 1, 0.8, e = makeXonoticRadioButton(3, "hud_panel_weapons_timeout_effect", "2", "Alpha")); - setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_timeout")), "0"); - me.TR(me); - me.TD(me, 1, 2, e = makeXonoticTextLabel(0, "Weapon icons:")); + me.TD(me, 1, 3.8, e = makeXonoticCheckBox(0, "hud_panel_weapons_onlyowned", _("Show only owned weapons"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "Show weapon ID as:")); - me.TD(me, 1, 0.8, e = makeXonoticRadioButton(2, "hud_panel_weapons_label", "0", "None")); - me.TD(me, 1, 0.8, e = makeXonoticRadioButton(2, "hud_panel_weapons_label", "1", "Number")); - me.TD(me, 1, 0.8, e = makeXonoticRadioButton(2, "hud_panel_weapons_label", "2", "Bind")); + me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, _("Show weapon ID as:"))); + me.TD(me, 1, 0.8, e = makeXonoticRadioButton(2, "hud_panel_weapons_label", "0", ZCTX(_("SHOWAS^None")))); + me.TD(me, 1, 0.8, e = makeXonoticRadioButton(2, "hud_panel_weapons_label", "1", _("Number"))); + me.TD(me, 1, 0.8, e = makeXonoticRadioButton(2, "hud_panel_weapons_label", "2", _("Bind"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "hud_panel_weapons_accuracy", "Show Accuracy")); - me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "hud_panel_weapons_ammo", "Show Ammo")); + me.TD(me, 1, 3.8/2, e = makeXonoticCheckBox(0, "hud_panel_weapons_accuracy", _("Show Accuracy"))); + me.TD(me, 1, 3.8/2, e = makeXonoticCheckBox(0, "hud_panel_weapons_ammo", _("Show Ammo"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Ammo bar color:")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Ammo bar color:"))); me.TD(me, 2, 2.4, e = makeXonoticColorpickerString("hud_panel_weapons_ammo_color", "hud_panel_weapons_ammo_color")); setDependent(e, "hud_panel_weapons_ammo", 1, 1); me.TR(me); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "Ammo bar alpha:")); - me.TD(me, 1, 2.6, e = makeXonoticSlider(0.1, 1, 0.1, "hud_panel_weapons_ammo_alpha")); + me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, _("Ammo bar alpha:"))); + me.TD(me, 1, 2.4, e = makeXonoticSlider(0.1, 1, 0.1, "hud_panel_weapons_ammo_alpha")); setDependent(e, "hud_panel_weapons_ammo", 1, 1); } #endif diff --git a/qcsrc/menu/xonotic/dialog_hudsetup_exit.c b/qcsrc/menu/xonotic/dialog_hudsetup_exit.c index 751b3cf95c..0fde6e0bd5 100644 --- a/qcsrc/menu/xonotic/dialog_hudsetup_exit.c +++ b/qcsrc/menu/xonotic/dialog_hudsetup_exit.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticHUDExitDialog) EXTENDS(XonoticRootDialog) METHOD(XonoticHUDExitDialog, fill, void(entity)) - ATTRIB(XonoticHUDExitDialog, title, string, "Panel HUD Setup") + ATTRIB(XonoticHUDExitDialog, title, string, _("Panel HUD Setup")) ATTRIB(XonoticHUDExitDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT) ATTRIB(XonoticHUDExitDialog, intendedWidth, float, 0.4) ATTRIB(XonoticHUDExitDialog, rows, float, 18) @@ -18,95 +18,95 @@ void XonoticHUDExitDialog_fill(entity me) float i; me.TR(me); - me.TD(me, 1, 4, makeXonoticTextLabel(0, "Panel background defaults:")); + me.TD(me, 1, 4, makeXonoticTextLabel(0, _("Panel background defaults:"))); me.TR(me); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "Background:")); - me.TD(me, 1, 1.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_bg")))); - e.addValue(e, "Disable", "0"); - e.addValue(e, "border_default", "border_default"); + me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, _("Background:"))); + me.TD(me, 1, 2.6, e = makeXonoticTextSlider("hud_panel_bg")); + e.addValue(e, _("Disable"), "0"); + e.addValue(e, "border_default", "border_default"); // this is a file name! e.configureXonoticTextSliderValues(e); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Color:")); - me.TD(me, 2, 2.4, e = makeXonoticColorpickerString("hud_panel_bg_color", "hud_panel_bg_color")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Color:"))); + me.TD(me, 2, 2.6, e = makeXonoticColorpickerString("hud_panel_bg_color", "hud_panel_bg_color")); me.TR(me); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Border size:")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Border size:"))); me.TD(me, 1, 2.6, e = makeXonoticTextSlider("hud_panel_bg_border")); - e.addValue(e, "Disable", "0"); + e.addValue(e, _("Disable"), "0"); for(i = 1; i <= 10; ++i) e.addValue(e, strzone(ftos_decimals(i * 2, 0)), strzone(ftos(i * 2))); e.configureXonoticTextSliderValues(e); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Alpha:")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Alpha:"))); me.TD(me, 1, 2.6, e = makeXonoticTextSlider("hud_panel_bg_alpha")); for(i = 1; i <= 10; ++i) e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); e.configureXonoticTextSliderValues(e); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Team color:")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Team color:"))); me.TD(me, 1, 2.6, e = makeXonoticTextSlider("hud_panel_bg_color_team")); - e.addValue(e, "Disable", "0"); + e.addValue(e, _("Disable"), "0"); for(i = 1; i <= 10; ++i) e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); e.configureXonoticTextSliderValues(e); me.TR(me); me.TDempty(me, 0.4); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_configure_teamcolorforced", "Test the team color in HUD configure mode")); + me.TD(me, 1, 3.6, e = makeXonoticCheckBox(0, "hud_configure_teamcolorforced", _("Test team color in configure mode"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Padding:")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Padding:"))); me.TD(me, 1, 2.6, e = makeXonoticTextSlider("hud_panel_bg_padding")); for(i = 0; i <= 10; ++i) e.addValue(e, strzone(ftos_decimals(i - 5, 0)), strzone(ftos(i - 5))); e.configureXonoticTextSliderValues(e); me.TR(me); - me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, "HUD Dock:")); + me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, _("HUD Dock:"))); me.TD(me, 1, 2.6, e = makeXonoticTextSlider("hud_dock")); - e.addValue(e, "Disable", "0"); - e.addValue(e, "Small", "dock_small"); - e.addValue(e, "Medium", "dock_medium"); - e.addValue(e, "Large", "dock_large"); + e.addValue(e, ZCTX(_("DOCK^Disabled")), "0"); + e.addValue(e, ZCTX(_("DOCK^Small")), "dock_small"); + e.addValue(e, ZCTX(_("DOCK^Medium")), "dock_medium"); + e.addValue(e, ZCTX(_("DOCK^Large")), "dock_large"); e.configureXonoticTextSliderValues(e); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Color:")); - me.TD(me, 2, 2.4, e = makeXonoticColorpickerString("hud_dock_color", "hud_dock_color")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Color:"))); + me.TD(me, 2, 2.6, e = makeXonoticColorpickerString("hud_dock_color", "hud_dock_color")); me.TR(me); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Alpha:")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Alpha:"))); me.TD(me, 1, 2.6, e = makeXonoticTextSlider("hud_dock_alpha")); for(i = 1; i <= 10; ++i) e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); e.configureXonoticTextSliderValues(e); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Team color:")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Team color:"))); me.TD(me, 1, 2.6, e = makeXonoticTextSlider("hud_dock_color_team")); - e.addValue(e, "Disable", "0"); + e.addValue(e, _("Disable"), "0"); for(i = 1; i <= 10; ++i) e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); e.configureXonoticTextSliderValues(e); me.TR(me); - me.TD(me, 1, 4, makeXonoticTextLabel(0, "Grid settings:")); + me.TD(me, 1, 4, makeXonoticTextLabel(0, _("Grid settings:"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_configure_grid", "Snap panels to grid")); + me.TD(me, 1, 3.8, e = makeXonoticCheckBox(0, "hud_configure_grid", _("Snap panels to grid"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Grid size:")); - me.TD(me, 1, 0.2, e = makeXonoticTextLabel(0, "X:")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Grid size:"))); + me.TD(me, 1, 0.2, e = makeXonoticTextLabel(0, _("X:"))); me.TD(me, 1, 1.1, e = makeXonoticTextSlider("hud_configure_grid_xsize")); for(i = 1; i <= 14; ++i) e.addValue(e, strzone(ftos_decimals(i/200, 3)), strzone(ftos(i/200))); e.configureXonoticTextSliderValues(e); setDependent(e, "hud_configure_grid", 1, 1); - me.TD(me, 1, 0.2, e = makeXonoticTextLabel(0, "Y:")); + me.TD(me, 1, 0.2, e = makeXonoticTextLabel(0, _("Y:"))); me.TD(me, 1, 1.1, e = makeXonoticTextSlider("hud_configure_grid_ysize")); for(i = 1; i <= 14; ++i) e.addValue(e, strzone(ftos_decimals(i/200, 3)), strzone(ftos(i/200))); @@ -114,6 +114,6 @@ void XonoticHUDExitDialog_fill(entity me) setDependent(e, "hud_configure_grid", 1, 1); me.gotoRC(me, me.rows - 1, 0); - me.TD(me, 1, me.columns, e = makeXonoticCommandButton("Exit setup", '0 0 0', "_hud_configure 0", 1)); + me.TD(me, 1, me.columns, e = makeXonoticCommandButton(_("Exit setup"), '0 0 0', "_hud_configure 0", 1)); } #endif diff --git a/qcsrc/menu/xonotic/dialog_multiplayer.c b/qcsrc/menu/xonotic/dialog_multiplayer.c index e755710c5b..2492581d06 100644 --- a/qcsrc/menu/xonotic/dialog_multiplayer.c +++ b/qcsrc/menu/xonotic/dialog_multiplayer.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticMultiplayerDialog) EXTENDS(XonoticDialog) METHOD(XonoticMultiplayerDialog, fill, void(entity)) - ATTRIB(XonoticMultiplayerDialog, title, string, "Multiplayer") + ATTRIB(XonoticMultiplayerDialog, title, string, _("Multiplayer")) ATTRIB(XonoticMultiplayerDialog, color, vector, SKINCOLOR_DIALOG_MULTIPLAYER) ATTRIB(XonoticMultiplayerDialog, intendedWidth, float, 0.96) ATTRIB(XonoticMultiplayerDialog, rows, float, 24) @@ -15,14 +15,10 @@ void XonoticMultiplayerDialog_fill(entity me) entity mc, e; mc = makeXonoticTabController(me.rows - 2); me.TR(me); - me.TD(me, 1, 1, e = mc.makeTabButton(mc, "Servers", makeXonoticServerListTab())); - setDependentStringNotEqual(e, "_cl_name", "Player"); - me.TD(me, 1, 1, e = mc.makeTabButton(mc, "Create", makeXonoticServerCreateTab())); - setDependentStringNotEqual(e, "_cl_name", "Player"); - me.TD(me, 1, 1, mc.makeTabButton(mc, "Demos", makeXonoticDemoBrowserTab())); - me.TD(me, 1, 1, e = mc.makeTabButton(mc, "Player Setup", makeXonoticPlayerSettingsTab())); - if(cvar_string("_cl_name") == "Player") - e.onClick(e, e.onClickEntity); // lol animation + me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Servers"), makeXonoticServerListTab())); + me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Create"), makeXonoticServerCreateTab())); + me.TD(me, 1, 1, mc.makeTabButton(mc, _("Demos"), makeXonoticDemoBrowserTab())); + me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Player Setup"), makeXonoticPlayerSettingsTab())); me.TR(me); me.TR(me); diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_create.c b/qcsrc/menu/xonotic/dialog_multiplayer_create.c index 416a85419b..b9b5896804 100644 --- a/qcsrc/menu/xonotic/dialog_multiplayer_create.c +++ b/qcsrc/menu/xonotic/dialog_multiplayer_create.c @@ -2,7 +2,7 @@ CLASS(XonoticServerCreateTab) EXTENDS(XonoticTab) METHOD(XonoticServerCreateTab, fill, void(entity)) METHOD(XonoticServerCreateTab, gameTypeChangeNotify, void(entity)) - ATTRIB(XonoticServerCreateTab, title, string, "Create") + ATTRIB(XonoticServerCreateTab, title, string, _("Create")) ATTRIB(XonoticServerCreateTab, intendedWidth, float, 0.9) ATTRIB(XonoticServerCreateTab, rows, float, 22) ATTRIB(XonoticServerCreateTab, columns, float, 6.5) @@ -29,151 +29,94 @@ entity makeXonoticServerCreateTab() void XonoticServerCreateTab_fill(entity me) { entity e, e0; - float n; me.TR(me); - n = 6; - me.TD(me, 1, me.columns / n, e = makeXonoticGametypeButton(1, "g_dm", "DM")); - e0 = e; - me.TD(me, 1, me.columns / n, e = makeXonoticGametypeButton(1, "g_lms", "LMS")); - if(e.checked) e0 = NULL; - me.TD(me, 1, me.columns / n, e = makeXonoticGametypeButton(1, "g_arena", "Arena")); - if(e.checked) e0 = NULL; - me.TD(me, 1, me.columns / n, e = makeXonoticGametypeButton(1, "g_keepaway", "Keepaway")); - if(e.checked) e0 = NULL; - me.TD(me, 1, me.columns / n, e = makeXonoticGametypeButton(1, "g_race", "Race")); - if(e.checked) e0 = NULL; - me.TD(me, 1, me.columns / n, e = makeXonoticGametypeButton(1, "g_cts", "Race CTS")); - if(e.checked) e0 = NULL; - me.TR(me); - n = 9; - me.TD(me, 1, me.columns / n, e = makeXonoticGametypeButton(1, "g_tdm", "TDM")); - if(e.checked) e0 = NULL; - me.TD(me, 1, me.columns / n, e = makeXonoticGametypeButton(1, "g_ctf", "CTF")); - if(e.checked) e0 = NULL; - me.TD(me, 1, me.columns / n, e = makeXonoticGametypeButton(1, "g_ca", "CA")); - if(e.checked) e0 = NULL; - me.TD(me, 1, me.columns / n, e = makeXonoticGametypeButton(1, "g_freezetag", "Freeze Tag")); - if(e.checked) e0 = NULL; - me.TD(me, 1, me.columns / n, e = makeXonoticGametypeButton(1, "g_domination", "Domination")); - if(e.checked) e0 = NULL; - me.TD(me, 1, me.columns / n, e = makeXonoticGametypeButton(1, "g_keyhunt", "Key Hunt")); - if(e.checked) e0 = NULL; - me.TD(me, 1, me.columns / n, e = makeXonoticGametypeButton(1, "g_assault", "Assault")); - if(e.checked) e0 = NULL; - me.TD(me, 1, me.columns / n, e = makeXonoticGametypeButton(1, "g_onslaught", "Onslaught")); - if(e.checked) e0 = NULL; - me.TD(me, 1, me.columns / n, e = makeXonoticGametypeButton(1, "g_nexball", "Nexball")); - if(e.checked) e0 = NULL; - if(e0) - { - //print("NO CHECK\n"); - e0.setChecked(e0, 1); - } + me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Game type:"))); + me.TR(me); + me.TD(me, 9, 3, e = makeXonoticGametypeList()); + me.TR(me); me.TR(me); me.TR(me); - me.mapListBox = makeXonoticMapList(); - me.TD(me, 1, 3, e = makeXonoticTextLabel(0, "Map list:")); - makeCallback(e, me.mapListBox, me.mapListBox.refilterCallback); me.TR(me); - me.TD(me, me.rows - 7, 3, me.mapListBox); - me.gotoRC(me, me.rows - 3, 0); - me.TDempty(me, 0.5); - me.TD(me, 1, 1, e = makeXonoticButton("All", '0 0 0')); - e.onClick = MapList_All; - e.onClickEntity = me.mapListBox; - me.TD(me, 1, 1, e = makeXonoticButton("None", '0 0 0')); - e.onClick = MapList_None; - e.onClickEntity = me.mapListBox; - me.TDempty(me, 0.5); - - me.gotoRC(me, 3, 3.5); me.setFirstColumn(me, me.currentColumn); - me.TD(me, 1, 3, e = makeXonoticTextLabel(0, "Match settings:")); + me.TR(me); + me.TR(me); + me.TR(me); + me.TR(me); + me.TR(me); + me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Match settings:"))); me.TR(me); me.sliderTimelimit = makeXonoticSlider(1.0, 60.0, 0.5, "timelimit_override"); - me.TD(me, 1, 1, e = makeXonoticSliderCheckBox(0, 1, me.sliderTimelimit, "Time limit:")); + me.TD(me, 1, 1, e = makeXonoticSliderCheckBox(0, 1, me.sliderTimelimit, _("Time limit:"))); me.TD(me, 1, 2, me.sliderTimelimit); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 2.8, e = makeXonoticSliderCheckBox(-1, 0, me.sliderTimelimit, "Use map specified default")); + me.TD(me, 1, 2.8, e = makeXonoticSliderCheckBox(-1, 0, me.sliderTimelimit, _("Use map specified default"))); me.TR(me); me.sliderFraglimit = makeXonoticSlider(1.0, 2000.0, 5, "fraglimit_override"); - me.TD(me, 1, 1, e = makeXonoticSliderCheckBox(0, 1, me.sliderFraglimit, "Point limit:")); + me.TD(me, 1, 1, e = makeXonoticSliderCheckBox(0, 1, me.sliderFraglimit, _("Point limit:"))); me.checkboxFraglimit = e; me.TD(me, 1, 2, me.sliderFraglimit); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 2.8, e = makeXonoticSliderCheckBox(-1, 0, me.sliderFraglimit, "Use map specified default")); + me.TD(me, 1, 2.8, e = makeXonoticSliderCheckBox(-1, 0, me.sliderFraglimit, _("Use map specified default"))); me.checkboxFraglimitMapinfo = e; me.TR(me); - me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Player slots:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Player slots:"))); me.TD(me, 1, 2, makeXonoticSlider(1, 32, 1, "menu_maxplayers")); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Number of bots:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Number of bots:"))); me.TD(me, 1, 2, makeXonoticSlider(0, 9, 1, "bot_number")); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, "Bot skill:")); + me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Bot skill:"))); setDependent(e, "bot_number", 0, -1); me.TD(me, 1, 2, e = makeXonoticTextSlider("skill")); - e.addValue(e, "Botlike", "0"); - e.addValue(e, "Beginner", "1"); - e.addValue(e, "You will win", "2"); - e.addValue(e, "You can win", "3"); - e.addValue(e, "You might win", "4"); - e.addValue(e, "Advanced", "5"); - e.addValue(e, "Expert", "6"); - e.addValue(e, "Pro", "7"); - e.addValue(e, "Assassin", "8"); - e.addValue(e, "Unhuman", "9"); - e.addValue(e, "Godlike", "10"); + e.addValue(e, _("Botlike"), "0"); + e.addValue(e, _("Beginner"), "1"); + e.addValue(e, _("You will win"), "2"); + e.addValue(e, _("You can win"), "3"); + e.addValue(e, _("You might win"), "4"); + e.addValue(e, _("Advanced"), "5"); + e.addValue(e, _("Expert"), "6"); + e.addValue(e, _("Pro"), "7"); + e.addValue(e, _("Assassin"), "8"); + e.addValue(e, _("Unhuman"), "9"); + e.addValue(e, _("Godlike"), "10"); e.configureXonoticTextSliderValues(e); setDependent(e, "bot_number", 0, -1); me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, "Bot names:")); - me.TD(me, 1, 0.7, e = makeXonoticInputBox(1, "bot_prefix")); - setDependent(e, "bot_number", 0, -1); - me.TD(me, 1, 0.6, e = makeXonoticTextLabel(0.5, "Shadow")); - setDependent(e, "bot_number", 0, -1); - me.TD(me, 1, 0.7, e = makeXonoticInputBox(1, "bot_suffix")); - setDependent(e, "bot_number", 0, -1); - me.TR(me); - me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Map voting:")); - me.TD(me, 1, 2, e = makeXonoticTextSlider("g_maplist_votable")); - e.addValue(e, "No voting", "0"); - e.addValue(e, "2 choices", "2"); - e.addValue(e, "3 choices", "3"); - e.addValue(e, "4 choices", "4"); - e.addValue(e, "5 choices", "5"); - e.addValue(e, "6 choices", "6"); - e.addValue(e, "7 choices", "7"); - e.addValue(e, "8 choices", "8"); - e.addValue(e, "9 choices", "9"); - e.configureXonoticTextSliderValues(e); - me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(0.5, 0, "sv_vote_simple_majority_factor", "Simple majority wins vcall")); - me.TR(me); - me.TR(me); - me.TDempty(me, 0.5); - me.TD(me, 1, 2, e = makeXonoticButton("Advanced settings...", '0 0 0')); - e.onClick = DialogOpenButton_Click; - e.onClickEntity = main.advancedDialog; - main.advancedDialog.refilterEntity = me.mapListBox; - me.TR(me); - me.TR(me); - me.TD(me, 1, 1, e = makeXonoticButton("Mutators...", '0 0 0')); + me.TD(me, 1, 1, e = makeXonoticButton(_("Mutators..."), '0 0 0')); e.onClick = DialogOpenButton_Click; e.onClickEntity = main.mutatorsDialog; main.mutatorsDialog.refilterEntity = me.mapListBox; me.TD(me, 1, 2, e0 = makeXonoticTextLabel(0, string_null)); e0.textEntity = main.mutatorsDialog; e0.allowCut = 1; + me.TR(me); + me.TDempty(me, 0.5); + me.TD(me, 1, 2, e = makeXonoticButton(_("Advanced settings..."), '0 0 0')); + e.onClick = DialogOpenButton_Click; + e.onClickEntity = main.advancedDialog; + main.advancedDialog.refilterEntity = me.mapListBox; + + me.gotoRC(me, 0, 3.5); me.setFirstColumn(me, me.currentColumn); + me.mapListBox = makeXonoticMapList(); + me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Map list:"))); + makeCallback(e, me.mapListBox, me.mapListBox.refilterCallback); + me.TR(me); + me.TD(me, me.rows - 4, 3, me.mapListBox); + me.gotoRC(me, me.rows - 3, 3.5); + me.TDempty(me, 0.25); + me.TD(me, 1, 1.125, e = makeXonoticButton(_("Select all"), '0 0 0')); + e.onClick = MapList_All; + e.onClickEntity = me.mapListBox; + me.TD(me, 1, 1.125, e = makeXonoticButton(_("Select none"), '0 0 0')); + e.onClick = MapList_None; + e.onClickEntity = me.mapListBox; + me.TDempty(me, 0.25); me.gotoRC(me, me.rows - 1, 0); - me.TD(me, 1, me.columns, e = makeXonoticButton("Start Multiplayer!", '0 0 0')); + me.TD(me, 1, me.columns, e = makeXonoticButton(_("Start Multiplayer!"), '0 0 0')); e.onClick = MapList_LoadMap; e.onClickEntity = me.mapListBox; me.mapListBox.startButton = e; @@ -208,17 +151,17 @@ void XonoticServerCreateTab_gameTypeChangeNotify(entity me) l2 = me.checkboxFraglimitMapinfo; switch(gt) { - case MAPINFO_TYPE_CTF: GameType_ConfigureSliders(e, l, l2, "Capture limit:", 1, 20, 1, "capturelimit_override"); break; - case MAPINFO_TYPE_DOMINATION: GameType_ConfigureSliders(e, l, l2, "Point limit:", 50, 500, 10, "g_domination_point_limit"); break; - case MAPINFO_TYPE_KEYHUNT: GameType_ConfigureSliders(e, l, l2, "Point limit:", 200, 1500, 50, "g_keyhunt_point_limit"); break; - case MAPINFO_TYPE_RUNEMATCH: GameType_ConfigureSliders(e, l, l2, "Point limit:", 50, 500, 10, "g_runematch_point_limit"); break; - case MAPINFO_TYPE_LMS: GameType_ConfigureSliders(e, l, l2, "Lives:", 3, 50, 1, "g_lms_lives_override"); break; - case MAPINFO_TYPE_RACE: GameType_ConfigureSliders(e, l, l2, "Laps:", 1, 25, 1, "g_race_laps_limit"); break; - case MAPINFO_TYPE_NEXBALL: GameType_ConfigureSliders(e, l, l2, "Goals:", 1, 50, 1, "g_nexball_goallimit"); break; - case MAPINFO_TYPE_ASSAULT: GameType_ConfigureSliders(e, l, l2, "Point limit:", 50, 500, 10, ""); break; - case MAPINFO_TYPE_ONSLAUGHT: GameType_ConfigureSliders(e, l, l2, "Point limit:", 50, 500, 10, ""); break; - case MAPINFO_TYPE_CTS: GameType_ConfigureSliders(e, l, l2, "Point limit:", 50, 500, 10, ""); break; - default: GameType_ConfigureSliders(e, l, l2, "Frag limit:", 5, 100, 5, "fraglimit_override"); break; + case MAPINFO_TYPE_CTF: GameType_ConfigureSliders(e, l, l2, _("Capture limit:"), 1, 20, 1, "capturelimit_override"); break; + case MAPINFO_TYPE_DOMINATION: GameType_ConfigureSliders(e, l, l2, _("Point limit:"), 50, 500, 10, "g_domination_point_limit"); break; + case MAPINFO_TYPE_KEYHUNT: GameType_ConfigureSliders(e, l, l2, _("Point limit:"), 200, 1500, 50, "g_keyhunt_point_limit"); break; + case MAPINFO_TYPE_RUNEMATCH: GameType_ConfigureSliders(e, l, l2, _("Point limit:"), 50, 500, 10, "g_runematch_point_limit"); break; + case MAPINFO_TYPE_LMS: GameType_ConfigureSliders(e, l, l2, _("Lives:"), 3, 50, 1, "g_lms_lives_override"); break; + case MAPINFO_TYPE_RACE: GameType_ConfigureSliders(e, l, l2, _("Laps:"), 1, 25, 1, "g_race_laps_limit"); break; + case MAPINFO_TYPE_NEXBALL: GameType_ConfigureSliders(e, l, l2, _("Goals:"), 1, 50, 1, "g_nexball_goallimit"); break; + case MAPINFO_TYPE_ASSAULT: GameType_ConfigureSliders(e, l, l2, _("Point limit:"), 50, 500, 10, ""); break; + case MAPINFO_TYPE_ONSLAUGHT: GameType_ConfigureSliders(e, l, l2, _("Point limit:"), 50, 500, 10, ""); break; + case MAPINFO_TYPE_CTS: GameType_ConfigureSliders(e, l, l2, _("Point limit:"), 50, 500, 10, ""); break; + default: GameType_ConfigureSliders(e, l, l2, _("Frag limit:"), 5, 100, 5, "fraglimit_override"); break; } me.mapListBox.refilter(me.mapListBox); } diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c b/qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c index 417cfa6108..226f346b64 100644 --- a/qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c +++ b/qcsrc/menu/xonotic/dialog_multiplayer_create_advanced.c @@ -3,10 +3,10 @@ CLASS(XonoticAdvancedDialog) EXTENDS(XonoticDialog) METHOD(XonoticAdvancedDialog, fill, void(entity)) METHOD(XonoticAdvancedDialog, showNotify, void(entity)) METHOD(XonoticAdvancedDialog, close, void(entity)) - ATTRIB(XonoticAdvancedDialog, title, string, "Advanced server settings") + ATTRIB(XonoticAdvancedDialog, title, string, _("Advanced server settings")) ATTRIB(XonoticAdvancedDialog, color, vector, SKINCOLOR_DIALOG_ADVANCED) ATTRIB(XonoticAdvancedDialog, intendedWidth, float, 0.5) - ATTRIB(XonoticAdvancedDialog, rows, float, 12) + ATTRIB(XonoticAdvancedDialog, rows, float, 17) ATTRIB(XonoticAdvancedDialog, columns, float, 3) ATTRIB(XonoticAdvancedDialog, refilterEntity, entity, NULL) ENDCLASS(XonoticAdvancedDialog) @@ -22,42 +22,64 @@ void XonoticAdvancedDialog_fill(entity me) { entity e; me.TR(me); - me.TD(me, 1, 1.2, makeXonoticTextLabel(0, "Game settings:")); + me.TD(me, 1, 3, makeXonoticTextLabel(0, _("Game settings:"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticCheckBox(0, "sv_spectate", "Allow spectating")); + me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "sv_spectate", _("Allow spectating"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Spawn shield:")); - me.TD(me, 1, 1.7, e = makeXonoticSlider(0, 15, 0.5, "g_spawnshieldtime")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Spawn shield:"))); + me.TD(me, 1, 1.6, e = makeXonoticSlider(0, 15, 0.5, "g_spawnshieldtime")); me.TR(me); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Game speed:")); - me.TD(me, 1, 1.7, e = makeXonoticSlider(0.5, 2.0, 0.1, "slowmo")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Game speed:"))); + me.TD(me, 1, 1.6, e = makeXonoticSlider(0.5, 2.0, 0.1, "slowmo")); me.TR(me); me.TR(me); - me.TD(me, 1, 1.2, makeXonoticTextLabel(0, "Teamplay settings:")); + me.TD(me, 1, 3, makeXonoticTextLabel(0, _("Teamplay settings:"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Friendly fire scale:")); - me.TD(me, 1, 1.7, e = makeXonoticSlider(0, 1.0, 0.05, "g_friendlyfire")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Friendly fire scale:"))); + me.TD(me, 1, 1.6, e = makeXonoticSlider(0, 1.0, 0.05, "g_friendlyfire")); + me.TR(me); + me.TDempty(me, 0.4); + me.TD(me, 1, 2.6, e = makeXonoticCheckBox(0, "g_friendlyfire_virtual", _("Virtual friendly fire (effect only)"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Friendly fire penalty:")); - me.TD(me, 1, 1.7, e = makeXonoticSlider(0, 1.0, 0.05, "g_mirrordamage")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Friendly fire penalty:"))); + me.TD(me, 1, 1.6, e = makeXonoticSlider(0, 1.0, 0.05, "g_mirrordamage")); + me.TR(me); + me.TDempty(me, 0.4); + me.TD(me, 1, 2.6, e = makeXonoticCheckBox(0, "g_mirrordamage_virtual", _("Virtual penalty (effect only)"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, "Teams:")); - me.TD(me, 1, 1.7, e = makeXonoticTextSlider("g_tdm_teams_override g_domination_teams_override g_keyhunt_teams_override")); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Teams:"))); + me.TD(me, 1, 1.6, e = makeXonoticTextSlider("g_tdm_teams_override g_domination_teams_override g_keyhunt_teams_override")); e.addValue(e, "Default", "0"); e.addValue(e, "2 teams", "2"); e.addValue(e, "3 teams", "3"); e.addValue(e, "4 teams", "4"); e.configureXonoticTextSliderValues(e); + me.TR(me); + me.TR(me); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Map voting:"))); + me.TD(me, 1, 2, e = makeXonoticTextSlider("g_maplist_votable")); + e.addValue(e, _("No voting"), "0"); + e.addValue(e, _("2 choices"), "2"); + e.addValue(e, _("3 choices"), "3"); + e.addValue(e, _("4 choices"), "4"); + e.addValue(e, _("5 choices"), "5"); + e.addValue(e, _("6 choices"), "6"); + e.addValue(e, _("7 choices"), "7"); + e.addValue(e, _("8 choices"), "8"); + e.addValue(e, _("9 choices"), "9"); + e.configureXonoticTextSliderValues(e); + me.TR(me); + me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(0.5, 0, "sv_vote_simple_majority_factor", _("Simple majority wins vcall"))); me.gotoRC(me, me.rows - 1, 0); - me.TD(me, 1, me.columns, e = makeXonoticButton("OK", '0 0 0')); + me.TD(me, 1, me.columns, e = makeXonoticButton(_("OK"), '0 0 0')); e.onClick = Dialog_Close; e.onClickEntity = me; } diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c b/qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c index f3f620d731..169e9734b1 100644 --- a/qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c +++ b/qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c @@ -2,10 +2,10 @@ CLASS(XonoticMapInfoDialog) EXTENDS(XonoticDialog) METHOD(XonoticMapInfoDialog, fill, void(entity)) METHOD(XonoticMapInfoDialog, loadMapInfo, void(entity, float, entity)) - ATTRIB(XonoticMapInfoDialog, title, string, "Map Information") + ATTRIB(XonoticMapInfoDialog, title, string, _("Map Information")) ATTRIB(XonoticMapInfoDialog, color, vector, SKINCOLOR_DIALOG_MAPINFO) - ATTRIB(XonoticMapInfoDialog, intendedWidth, float, 0.85) - ATTRIB(XonoticMapInfoDialog, rows, float, 9) + ATTRIB(XonoticMapInfoDialog, intendedWidth, float, 1.0) + ATTRIB(XonoticMapInfoDialog, rows, float, 12) ATTRIB(XonoticMapInfoDialog, columns, float, 10) ATTRIB(XonoticMapInfoDialog, previewImage, entity, NULL) @@ -14,22 +14,7 @@ CLASS(XonoticMapInfoDialog) EXTENDS(XonoticDialog) ATTRIB(XonoticMapInfoDialog, descriptionLabel, entity, NULL) ATTRIB(XonoticMapInfoDialog, featuresLabel, entity, NULL) - ATTRIB(XonoticMapInfoDialog, typeDeathmatchLabel, entity, NULL) - ATTRIB(XonoticMapInfoDialog, typeTDMLabel, entity, NULL) - ATTRIB(XonoticMapInfoDialog, typeLMSLabel, entity, NULL) - ATTRIB(XonoticMapInfoDialog, typeArenaLabel, entity, NULL) - ATTRIB(XonoticMapInfoDialog, typeRuneLabel, entity, NULL) - ATTRIB(XonoticMapInfoDialog, typeDominationLabel, entity, NULL) - ATTRIB(XonoticMapInfoDialog, typeKeyHuntLabel, entity, NULL) - ATTRIB(XonoticMapInfoDialog, typeCTFLabel, entity, NULL) - ATTRIB(XonoticMapInfoDialog, typeCALabel, entity, NULL) - ATTRIB(XonoticMapInfoDialog, typeAssaultLabel, entity, NULL) - ATTRIB(XonoticMapInfoDialog, typeOnslaughtLabel, entity, NULL) - ATTRIB(XonoticMapInfoDialog, typeRaceLabel, entity, NULL) - ATTRIB(XonoticMapInfoDialog, typeCTSLabel, entity, NULL) - ATTRIB(XonoticMapInfoDialog, typeNexballLabel, entity, NULL) - ATTRIB(XonoticMapInfoDialog, typeFreezetagLabel, entity, NULL) - ATTRIB(XonoticMapInfoDialog, typeKeepawayLabel, entity, NULL) + ATTRIBARRAY(XonoticMapInfoDialog, typeLabels, entity, 24) ATTRIB(XonoticMapInfoDialog, currentMapIndex, float, 0) ATTRIB(XonoticMapInfoDialog, currentMapBSPName, string, string_null) @@ -61,7 +46,7 @@ void XonoticMapInfoDialog_loadMapInfo(entity me, float i, entity mlb) me.currentMapTitle = strzone(MapInfo_Map_title); me.currentMapAuthor = strzone(MapInfo_Map_author); me.currentMapDescription = strzone(MapInfo_Map_description); - me.currentMapFeaturesText = strzone((MapInfo_Map_supportedFeatures & MAPINFO_FEATURE_WEAPONS) ? "Full item placement" : "MinstaGib only"); + me.currentMapFeaturesText = strzone((MapInfo_Map_supportedFeatures & MAPINFO_FEATURE_WEAPONS) ? _("Full item placement") : _("MinstaGib only")); me.currentMapPreviewImage = strzone(strcat("/maps/", MapInfo_Map_bspname)); me.frame.setText(me.frame, me.currentMapBSPName); @@ -69,91 +54,61 @@ void XonoticMapInfoDialog_loadMapInfo(entity me, float i, entity mlb) me.authorLabel.setText(me.authorLabel, me.currentMapAuthor); me.descriptionLabel.setText(me.descriptionLabel, me.currentMapDescription); me.featuresLabel.setText(me.featuresLabel, me.currentMapFeaturesText); - me.previewImage.src = me.currentMapPreviewImage; + if(draw_PictureSize(me.currentMapPreviewImage) == '0 0 0') + me.previewImage.src = "nopreview_map"; + else + me.previewImage.src = me.currentMapPreviewImage; - me.typeDeathmatchLabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_DEATHMATCH); - me.typeTDMLabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_TEAM_DEATHMATCH); - me.typeLMSLabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_LMS); - me.typeArenaLabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_ARENA); - me.typeDominationLabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_DOMINATION); - me.typeRuneLabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_RUNEMATCH); - me.typeKeyHuntLabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_KEYHUNT); - me.typeCTFLabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_CTF); - me.typeCALabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_CA); - me.typeAssaultLabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_ASSAULT); - me.typeOnslaughtLabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_ONSLAUGHT); - me.typeRaceLabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_RACE); - me.typeCTSLabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_CTS); - me.typeNexballLabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_NEXBALL); - me.typeFreezetagLabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_FREEZETAG); - me.typeKeepawayLabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_KEEPAWAY); + for(i = 0; i < GameType_GetCount(); ++i) + { + entity e; + e = me.(typeLabels[i]); + e.disabled = !(MapInfo_Map_supportedGametypes & GameType_GetID(i)); + } MapInfo_ClearTemps(); } void XonoticMapInfoDialog_fill(entity me) { entity e; - float w, wgt; + float w, wgt, i, n; me.TR(me); me.TDempty(me, 0.2); me.TD(me, me.rows - 2, 3, e = makeXonoticImage(string_null, 4.0/3.0)); me.previewImage = e; me.gotoRC(me, 0, 3.5); me.setFirstColumn(me, me.currentColumn); w = me.columns - me.currentColumn; - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Title:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Title:"))); me.TD(me, 1, w-1, e = makeXonoticTextLabel(0, "")); e.colorL = SKINCOLOR_MAPLIST_TITLE; e.allowCut = 1; me.titleLabel = e; me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Author:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Author:"))); me.TD(me, 1, w-1, e = makeXonoticTextLabel(0, "")); e.colorL = SKINCOLOR_MAPLIST_AUTHOR; e.allowCut = 1; me.authorLabel = e; me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Features:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Features:"))); me.TD(me, 1, w-1, e = makeXonoticTextLabel(0, "")); e.allowCut = 1; me.featuresLabel = e; me.TR(me); - me.TD(me, 1, w, e = makeXonoticTextLabel(0, "Game types:")); - me.TR(me); wgt = (w-0.2)/5; - me.TDempty(me, 0.2); - me.TD(me, 1, wgt, e = makeXonoticTextLabel(0, "DM")); - me.typeDeathmatchLabel = e; - me.TD(me, 1, wgt, e = makeXonoticTextLabel(0, "TDM")); - me.typeTDMLabel = e; - me.TD(me, 1, wgt, e = makeXonoticTextLabel(0, "LMS")); - me.typeLMSLabel = e; - me.TD(me, 1, wgt, e = makeXonoticTextLabel(0, "Arena")); - me.typeArenaLabel = e; - me.TD(me, 1, wgt, e = makeXonoticTextLabel(0, "Domination")); - me.typeDominationLabel = e; - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, wgt, e = makeXonoticTextLabel(0, "Key Hunt")); - me.typeKeyHuntLabel = e; - me.TD(me, 1, wgt, e = makeXonoticTextLabel(0, "CTF")); - me.typeCTFLabel = e; - me.TD(me, 1, wgt, e = makeXonoticTextLabel(0, "CA")); - me.typeCALabel = e; - me.TD(me, 1, wgt, e = makeXonoticTextLabel(0, "Assault")); - me.typeAssaultLabel = e; - me.TD(me, 1, wgt, e = makeXonoticTextLabel(0, "Onslaught")); - me.typeOnslaughtLabel = e; - me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, wgt, e = makeXonoticTextLabel(0, "Race")); - me.typeRaceLabel = e; - me.TD(me, 1, wgt, e = makeXonoticTextLabel(0, "CTS")); - me.typeCTSLabel = e; - me.TD(me, 1, wgt, e = makeXonoticTextLabel(0, "Nexball")); - me.typeNexballLabel = e; - me.TD(me, 1, wgt, e = makeXonoticTextLabel(0, "Freezetag")); - me.typeFreezetagLabel = e; - me.TD(me, 1, wgt, e = makeXonoticTextLabel(0, "Keepaway")); - me.typeKeepawayLabel = e; + me.TD(me, 1, w, e = makeXonoticTextLabel(0, _("Game types:"))); + + n = ceil(GameType_GetCount() / (me.rows - 6)); + wgt = (w - 0.2) / n; + for(i = 0; i < GameType_GetCount(); ++i) + { + if(mod(i, n) == 0) + { + me.TR(me); + me.TDempty(me, 0.2); + } + me.TD(me, 1, wgt, e = makeXonoticTextLabel(0, MapInfo_Type_ToText(GameType_GetID(i)))); + me.(typeLabels[i]) = e; + } me.gotoRC(me, me.rows - 2, 0); me.TD(me, 1, me.columns, e = makeXonoticTextLabel(0.5, "")); @@ -163,10 +118,10 @@ void XonoticMapInfoDialog_fill(entity me) me.gotoRC(me, me.rows - 1, 0); me.TDempty(me, 0.5); - me.TD(me, 1, me.columns - 5.5, e = makeXonoticButton("Close", '0 0 0')); + me.TD(me, 1, me.columns - 5.5, e = makeXonoticButton(_("Close"), '0 0 0')); e.onClick = Dialog_Close; e.onClickEntity = me; - me.TD(me, 1, me.columns - 5.5, me.startButton = e = makeXonoticButton("Play", '0 0 0')); + me.TD(me, 1, me.columns - 5.5, me.startButton = e = makeXonoticButton(ZCTX(_("MAP^Play")), '0 0 0')); me.startButton.onClick = MapList_LoadMap; me.startButton.onClickEntity = NULL; // filled later } diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c b/qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c index 984ae9b265..ac2d71e481 100644 --- a/qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c +++ b/qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c @@ -4,7 +4,7 @@ CLASS(XonoticMutatorsDialog) EXTENDS(XonoticDialog) METHOD(XonoticMutatorsDialog, fill, void(entity)) METHOD(XonoticMutatorsDialog, showNotify, void(entity)) METHOD(XonoticMutatorsDialog, close, void(entity)) - ATTRIB(XonoticMutatorsDialog, title, string, "Mutators") + ATTRIB(XonoticMutatorsDialog, title, string, _("Mutators")) ATTRIB(XonoticMutatorsDialog, color, vector, SKINCOLOR_DIALOG_MUTATORS) ATTRIB(XonoticMutatorsDialog, intendedWidth, float, 0.9) ATTRIB(XonoticMutatorsDialog, rows, float, 17) @@ -30,9 +30,9 @@ string WeaponArenaString() if(s == "0") return ""; if(s == "all") - return "All Weapons Arena"; + return _("All Weapons Arena"); if(s == "most") - return "Most Weapons Arena"; + return _("Most Weapons Arena"); if(s == weaponarenastring_cvar) return weaponarenastring; if(weaponarenastring) @@ -53,7 +53,7 @@ string WeaponArenaString() s = strcat(s, " & ", e.message); } } - s = strcat(substring(s, 3, strlen(s) - 3), " Arena"); + s = sprintf(_("%s Arena"), substring(s, 3, strlen(s) - 3)); weaponarenastring = strzone(s); @@ -65,37 +65,43 @@ string XonoticMutatorsDialog_toString(entity me) string s; s = ""; if(cvar("g_dodging")) - s = strcat(s, ", Dodging"); + s = strcat(s, ", ", _("Dodging")); if(cvar("g_minstagib")) - s = strcat(s, ", MinstaGib"); + s = strcat(s, ", ", _("MinstaGib")); if(cvar("g_nix")) - s = strcat(s, ", NIX"); + s = strcat(s, ", ", _("NIX")); if(cvar("g_rocket_flying")) - s = strcat(s, ", Rocket Flying"); + s = strcat(s, ", ", _("Rocket Flying")); + if(cvar("g_invincible_projectiles")) + s = strcat(s, ", ", _("Invincible Projectiles")); if(cvar_string("g_weaponarena") != "0") s = strcat(s, ", ", WeaponArenaString()); if(cvar("g_start_weapon_laser") == 0) - s = strcat(s, ", No start weapons"); + s = strcat(s, ", ", _("No start weapons")); if(cvar("sv_gravity") < 800) - s = strcat(s, ", Low gravity"); + s = strcat(s, ", ", _("Low gravity")); if(cvar("g_cloaked")) - s = strcat(s, ", Cloaked"); + s = strcat(s, ", ", _("Cloaked")); if(cvar("g_grappling_hook")) - s = strcat(s, ", Hook"); + s = strcat(s, ", ", _("Hook")); if(cvar("g_midair")) - s = strcat(s, ", Midair"); + s = strcat(s, ", ", _("Midair")); if(cvar("g_vampire")) - s = strcat(s, ", Vampire"); + s = strcat(s, ", ", _("Vampire")); if(cvar("g_pinata")) - s = strcat(s, ", Pinata"); + s = strcat(s, ", ", _("Piñata")); if(cvar("g_weapon_stay")) - s = strcat(s, ", Weapons stay"); + s = strcat(s, ", ", _("Weapons stay")); if(cvar("g_bloodloss") > 0) - s = strcat(s, ", Bloodloss"); + s = strcat(s, ", ", _("Blood loss")); if(cvar("g_jetpack")) - s = strcat(s, ", Jet pack"); + s = strcat(s, ", ", _("Jet pack")); + if(cvar("g_powerups") == 0) + s = strcat(s, ", ", _("No powerups")); + if(cvar("g_powerups") > 0) + s = strcat(s, ", ", _("Powerups")); if(s == "") - return "None"; + return ZCTX(_("MUT^None")); else return substring(s, 2, strlen(s) - 2); } @@ -161,23 +167,23 @@ void XonoticMutatorsDialog_fill(entity me) float i, j; string str, hstr; me.TR(me); - me.TD(me, 1, 2, makeXonoticTextLabel(0, "Gameplay mutators:")); + me.TD(me, 1, 2, makeXonoticTextLabel(0, _("Gameplay mutators:"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_dodging", "Dodging")); + me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_dodging", _("Dodging"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_cloaked", "Cloaked")); + me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_cloaked", _("Cloaked"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_midair", "Midair")); + me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_midair", _("Midair"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_vampire", "Vampire")); + me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_vampire", _("Vampire"))); me.TR(me); me.TDempty(me, 0.2); s = makeXonoticSlider(10, 50, 1, "g_bloodloss"); - me.TD(me, 1, 2, e = makeXonoticSliderCheckBox(0, 1, s, "Blood loss")); + me.TD(me, 1, 2, e = makeXonoticSliderCheckBox(0, 1, s, _("Blood loss"))); me.TR(me); me.TDempty(me, 0.4); me.TD(me, 1, 1.8, s); @@ -186,36 +192,38 @@ void XonoticMutatorsDialog_fill(entity me) s = makeXonoticSlider(80, 400, 8, "sv_gravity"); s.valueDigits = 0; s.valueDisplayMultiplier = 0.125; // show gravity in percent - me.TD(me, 1, 2, e = makeXonoticSliderCheckBox(800, 1, s, "Low gravity")); + me.TD(me, 1, 2, e = makeXonoticSliderCheckBox(800, 1, s, _("Low gravity"))); e.savedValue = 200; // good on silvercity me.TR(me); me.TDempty(me, 0.4); me.TD(me, 1, 1.8, s); me.TR(me); + me.TD(me, 1, 2, makeXonoticTextLabel(0, _("Weapon & item mutators:"))); me.TR(me); - me.TD(me, 1, 2, makeXonoticTextLabel(0, "Weapon & item mutators:")); + me.TDempty(me, 0.2); + me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_grappling_hook", _("Grappling hook"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_grappling_hook", "Grappling hook")); + me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_jetpack", _("Jet pack"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_jetpack", "Jet pack")); + me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_invincible_projectiles", _("Invincible Projectiles"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_rocket_flying", "Rocket Flying")); + me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_rocket_flying", _("Rocket Flying"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_pinata", "Pinata")); + me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_pinata", _("Piñata"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 2, e = makeXonoticCheckBoxEx(2, 0, "g_weapon_stay", "Weapons stay")); + me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_weapon_stay", _("Weapons stay"))); me.TR(me); me.gotoRC(me, 0, 2); me.setFirstColumn(me, me.currentColumn); - me.TD(me, 1, 4, makeXonoticTextLabel(0, "Weapon arenas:")); + me.TD(me, 1, 4, makeXonoticTextLabel(0, _("Weapon arenas:"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 2, e = makeXonoticRadioButton(1, string_null, string_null, "Regular (no arena)")); + me.TD(me, 1, 2, e = makeXonoticRadioButton(1, string_null, string_null, _("Regular (no arena)"))); for(i = WEP_FIRST, j = 0; i <= WEP_LAST; ++i) { w = get_weaponinfo(i); @@ -236,7 +244,7 @@ void XonoticMutatorsDialog_fill(entity me) } me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "menu_weaponarena_with_laser", "with laser")); + me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "menu_weaponarena_with_laser", _("with laser"))); // hook the draw function to gray it out e.draw_weaponarena = e.draw; e.draw = preDrawLaserWeaponArenaLaserButton; @@ -244,29 +252,29 @@ void XonoticMutatorsDialog_fill(entity me) e.saveCvars_weaponarena = e.saveCvars; e.saveCvars = saveCvarsLaserWeaponArenaLaserButton; me.TR(me); - me.TD(me, 1, 4, makeXonoticTextLabel(0, "Special arenas:")); + me.TD(me, 1, 4, makeXonoticTextLabel(0, _("Special arenas:"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "g_minstagib", string_null, "MinstaGib")); + me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "g_minstagib", string_null, _("MinstaGib"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "g_nix", string_null, "NIX")); + me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "g_nix", string_null, _("NIX"))); me.TR(me); me.TDempty(me, 0.4); - me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "g_nix_with_laser", "with laser")); + me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "g_nix_with_laser", _("with laser"))); setDependent(e, "g_nix", 1, 1); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "g_weaponarena", "most", "Most weapons")); + me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "g_weaponarena", "most", _("Most weapons"))); e.cvarOffValue = "0"; me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "g_start_weapon_laser", "0", "No start weapons")); + me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "g_start_weapon_laser", "0", _("No start weapons"))); e.cvarOffValue = "-1"; - makeMulti(e, "g_start_weapon_shotgun g_start_weapon_uzi g_start_weapon_grenadelauncher g_start_weapon_minelayer g_start_weapon_electro g_start_weapon_crylink g_start_weapon_nex g_start_weapon_hagar g_start_weapon_rocketlauncher g_start_weapon_campingrifle g_start_weapon_hlac g_start_weapon_seeker g_start_weapon_minstanex g_start_weapon_hook g_start_weapon_porto g_start_weapon_tuba"); + makeMulti(e, "g_start_weapon_shotgun g_start_weapon_uzi g_start_weapon_grenadelauncher g_start_weapon_minelayer g_start_weapon_electro g_start_weapon_crylink g_start_weapon_nex g_start_weapon_hagar g_start_weapon_rocketlauncher g_start_weapon_rifle g_start_weapon_hlac g_start_weapon_seeker g_start_weapon_minstanex g_start_weapon_hook g_start_weapon_porto g_start_weapon_tuba g_start_weapon_minelayer"); me.gotoRC(me, me.rows - 1, 0); - me.TD(me, 1, me.columns, e = makeXonoticButton("OK", '0 0 0')); + me.TD(me, 1, me.columns, e = makeXonoticButton(_("OK"), '0 0 0')); e.onClick = Dialog_Close; e.onClickEntity = me; } diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_demo.c b/qcsrc/menu/xonotic/dialog_multiplayer_demo.c index ec57b7fca8..99f5a179b5 100644 --- a/qcsrc/menu/xonotic/dialog_multiplayer_demo.c +++ b/qcsrc/menu/xonotic/dialog_multiplayer_demo.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticDemoBrowserTab) EXTENDS(XonoticTab) METHOD(XonoticDemoBrowserTab, fill, void(entity)) - ATTRIB(XonoticDemoBrowserTab, title, string, "Demo") + ATTRIB(XonoticDemoBrowserTab, title, string, _("Demo")) ATTRIB(XonoticDemoBrowserTab, intendedWidth, float, 0.9) ATTRIB(XonoticDemoBrowserTab, rows, float, 22) ATTRIB(XonoticDemoBrowserTab, columns, float, 6.5) @@ -25,12 +25,12 @@ void XonoticDemoBrowserTab_fill(entity me) entity dlist; me.TR(me); - me.TD(me, 1, me.columns, e = makeXonoticCheckBox(0, "cl_autodemo", "Record demos while playing")); + me.TD(me, 1, me.columns, e = makeXonoticCheckBox(0, "cl_autodemo", _("Record demos while playing"))); me.TR(me); dlist = makeXonoticDemoList(); me.TR(me); - me.TD(me, 1, 0.5, e = makeXonoticTextLabel(0, "Filter:")); - me.TD(me, 1, 0.5, btn = makeXonoticButton("Clear", '0 0 0')); + me.TD(me, 1, 0.5, e = makeXonoticTextLabel(0, _("Filter:"))); + me.TD(me, 1, 0.5, btn = makeXonoticButton(_("Clear"), '0 0 0')); btn.onClick = InputBox_Clear_Click; me.TD(me, 1, me.columns - 1, e = makeXonoticInputBox(0, string_null)); e.onChange = DemoList_Filter_Change; @@ -40,10 +40,10 @@ void XonoticDemoBrowserTab_fill(entity me) me.TR(me); me.TD(me, me.rows - 4, me.columns, dlist); me.gotoRC(me, me.rows - 1, 0); - me.TD(me, 1, me.columns / 2, e = makeXonoticButton("Timedemo", '0 0 0')); + me.TD(me, 1, me.columns / 2, e = makeXonoticButton(_("Timedemo"), '0 0 0')); e.onClick = TimeDemo_Click; e.onClickEntity = dlist; - me.TD(me, 1, me.columns / 2, e = makeXonoticButton("Play", '0 0 0')); + me.TD(me, 1, me.columns / 2, e = makeXonoticButton(ZCTX(_("DEMO^Play")), '0 0 0')); e.onClick = StartDemo_Click; e.onClickEntity = dlist; } diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_join.c b/qcsrc/menu/xonotic/dialog_multiplayer_join.c index 799d33455f..ee451744fb 100644 --- a/qcsrc/menu/xonotic/dialog_multiplayer_join.c +++ b/qcsrc/menu/xonotic/dialog_multiplayer_join.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticServerListTab) EXTENDS(XonoticTab) METHOD(XonoticServerListTab, fill, void(entity)) - ATTRIB(XonoticServerListTab, title, string, "Join") + ATTRIB(XonoticServerListTab, title, string, _("Join")) ATTRIB(XonoticServerListTab, intendedWidth, float, 0.9) ATTRIB(XonoticServerListTab, rows, float, 22) ATTRIB(XonoticServerListTab, columns, float, 6.5) @@ -25,23 +25,23 @@ void XonoticServerListTab_fill(entity me) slist = makeXonoticServerList(); me.TR(me); - me.TD(me, 1, 0.4, e = makeXonoticTextLabel(0, "Filter:")); - me.TD(me, 1, 0.6, btn = makeXonoticButton("Clear", '0 0 0')); + me.TD(me, 1, 0.4, e = makeXonoticTextLabel(0, _("Filter:"))); + me.TD(me, 1, 0.6, btn = makeXonoticButton(_("Clear"), '0 0 0')); btn.onClick = InputBox_Clear_Click; me.TD(me, 1, me.columns - 0.6 * 4 - 0.4, e = makeXonoticInputBox(0, string_null)); e.onChange = ServerList_Filter_Change; e.onChangeEntity = slist; btn.onClickEntity = e; slist.controlledTextbox = e; - me.TD(me, 1, 0.6, e = makeXonoticCheckBox(0, "menu_slist_showempty", "Empty")); + me.TD(me, 1, 0.6, e = makeXonoticCheckBox(0, "menu_slist_showempty", ZCTX(_("SRVS^Empty")))); slist.filterShowEmpty = e.checked; e.onClickEntity = slist; e.onClick = ServerList_ShowEmpty_Click; - me.TD(me, 1, 0.6, e = makeXonoticCheckBox(0, "menu_slist_showfull", "Full")); + me.TD(me, 1, 0.6, e = makeXonoticCheckBox(0, "menu_slist_showfull", ZCTX(_("SRVS^Full")))); slist.filterShowFull = e.checked; e.onClickEntity = slist; e.onClick = ServerList_ShowFull_Click; - me.TD(me, 1, 0.6, e = makeXonoticCheckBox(0, "net_slist_pause", "Pause")); + me.TD(me, 1, 0.6, e = makeXonoticCheckBox(0, "net_slist_pause", _("Pause"))); me.TR(me); me.TD(me, 1, 1, slist.sortButton1 = makeXonoticButton(string_null, '0 0 0')); @@ -53,21 +53,23 @@ void XonoticServerListTab_fill(entity me) me.TD(me, me.rows - 4, me.columns, slist); me.gotoRC(me, me.rows - 2, 0); - me.TD(me, 1, 0.6, e = makeXonoticTextLabel(0, "Address:")); + me.TD(me, 1, 0.6, e = makeXonoticTextLabel(0, _("Address:"))); me.TD(me, 1, 2.9, e = makeXonoticInputBox(0, string_null)); e.onEnter = ServerList_Connect_Click; e.onEnterEntity = slist; + e.onChange = ServerList_Update_favoriteButton; + e.onChangeEntity = slist; slist.ipAddressBox = e; me.TD(me, 1, 1.5, e = makeXonoticButton("", '0 0 0')); e.onClick = ServerList_Favorite_Click; e.onClickEntity = slist; slist.favoriteButton = e; - me.TD(me, 1, 1.5, e = makeXonoticButton("Info", '0 0 0')); + me.TD(me, 1, 1.5, e = makeXonoticButton(_("Info..."), '0 0 0')); e.onClick = ServerList_Info_Click; e.onClickEntity = slist; slist.infoButton = e; me.TR(me); - me.TD(me, 1, me.columns, e = makeXonoticButton("Join!", '0 0 0')); + me.TD(me, 1, me.columns, e = makeXonoticButton(_("Join!"), '0 0 0')); e.onClick = ServerList_Connect_Click; e.onClickEntity = slist; slist.connectButton = e; diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c b/qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c index 5f6262cf45..8bf090fe4b 100644 --- a/qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c +++ b/qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.c @@ -2,9 +2,9 @@ CLASS(XonoticServerInfoDialog) EXTENDS(XonoticDialog) METHOD(XonoticServerInfoDialog, fill, void(entity)) METHOD(XonoticServerInfoDialog, loadServerInfo, void(entity, float)) - ATTRIB(XonoticServerInfoDialog, title, string, "Server Information") + ATTRIB(XonoticServerInfoDialog, title, string, _("Server Information")) ATTRIB(XonoticServerInfoDialog, color, vector, SKINCOLOR_DIALOG_SERVERINFO) - ATTRIB(XonoticServerInfoDialog, intendedWidth, float, 0.68) + ATTRIB(XonoticServerInfoDialog, intendedWidth, float, 0.8) ATTRIB(XonoticServerInfoDialog, rows, float, 15) ATTRIB(XonoticServerInfoDialog, columns, float, 12) @@ -56,8 +56,8 @@ void Join_Click(entity btn, entity me); #ifdef IMPLEMENTATION void XonoticServerInfoDialog_loadServerInfo(entity me, float i) { - float m, pure, j; - string s, typestr, versionstr, numh, maxp, k, v; + float m, pure, freeslots, j, numh, maxp, numb, sflags; + string s, typestr, versionstr, k, v; if(me.currentServerName) strunzone(me.currentServerName); @@ -112,8 +112,8 @@ void XonoticServerInfoDialog_loadServerInfo(entity me, float i) me.cnameLabel.setText(me.cnameLabel, me.currentServerCName); pure = -1; - typestr = "N/A"; - versionstr = "N/A"; + typestr = _("N/A"); + versionstr = _("N/A"); SLIST_FIELD_QCSTATUS = gethostcacheindexforkey("qcstatus"); s = gethostcachestring(SLIST_FIELD_QCSTATUS, i); @@ -123,6 +123,8 @@ void XonoticServerInfoDialog_loadServerInfo(entity me, float i) typestr = argv(0); versionstr = argv(1); } + freeslots = -1; + sflags = -1; for(j = 2; j < m; ++j) { if(argv(j) == "") @@ -131,6 +133,10 @@ void XonoticServerInfoDialog_loadServerInfo(entity me, float i) v = substring(argv(j), 1, -1); if(k == "P") pure = stof(v); + else if(k == "S") + freeslots = stof(v); + else if(k == "F") + sflags = stof(v); } me.currentServerType = strzone(typestr); @@ -145,14 +151,17 @@ void XonoticServerInfoDialog_loadServerInfo(entity me, float i) me.rawPlayerList.setPlayerList(me.rawPlayerList, me.currentServerPlayers); SLIST_FIELD_NUMHUMANS = gethostcacheindexforkey("numhumans"); - numh = ftos(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i)); + numh = gethostcachenumber(SLIST_FIELD_NUMHUMANS, i); SLIST_FIELD_MAXPLAYERS = gethostcacheindexforkey("maxplayers"); - maxp = ftos(gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i)); - me.currentServerNumPlayers = strzone(strcat(numh,"/",maxp)); + maxp = gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i); + SLIST_FIELD_NUMBOTS = gethostcacheindexforkey("numbots"); + numb = gethostcachenumber(SLIST_FIELD_NUMBOTS, i); + if(freeslots < 0) + freeslots = maxp - numh - numb; + me.currentServerNumPlayers = strzone(sprintf(_("%d/%d, %d free player slots"), numh, maxp, freeslots)); me.numPlayersLabel.setText(me.numPlayersLabel, me.currentServerNumPlayers); - SLIST_FIELD_NUMBOTS = gethostcacheindexforkey("numbots"); - s = ftos(gethostcachenumber(SLIST_FIELD_NUMBOTS, i)); + s = ftos(numb); me.currentServerNumBots = strzone(s); me.numBotsLabel.setText(me.numBotsLabel, me.currentServerNumBots); @@ -163,7 +172,7 @@ void XonoticServerInfoDialog_loadServerInfo(entity me, float i) me.currentServerVersion = strzone(versionstr); me.versionLabel.setText(me.versionLabel, me.currentServerVersion); - me.currentServerPure = ((pure < 0) ? "N/A" : (pure == 0) ? "Official settings" : sprintf("%d modified settings", pure)); + me.currentServerPure = ((pure < 0) ? "N/A" : (pure == 0) ? _("Official settings") : sprintf(_("%d modified settings"), pure)); me.currentServerPure = strzone(me.currentServerPure); me.pureLabel.setText(me.pureLabel, me.currentServerPure); @@ -174,13 +183,13 @@ void XonoticServerInfoDialog_loadServerInfo(entity me, float i) s = crypto_getidfp(me.currentServerCName); if not(s) - s = "N/A"; + s = _("N/A"); me.currentServerID = strzone(s); me.idLabel.setText(me.idLabel, me.currentServerID); s = crypto_getkeyfp(me.currentServerCName); if not(s) - s = "N/A"; + s = _("N/A"); me.currentServerKey = strzone(s); me.keyLabel.setText(me.keyLabel, me.currentServerKey); @@ -188,35 +197,35 @@ void XonoticServerInfoDialog_loadServerInfo(entity me, float i) if(s == "") { if(cvar("crypto_aeslevel") >= 3) - me.currentServerEncrypt = "N/A (can't connect)"; + me.currentServerEncrypt = _("N/A (can't connect)"); else - me.currentServerEncrypt = "N/A"; + me.currentServerEncrypt = _("N/A"); } else switch(stof(substring(s, 0, 1))) { case 0: if(cvar("crypto_aeslevel") >= 3) - me.currentServerEncrypt = "not supported (can't connect)"; + me.currentServerEncrypt = _("not supported (can't connect)"); else - me.currentServerEncrypt = "not supported (won't encrypt)"; + me.currentServerEncrypt = _("not supported (won't encrypt)"); break; case 1: if(cvar("crypto_aeslevel") >= 2) - me.currentServerEncrypt = "supported (will encrypt)"; + me.currentServerEncrypt = _("supported (will encrypt)"); else - me.currentServerEncrypt = "supported (won't encrypt)"; + me.currentServerEncrypt = _("supported (won't encrypt)"); break; case 2: if(cvar("crypto_aeslevel") >= 1) - me.currentServerEncrypt = "requested (will encrypt)"; + me.currentServerEncrypt = _("requested (will encrypt)"); else - me.currentServerEncrypt = "requested (won't encrypt)"; + me.currentServerEncrypt = _("requested (won't encrypt)"); break; case 3: if(cvar("crypto_aeslevel") <= 0) - me.currentServerEncrypt = "required (can't connect)"; + me.currentServerEncrypt = _("required (can't connect)"); else - me.currentServerEncrypt = "required (will encrypt)"; + me.currentServerEncrypt = _("required (will encrypt)"); break; } me.encryptLabel.setText(me.encryptLabel, me.currentServerEncrypt); @@ -237,7 +246,7 @@ void XonoticServerInfoDialog_fill(entity me) me.cnameLabel = e; me.TR(me); - me.TD(me, 1, 5.5, e = makeXonoticTextLabel(0, "Players:")); + me.TD(me, 1, 5.5, e = makeXonoticTextLabel(0, _("Players:"))); me.TR(me); me.TD(me, me.rows - 4, 6, e = makeXonoticPlayerList()); me.rawPlayerList = e; @@ -245,70 +254,70 @@ void XonoticServerInfoDialog_fill(entity me) me.gotoRC(me, 1, 6.25); me.setFirstColumn(me, me.currentColumn); me.TR(me); - me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, "Type:")); + me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, _("Type:"))); me.TD(me, 1, 4.0, e = makeXonoticTextLabel(0, "")); e.allowCut = 1; me.typeLabel = e; me.TR(me); - me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, "Map:")); + me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, _("Map:"))); me.TD(me, 1, 4.0, e = makeXonoticTextLabel(0, "")); e.allowCut = 1; me.mapLabel = e; me.TR(me); - me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, "Gameplay:")); + me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, _("Gameplay:"))); me.TD(me, 1, 4.0, e = makeXonoticTextLabel(0, "")); e.allowCut = 1; me.pureLabel = e; me.TR(me); - me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, "Players:")); + me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, _("Players:"))); me.TD(me, 1, 4.0, e = makeXonoticTextLabel(0, "")); e.allowCut = 1; me.numPlayersLabel = e; me.TR(me); - me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, "Bots:")); + me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, _("Bots:"))); me.TD(me, 1, 4.0, e = makeXonoticTextLabel(0, "")); e.allowCut = 1; me.numBotsLabel = e; me.TR(me); - me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, "Mod:")); + me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, _("Mod:"))); me.TD(me, 1, 4.0, e = makeXonoticTextLabel(0, "")); e.allowCut = 1; me.modLabel = e; me.TR(me); - me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, "Version:")); + me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, _("Version:"))); me.TD(me, 1, 4.0, e = makeXonoticTextLabel(0, "")); e.allowCut = 1; me.versionLabel = e; me.TR(me); - me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, "Ping:")); + me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, _("Ping:"))); me.TD(me, 1, 4.0, e = makeXonoticTextLabel(0, "")); e.allowCut = 1; me.pingLabel = e; me.TR(me); - me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, "CA:")); + me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, _("CA:"))); me.TD(me, 1, 4.0, e = makeXonoticTextLabel(0, "")); e.allowCut = 1; me.keyLabel = e; me.TR(me); - me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, "Key:")); + me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, _("Key:"))); me.TD(me, 1, 4.0, e = makeXonoticTextLabel(0, "")); e.allowCut = 1; me.idLabel = e; me.TR(me); - me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, "Encryption:")); + me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, _("Encryption:"))); me.TD(me, 1, 4.0, e = makeXonoticTextLabel(0, "")); e.allowCut = 1; me.encryptLabel = e; me.gotoRC(me, me.rows - 1, 0); - me.TD(me, 1, me.columns - 6, e = makeXonoticButton("Close", '0 0 0')); + me.TD(me, 1, me.columns - 6, e = makeXonoticButton(_("Close"), '0 0 0')); e.onClick = Dialog_Close; e.onClickEntity = me; - me.TD(me, 1, me.columns - 6, e = makeXonoticButton("Join!", '0 0 0')); + me.TD(me, 1, me.columns - 6, e = makeXonoticButton(_("Join!"), '0 0 0')); e.onClick = Join_Click; e.onClickEntity = me; } diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c b/qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c index 586896171e..6365081658 100644 --- a/qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c +++ b/qcsrc/menu/xonotic/dialog_multiplayer_playersetup.c @@ -2,7 +2,7 @@ CLASS(XonoticPlayerSettingsTab) EXTENDS(XonoticTab) METHOD(XonoticPlayerSettingsTab, fill, void(entity)) METHOD(XonoticPlayerSettingsTab, draw, void(entity)) - ATTRIB(XonoticPlayerSettingsTab, title, string, "Player Setup") + ATTRIB(XonoticPlayerSettingsTab, title, string, _("Player Setup")) ATTRIB(XonoticPlayerSettingsTab, intendedWidth, float, 0.9) ATTRIB(XonoticPlayerSettingsTab, rows, float, 22) ATTRIB(XonoticPlayerSettingsTab, columns, float, 6.5) @@ -37,7 +37,7 @@ void XonoticPlayerSettingsTab_fill(entity me) float i, r, m, n; me.TR(me); - me.TD(me, 1, 0.5, me.playerNameLabel = makeXonoticTextLabel(0, "Name:")); + me.TD(me, 1, 0.5, me.playerNameLabel = makeXonoticTextLabel(0, _("Name:"))); me.playerNameLabelAlpha = me.playerNameLabel.alpha; me.TD(me, 1, 2.5, label = makeXonoticTextLabel(0, string_null)); label.allowCut = 1; @@ -46,7 +46,8 @@ void XonoticPlayerSettingsTab_fill(entity me) me.TR(me); me.TD(me, 1, 3.0, box = makeXonoticInputBox(1, "_cl_name")); box.forbiddenCharacters = "\r\n\\\"$"; // don't care, isn't getting saved - box.maxLength = -63; // negativ means encoded length in bytes + box.maxLength = -127; // negative means encoded length in bytes + box.saveImmediately = 1; label.textEntity = box; me.TR(me); me.TD(me, 5, 1, e = makeXonoticColorpicker(box)); @@ -59,17 +60,17 @@ void XonoticPlayerSettingsTab_fill(entity me) me.TR(me); me.gotoRC(me, 8, 0.0); pms = makeXonoticPlayerModelSelector(); - me.TD(me, 1, 0.6, e = makeXonoticTextLabel(1, "Model:")); + me.TD(me, 1, 0.6, e = makeXonoticTextLabel(1, _("Model:"))); me.TD(me, 1, 0.3, e = makeXonoticButton("<<", '0 0 0')); e.onClick = PlayerModelSelector_Prev_Click; e.onClickEntity = pms; - me.TD(me, me.rows - me.currentRow - 1, 1.8, pms); + me.TD(me, me.rows - (me.currentRow + 3), 1.8, pms); me.TD(me, 1, 0.3, e = makeXonoticButton(">>", '0 0 0')); e.onClick = PlayerModelSelector_Next_Click; e.onClickEntity = pms; me.TR(me); r = me.currentRow; - m = me.rows - r - 2; + m = me.rows - (r + 4); n = 16 - !cvar("developer"); m = m / (n - 1); for(i = 0; i < n; ++i) @@ -82,115 +83,120 @@ void XonoticPlayerSettingsTab_fill(entity me) me.gotoRC(me, r + i * m, 0.4); me.TDNoMargin(me, m, 0.2, e = makeXonoticColorButton(2, 1, i), '0 1 0'); } + me.gotoRC(me, me.rows - 3, 0); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_forceplayermodels", _("Force player models to mine"))); + me.TR(me); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_forceplayercolors", _("Force player colors to mine"))); me.gotoRC(me, 0, 3.5); me.setFirstColumn(me, me.currentColumn); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Field of view:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Field of view:"))); me.TD(me, 1, 2, e = makeXonoticSlider(60, 130, 1, "fov")); me.TR(me); sl = makeXonoticSlider(0.45, 0.75, 0.01, "cl_bobcycle"); - me.TD(me, 1, 1, e = makeXonoticSliderCheckBox(0, 1, sl, "View bobbing:")); + me.TD(me, 1, 1, e = makeXonoticSliderCheckBox(0, 1, sl, _("View bobbing:"))); makeMulti(sl, "cl_bob2cycle"); me.TD(me, 1, 2, sl); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Zoom factor:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Zoom factor:"))); me.TD(me, 1, 2, e = makeXonoticSlider(2, 16, 0.5, "cl_zoomfactor")); me.TR(me); sl = makeXonoticSlider(1, 8, 0.5, "cl_zoomspeed"); - me.TD(me, 1, 1, e = makeXonoticSliderCheckBox(-1, 1, sl, "Zoom speed:")); + me.TD(me, 1, 1, e = makeXonoticSliderCheckBox(-1, 1, sl, _("Zoom speed:"))); me.TD(me, 1, 2, sl); me.TR(me); - me.TD(me, 1, 1.5, e = makeXonoticButton("Weapon settings...", '0 0 0')); + me.TD(me, 1, 1.5, e = makeXonoticButton(_("Weapon settings..."), '0 0 0')); e.onClick = DialogOpenButton_Click; e.onClickEntity = main.weaponsDialog; me.TD(me, 1, 1.5, e0 = makeXonoticTextLabel(0, string_null)); e0.textEntity = main.weaponsDialog; e0.allowCut = 1; me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Crosshair:")); - me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "crosshair_per_weapon", "Per weapon")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Crosshair:"))); + me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "crosshair_per_weapon", _("Per weapon"))); me.TR(me); me.TDempty(me, 0.2); - for(i = 1; i <= 10; ++i) { - me.TDNoMargin(me, 1, 2 / 10, e = makeXonoticCrosshairButton(3, i), '1 1 0'); + for(i = 1; i <= 14; ++i) { + me.TDNoMargin(me, 1, 2 / 14, e = makeXonoticCrosshairButton(3, i), '1 1 0'); setDependent(e, "crosshair_per_weapon", 0, 0); } // show a larger preview of the selected crosshair me.TDempty(me, 0.2); - me.TDNoMargin(me, 2, 2 / 5, e = makeXonoticCrosshairButton(4, -1), '1 1 0'); // crosshair -1 makes this a preview + me.TDNoMargin(me, 2, 2 / 5, e = makeXonoticCrosshairButton(7, -1), '1 1 0'); // crosshair -1 makes this a preview setDependent(e, "crosshair_per_weapon", 0, 0); me.TR(me); me.TDempty(me, 0.2); - for(i = 11; i <= 20; ++i) { - me.TDNoMargin(me, 1, 2 / 10, e = makeXonoticCrosshairButton(3, i), '1 1 0'); + for(i = 15; i <= 28; ++i) { + me.TDNoMargin(me, 1, 2 / 14, e = makeXonoticCrosshairButton(3, i), '1 1 0'); setDependent(e, "crosshair_per_weapon", 0, 0); } me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Crosshair size:")); - me.TD(me, 1, 1.8, e = makeXonoticSlider(0.10, 1.5, 0.05, "crosshair_size")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Crosshair size:"))); + me.TD(me, 1, 1.8, e = makeXonoticSlider(0.1, 1.0, 0.01, "crosshair_size")); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Crosshair alpha:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Crosshair alpha:"))); me.TD(me, 1, 1.8, e = makeXonoticSlider(0, 1, 0.1, "crosshair_alpha")); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Crosshair color:")); - me.TD(me, 2, 1.8, e = makeXonoticColorpickerString("crosshair_color", "crosshair_color")); - setDependent(e, "crosshair_color_per_weapon", 0, 0); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Crosshair color:"))); + me.TD(me, 1, 0.9, e = makeXonoticRadioButton(4, "crosshair_color_per_weapon", string_null, _("Per weapon"))); + me.TD(me, 1, 0.9, e = makeXonoticRadioButton(4, "crosshair_color_by_health", string_null, _("By health"))); me.TR(me); me.TDempty(me, 0.3); - me.TD(me, 1, 0.7, e = makeXonoticCheckBox(0, "crosshair_color_per_weapon", "Per weapon")); + me.TD(me, 1, 0.9, e = makeXonoticRadioButton(4, string_null, string_null, _("Custom"))); + me.TD(me, 2, 1.8, e = makeXonoticColorpickerString("crosshair_color", "crosshair_color")); + setDependentAND(e, "crosshair_color_per_weapon", 0, 0, "crosshair_color_by_health", 0, 0); + me.TR(me); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "crosshair_dot", "Enable centered dot")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "crosshair_dot", _("Enable center dot"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 0.5, e = makeXonoticTextLabel(0, "Size:")); + me.TD(me, 1, 0.5, e = makeXonoticTextLabel(0, _("Size:"))); me.TD(me, 1, 0.9, e = makeXonoticSlider(0.2, 2, 0.1, "crosshair_dot_size")); setDependent(e, "crosshair_dot", 1, 1); - me.TD(me, 1, 0.5, e = makeXonoticTextLabel(0, "Alpha:")); + me.TD(me, 1, 0.5, e = makeXonoticTextLabel(0, _("Alpha:"))); me.TD(me, 1, 0.9, e = makeXonoticSlider(0.10, 1, 0.1, "crosshair_dot_alpha")); setDependent(e, "crosshair_dot", 1, 1); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Hit test:")); - me.TD(me, 1, 2/3, e = makeXonoticRadioButton(5, "crosshair_hittest", "0", "None")); - me.TD(me, 1, 2/3, e = makeXonoticRadioButton(5, "crosshair_hittest", "1", "TrueAim")); - me.TD(me, 1, 2/3, e = makeXonoticRadioButton(5, "crosshair_hittest", "1.25", "Enemies")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Hit test:"))); + me.TD(me, 1, 2/3, e = makeXonoticRadioButton(5, "crosshair_hittest", "0", ZCTX(_("HTST^None")))); + me.TD(me, 1, 2/3, e = makeXonoticRadioButton(5, "crosshair_hittest", "1", _("TrueAim"))); + me.TD(me, 1, 2/3, e = makeXonoticRadioButton(5, "crosshair_hittest", "1.25", _("Enemies"))); me.TR(me); me.TDempty(me, 0.4); - me.TD(me, 1, 2.2, e = makeXonoticButton("Waypoints setup...", '0 0 0')); + me.TD(me, 1, 2.2, e = makeXonoticButton(_("Waypoints setup..."), '0 0 0')); e.onClick = DialogOpenButton_Click; e.onClickEntity = main.waypointDialog; - me.TDempty(me, 0.5); me.TR(me); me.TDempty(me, 0.4); - me.TD(me, 1, 2.2, e = makeXonoticButton("Enter HUD editor", '0 0 0')); + me.TD(me, 1, 2.2, e = makeXonoticButton(_("Enter HUD editor"), '0 0 0')); e.onClick = HUDSetup_Join_Click; e.onClickEntity = me; - me.TDempty(me, 0.5); - me.TR(me); - me.TR(me); #ifdef ALLOW_FORCEMODELS - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Force models:")); - me.TD(me, 1, 2/3, e = makeXonoticRadioButton(6, string_null, string_null, "None")); - me.TD(me, 1, 2/3, e = makeXonoticRadioButton(6, "cl_forceplayermodelsfromxonotic", string_null, "Custom")); - me.TD(me, 1, 2/3, e = makeXonoticRadioButton(6, "cl_forceplayermodels", string_null, "All")); + me.TR(me); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Force models:"))); + me.TD(me, 1, 2/3, e = makeXonoticRadioButton(6, string_null, string_null, ZCTX(_("MDL^None")))); + me.TD(me, 1, 2/3, e = makeXonoticRadioButton(6, "cl_forceplayermodelsfromxonotic", string_null, ZCTX(_("MDL^Custom")))); + me.TD(me, 1, 2/3, e = makeXonoticRadioButton(6, "cl_forceplayermodels", string_null, ZCTX(_("MDL^All")))); #endif - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_gentle", "Disable gore effects")); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Gibs:")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_gentle", _("Disable gore effects"))); + me.TR(me); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Gibs:"))); me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_nogibs")); - e.addValue(e, "None", "1"); - e.addValue(e, "Few", "0.75"); - e.addValue(e, "Many", "0.5"); - e.addValue(e, "Lots", "0"); + e.addValue(e, ZCTX(_("GIBS^None")), "1"); + e.addValue(e, ZCTX(_("GIBS^Few")), "0.75"); + e.addValue(e, ZCTX(_("GIBS^Many")), "0.5"); + e.addValue(e, ZCTX(_("GIBS^Lots")), "0"); e.configureXonoticTextSliderValues(e); setDependent(e, "cl_gentle", 0, 0); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Damage splash:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Damage splash:"))); me.TD(me, 1, 2, e = makeXonoticSlider(0, 1, 0.05, "hud_damage")); me.gotoRC(me, me.rows - 1, 0); - me.TD(me, 1, me.columns, makeXonoticCommandButton("Apply immediately", '0 0 0', "color -1 -1;name \"$_cl_name\";cl_cmd sendcvar cl_weaponpriority;sendcvar cl_zoomfactor;sendcvar cl_zoomspeed;sendcvar cl_autoswitch;sendcvar cl_shownames;sendcvar cl_forceplayermodelsfromxonotic;sendcvar cl_forceplayermodels;playermodel $_cl_playermodel;playerskin $_cl_playerskin", COMMANDBUTTON_APPLY)); + me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "color -1 -1;name \"$_cl_name\";cl_cmd sendcvar cl_weaponpriority;sendcvar cl_zoomfactor;sendcvar cl_zoomspeed;sendcvar cl_autoswitch;sendcvar cl_forceplayermodelsfromxonotic;sendcvar cl_forceplayermodels;playermodel $_cl_playermodel;playerskin $_cl_playerskin", COMMANDBUTTON_APPLY)); } void HUDSetup_Join_Click(entity me, entity btn) { diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c b/qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c index dcc6a64f36..7ded2c5054 100644 --- a/qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c +++ b/qcsrc/menu/xonotic/dialog_multiplayer_playersetup_waypoint.c @@ -1,56 +1,39 @@ #ifdef INTERFACE CLASS(XonoticWaypointDialog) EXTENDS(XonoticDialog) - METHOD(XonoticWaypointDialog, toString, string(entity)) METHOD(XonoticWaypointDialog, fill, void(entity)) METHOD(XonoticWaypointDialog, showNotify, void(entity)) - ATTRIB(XonoticWaypointDialog, title, string, "Waypoints") - ATTRIB(XonoticWaypointDialog, color, vector, SKINCOLOR_DIALOG_RADAR) - ATTRIB(XonoticWaypointDialog, intendedWidth, float, 0.7) - ATTRIB(XonoticWaypointDialog, rows, float, 6) - ATTRIB(XonoticWaypointDialog, columns, float, 4) + ATTRIB(XonoticWaypointDialog, title, string, _("Waypoints")) + ATTRIB(XonoticWaypointDialog, color, vector, SKINCOLOR_DIALOG_WAYPOINTS) + ATTRIB(XonoticWaypointDialog, intendedWidth, float, 0.5) + ATTRIB(XonoticWaypointDialog, rows, float, 5) + ATTRIB(XonoticWaypointDialog, columns, float, 3) ENDCLASS(XonoticWaypointDialog) #endif #ifdef IMPLEMENTATION void XonoticWaypointDialog_showNotify(entity me) { - loadAllCvars(me); -} -string XonoticWaypointDialog_toString(entity me) -{ - return "XXX"; + loadAllCvars(me); } void XonoticWaypointDialog_fill(entity me) { entity e; - - me.TR(me); - me.TD(me, 1, 4, makeXonoticTextLabel(0, "Waypoint settings:")); + me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 3.8, e = makeXonoticCheckBox(1, "cl_hidewaypoints", "Show base waypoints")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(1, "cl_hidewaypoints", _("Show base waypoints"))); me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, "Waypoint scale:")); - me.TD(me, 1, 3, e = makeXonoticSlider(0.5, 1.5, 0.01, "g_waypointsprite_scale")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Waypoint scale:"))); + me.TD(me, 1, 2, e = makeXonoticSlider(0.5, 1.5, 0.05, "g_waypointsprite_scale")); setDependent(e, "cl_hidewaypoints", 0, 0); me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, "Waypoint alpha:")); - me.TD(me, 1, 3, e = makeXonoticSlider(0.1, 1, 0.01, "g_waypointsprite_alpha")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Waypoint alpha:"))); + me.TD(me, 1, 2, e = makeXonoticSlider(0.1, 1, 0.05, "g_waypointsprite_alpha")); setDependent(e, "cl_hidewaypoints", 0, 0); me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, "Show names:")); - me.TD(me, 1, 3, e = makeXonoticTextSlider("cl_shownames")); - e.addValue(e, "Never", "0"); - e.addValue(e, "Teammates", "1"); - e.addValue(e, "All players", "2"); - e.configureXonoticTextSliderValues(e); + me.TD(me, 1, 3, e = makeXonoticCheckBox(1, "hud_shownames", _("Show names above players"))); me.gotoRC(me, me.rows - 1, 0); - me.TD(me, 1, me.columns, e = makeXonoticButton("OK", '0 0 0')); + me.TD(me, 1, me.columns, e = makeXonoticButton(_("OK"), '0 0 0')); e.onClick = Dialog_Close; e.onClickEntity = me; } - #endif diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c b/qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c index ca6d705c6f..2c960d3688 100644 --- a/qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c +++ b/qcsrc/menu/xonotic/dialog_multiplayer_playersetup_weapons.c @@ -3,11 +3,11 @@ CLASS(XonoticWeaponsDialog) EXTENDS(XonoticDialog) METHOD(XonoticWeaponsDialog, toString, string(entity)) METHOD(XonoticWeaponsDialog, fill, void(entity)) METHOD(XonoticWeaponsDialog, showNotify, void(entity)) - ATTRIB(XonoticWeaponsDialog, title, string, "Weapon settings") + ATTRIB(XonoticWeaponsDialog, title, string, _("Weapon settings")) ATTRIB(XonoticWeaponsDialog, color, vector, SKINCOLOR_DIALOG_WEAPONS) - ATTRIB(XonoticWeaponsDialog, intendedWidth, float, 0.5) - ATTRIB(XonoticWeaponsDialog, rows, float, 17) - ATTRIB(XonoticWeaponsDialog, columns, float, 4) + ATTRIB(XonoticWeaponsDialog, intendedWidth, float, 0.4) + ATTRIB(XonoticWeaponsDialog, rows, float, 18) + ATTRIB(XonoticWeaponsDialog, columns, float, 3) ATTRIB(XonoticWeaponsDialog, weaponsList, entity, NULL) ENDCLASS(XonoticWeaponsDialog) #endif @@ -26,33 +26,35 @@ void XonoticWeaponsDialog_fill(entity me) entity e; me.TR(me); - me.TD(me, 1, 4, makeXonoticTextLabel(0, "Weapon priority list:")); + me.TD(me, 1, 3, makeXonoticTextLabel(0, _("Weapon priority list:"))); me.TR(me); - me.TD(me, 9, 4, e = me.weaponsList = makeXonoticWeaponsList()); - me.gotoRC(me, 10, 0); - me.TDempty(me, 1); - me.TD(me, 1, 1, e = makeXonoticButton("Up", '0 0 0')); + me.TD(me, 10, 3, e = me.weaponsList = makeXonoticWeaponsList()); + me.gotoRC(me, 11, 0); + me.TDempty(me, 0.5); + me.TD(me, 1, 1, e = makeXonoticButton(_("Up"), '0 0 0')); e.onClick = WeaponsList_MoveUp_Click; e.onClickEntity = me.weaponsList; - me.TD(me, 1, 1, e = makeXonoticButton("Down", '0 0 0')); + me.TD(me, 1, 1, e = makeXonoticButton(_("Down"), '0 0 0')); e.onClick = WeaponsList_MoveDown_Click; e.onClickEntity = me.weaponsList; - me.gotoRC(me, 11, 0); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_weaponpriority_useforcycling", "Use priority list for weapon cycling")); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_autoswitch", "Auto switch weapons on pickup")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_weaponpriority_useforcycling", _("Use priority list for weapon cycling"))); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "r_drawviewmodel", "Draw 1st person weapon model")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_autoswitch", _("Auto switch weapons on pickup"))); + me.TR(me); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "r_drawviewmodel", _("Draw 1st person weapon model"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1, e = makeXonoticRadioButton(1, "cl_gunalign", "4", "Left align")); + me.TD(me, 1, 0.9, e = makeXonoticRadioButton(1, "cl_gunalign", "4", _("Left align"))); + setDependent(e, "r_drawviewmodel", 1, 1); + me.TD(me, 1, 0.9, e = makeXonoticRadioButton(1, "cl_gunalign", "1", _("Center"))); setDependent(e, "r_drawviewmodel", 1, 1); - me.TD(me, 1, 1, e = makeXonoticRadioButton(1, "cl_gunalign", "3", "Right align")); + me.TD(me, 1, 1.0, e = makeXonoticRadioButton(1, "cl_gunalign", "3", _("Right align"))); setDependent(e, "r_drawviewmodel", 1, 1); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "v_flipped", "Flip view horizontally")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "v_flipped", _("Flip view horizontally"))); me.TR(me); - me.TD(me, 1, me.columns, e = makeXonoticButton("OK", '0 0 0')); + me.TD(me, 1, me.columns, e = makeXonoticButton(_("OK"), '0 0 0')); e.onClick = Dialog_Close; e.onClickEntity = me; } diff --git a/qcsrc/menu/xonotic/dialog_news.c b/qcsrc/menu/xonotic/dialog_news.c index cfe91afcee..f638c770d1 100644 --- a/qcsrc/menu/xonotic/dialog_news.c +++ b/qcsrc/menu/xonotic/dialog_news.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticNewsDialog) EXTENDS(XonoticDialog) METHOD(XonoticNewsDialog, fill, void(entity)) - ATTRIB(XonoticNewsDialog, title, string, "News") + ATTRIB(XonoticNewsDialog, title, string, _("News")) ATTRIB(XonoticNewsDialog, color, vector, SKINCOLOR_DIALOG_SETTINGS) ATTRIB(XonoticNewsDialog, intendedWidth, float, 0.96) ATTRIB(XonoticNewsDialog, rows, float, 24) @@ -15,6 +15,6 @@ void XonoticNewsDialog_fill(entity me) entity e; me.TR(me); me.TD(me, 24, 1, e = spawnGecko()); - e.configureBrowser( e, "http://alientrap.org/xonotic/index.php?module=news" ); + e.configureBrowser( e, _("http://www.xonotic.org/team/blog/") ); } #endif diff --git a/qcsrc/menu/xonotic/dialog_quit.c b/qcsrc/menu/xonotic/dialog_quit.c index 0229e02676..fd84711861 100644 --- a/qcsrc/menu/xonotic/dialog_quit.c +++ b/qcsrc/menu/xonotic/dialog_quit.c @@ -1,11 +1,12 @@ #ifdef INTERFACE CLASS(XonoticQuitDialog) EXTENDS(XonoticDialog) METHOD(XonoticQuitDialog, fill, void(entity)) - ATTRIB(XonoticQuitDialog, title, string, "Quit") + ATTRIB(XonoticQuitDialog, title, string, _("Quit")) ATTRIB(XonoticQuitDialog, color, vector, SKINCOLOR_DIALOG_QUIT) ATTRIB(XonoticQuitDialog, intendedWidth, float, 0.5) ATTRIB(XonoticQuitDialog, rows, float, 3) ATTRIB(XonoticQuitDialog, columns, float, 2) + ATTRIB(XonoticQuitDialog, name, string, "Quit") ENDCLASS(XonoticQuitDialog) #endif @@ -14,11 +15,11 @@ void XonoticQuitDialog_fill(entity me) { entity e; me.TR(me); - me.TD(me, 1, 2, makeXonoticTextLabel(0.5, "Are you sure you want to quit?")); + me.TD(me, 1, 2, makeXonoticTextLabel(0.5, _("Are you sure you want to quit?"))); me.TR(me); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticCommandButton("Yes", '1 0 0', "quit", 0)); - me.TD(me, 1, 1, e = makeXonoticButton("No", '0 1 0')); + me.TD(me, 1, 1, e = makeXonoticCommandButton(_("Yes"), '1 0 0', "quit", 0)); + me.TD(me, 1, 1, e = makeXonoticButton(_("No"), '0 1 0')); e.onClick = Dialog_Close; e.onClickEntity = me; } diff --git a/qcsrc/menu/xonotic/dialog_sandboxtools.c b/qcsrc/menu/xonotic/dialog_sandboxtools.c new file mode 100644 index 0000000000..9e8cb5fae6 --- /dev/null +++ b/qcsrc/menu/xonotic/dialog_sandboxtools.c @@ -0,0 +1,95 @@ +#ifdef INTERFACE +CLASS(XonoticSandboxToolsDialog) EXTENDS(XonoticRootDialog) + METHOD(XonoticSandboxToolsDialog, fill, void(entity)) // to be overridden by user to fill the dialog with controls + ATTRIB(XonoticSandboxToolsDialog, title, string, _("Sandbox Tools")) // ;) + ATTRIB(XonoticSandboxToolsDialog, color, vector, SKINCOLOR_DIALOG_SANDBOXTOOLS) + ATTRIB(XonoticSandboxToolsDialog, intendedWidth, float, 0.8) + ATTRIB(XonoticSandboxToolsDialog, rows, float, 16) + ATTRIB(XonoticSandboxToolsDialog, columns, float, 4) + ATTRIB(XonoticSandboxToolsDialog, name, string, "SandboxTools") +ENDCLASS(XonoticSandboxToolsDialog) +#endif + +#ifdef IMPLEMENTATION +void XonoticSandboxToolsDialog_fill(entity me) +{ + entity e, box; + + me.TR(me); + me.TD(me, 1, 0.25, e = makeXonoticTextLabel(0, _("Model:"))); + me.TD(me, 1, 1.5, box = makeXonoticInputBox(1, "menu_sandbox_spawn_model")); + box.forbiddenCharacters = "\r\n\\\"$"; // don't care, isn't getting saved + box.maxLength = -127; // negative means encoded length in bytes + box.saveImmediately = 1; + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Spawn"), '0 0 0', "sandbox object_spawn \"$menu_sandbox_spawn_model\"", 0)); + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Remove *"), '0 0 0', "sandbox object_remove", 0)); + me.TDempty(me, 0.1); + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Copy *"), '0 0 0', "sandbox object_duplicate copy cl_sandbox_clipboard", 0)); + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Paste"), '0 0 0', "sandbox object_duplicate paste \"$cl_sandbox_clipboard\"", 0)); + me.TR(me); + me.TD(me, 1, 0.25, e = makeXonoticTextLabel(0, _("Bone:"))); + me.TD(me, 1, 1.5, box = makeXonoticInputBox(1, "menu_sandbox_attach_bone")); + box.forbiddenCharacters = "\r\n\\\"$"; // don't care, isn't getting saved + box.maxLength = -127; // negative means encoded length in bytes + box.saveImmediately = 1; + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Set * as child"), '0 0 0', "sandbox object_attach get", 0)); + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Attach to *"), '0 0 0', "sandbox object_attach set \"$menu_sandbox_attach_bone\"", 0)); + me.TDempty(me, 0.1); + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Detach from *"), '0 0 0', "sandbox object_attach remove", 0)); + me.TR(me); + me.TR(me); + me.TD(me, 1, 1.5, e = makeXonoticTextLabel(0, _("Visual object properties for *:"))); + me.TR(me); + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Set skin:"), '0 0 0', "sandbox object_edit skin $menu_sandbox_edit_skin", 0)); + me.TD(me, 1, 1.5, e = makeXonoticSlider(0, 99, 1, "menu_sandbox_edit_skin")); + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Set alpha:"), '0 0 0', "sandbox object_edit alpha $menu_sandbox_edit_alpha", 0)); + me.TD(me, 1, 1.5, e = makeXonoticSlider(0.1, 1, 0.05, "menu_sandbox_edit_alpha")); + me.TR(me); + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Set color main:"), '0 0 0', "sandbox object_edit color_main \"$menu_sandbox_edit_color_main\"", 0)); + me.TD(me, 2, 1.5, e = makeXonoticColorpickerString("menu_sandbox_edit_color_main", "menu_sandbox_edit_color_main")); + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Set color glow:"), '0 0 0', "sandbox object_edit color_glow \"$menu_sandbox_edit_color_glow\"", 0)); + me.TD(me, 2, 1.5, e = makeXonoticColorpickerString("menu_sandbox_edit_color_glow", "menu_sandbox_edit_color_glow")); + me.TR(me); + me.TR(me); + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Set frame:"), '0 0 0', "sandbox object_edit frame $menu_sandbox_edit_frame", 0)); + me.TD(me, 1, 1.5, e = makeXonoticSlider(0, 99, 1, "menu_sandbox_edit_frame")); + me.TR(me); + me.TR(me); + me.TD(me, 1, 1.5, e = makeXonoticTextLabel(0, _("Physical object properties for *:"))); + me.TR(me); + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Set material:"), '0 0 0', "sandbox object_edit material \"$menu_sandbox_edit_material\"", 0)); + me.TD(me, 1, 1.5, box = makeXonoticInputBox(1, "menu_sandbox_edit_material")); + box.forbiddenCharacters = "\r\n\\\"$"; // don't care, isn't getting saved + box.maxLength = -127; // negative means encoded length in bytes + box.saveImmediately = 1; + me.TR(me); + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Set solidity:"), '0 0 0', "sandbox object_edit solidity $menu_sandbox_edit_solidity", 0)); + me.TD(me, 1, 0.75, e = makeXonoticRadioButton(1, "menu_sandbox_edit_solidity", "0", _("Non-solid"))); + me.TD(me, 1, 0.75, e = makeXonoticRadioButton(1, "menu_sandbox_edit_solidity", "1", _("Solid"))); + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Set physics:"), '0 0 0', "sandbox object_edit physics $menu_sandbox_edit_physics", 0)); + me.TD(me, 1, 0.5, e = makeXonoticRadioButton(2, "menu_sandbox_edit_physics", "0", _("Static"))); + me.TD(me, 1, 0.5, e = makeXonoticRadioButton(2, "menu_sandbox_edit_physics", "1", _("Movable"))); + me.TD(me, 1, 0.5, e = makeXonoticRadioButton(2, "menu_sandbox_edit_physics", "2", _("Physical"))); + me.TR(me); + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Set scale:"), '0 0 0', "sandbox object_edit scale $menu_sandbox_edit_scale", 0)); + me.TD(me, 1, 1.5, e = makeXonoticSlider(0.25, 2, 0.05, "menu_sandbox_edit_scale")); + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Set force:"), '0 0 0', "sandbox object_edit force $menu_sandbox_edit_force", 0)); + me.TD(me, 1, 1.5, e = makeXonoticSlider(0, 10, 0.5, "menu_sandbox_edit_force")); + me.TR(me); + me.TR(me); + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Claim *"), '0 0 0', "sandbox object_claim", 0)); + me.TDempty(me, 0.5); + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("* object info"), '1 1 0.5', "sandbox object_info object; toggleconsole", 0)); + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("* mesh info"), '1 1 0.5', "sandbox object_info mesh; toggleconsole", 0)); + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("* attachment info"), '1 1 0.5', "sandbox object_info attachments; toggleconsole", 0)); + me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Show help"), '1 0.5 0.5', "sandbox help; toggleconsole", 0)); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("* is the object you are facing"))); + + me.gotoRC(me, me.rows - 1, 0); + me.TD(me, 1, me.columns, e = makeXonoticButton(_("OK"), '0 0 0')); + e.onClick = Dialog_Close; + e.onClickEntity = me; +} +#endif + +/* Click. The c-word is here so you can grep for it :-) */ diff --git a/qcsrc/menu/xonotic/dialog_settings.c b/qcsrc/menu/xonotic/dialog_settings.c index 1f19bf6565..1f084a16cc 100644 --- a/qcsrc/menu/xonotic/dialog_settings.c +++ b/qcsrc/menu/xonotic/dialog_settings.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticSettingsDialog) EXTENDS(XonoticDialog) METHOD(XonoticSettingsDialog, fill, void(entity)) - ATTRIB(XonoticSettingsDialog, title, string, "Settings") + ATTRIB(XonoticSettingsDialog, title, string, _("Settings")) ATTRIB(XonoticSettingsDialog, color, vector, SKINCOLOR_DIALOG_SETTINGS) ATTRIB(XonoticSettingsDialog, intendedWidth, float, 0.96) ATTRIB(XonoticSettingsDialog, rows, float, 19) @@ -15,12 +15,12 @@ void XonoticSettingsDialog_fill(entity me) entity mc; mc = makeXonoticTabController(me.rows - 2); me.TR(me); - me.TD(me, 1, 1, mc.makeTabButton(mc, "Input", makeXonoticInputSettingsTab())); - me.TD(me, 1, 1, mc.makeTabButton(mc, "Video", makeXonoticVideoSettingsTab())); - me.TD(me, 1, 1, mc.makeTabButton(mc, "Effects", makeXonoticEffectsSettingsTab())); - me.TD(me, 1, 1, mc.makeTabButton(mc, "Audio", makeXonoticAudioSettingsTab())); - me.TD(me, 1, 1, mc.makeTabButton(mc, "Network", makeXonoticNetworkSettingsTab())); - me.TD(me, 1, 1, mc.makeTabButton(mc, "Misc", makeXonoticMiscSettingsTab())); + me.TD(me, 1, 1, mc.makeTabButton(mc, _("Input"), makeXonoticInputSettingsTab())); + me.TD(me, 1, 1, mc.makeTabButton(mc, _("Video"), makeXonoticVideoSettingsTab())); + me.TD(me, 1, 1, mc.makeTabButton(mc, _("Effects"), makeXonoticEffectsSettingsTab())); + me.TD(me, 1, 1, mc.makeTabButton(mc, _("Audio"), makeXonoticAudioSettingsTab())); + me.TD(me, 1, 1, mc.makeTabButton(mc, _("Network"), makeXonoticNetworkSettingsTab())); + me.TD(me, 1, 1, mc.makeTabButton(mc, _("Misc"), makeXonoticMiscSettingsTab())); me.TR(me); me.TR(me); me.TD(me, me.rows - 2, me.columns, mc); diff --git a/qcsrc/menu/xonotic/dialog_settings_audio.c b/qcsrc/menu/xonotic/dialog_settings_audio.c index ddde45d2b8..bf3406142c 100644 --- a/qcsrc/menu/xonotic/dialog_settings_audio.c +++ b/qcsrc/menu/xonotic/dialog_settings_audio.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticAudioSettingsTab) EXTENDS(XonoticTab) METHOD(XonoticAudioSettingsTab, fill, void(entity)) - ATTRIB(XonoticAudioSettingsTab, title, string, "Audio") + ATTRIB(XonoticAudioSettingsTab, title, string, _("Audio")) ATTRIB(XonoticAudioSettingsTab, intendedWidth, float, 0.9) ATTRIB(XonoticAudioSettingsTab, rows, float, 17) ATTRIB(XonoticAudioSettingsTab, columns, float, 6.5) @@ -24,155 +24,154 @@ void XonoticAudioSettingsTab_fill(entity me) me.TR(me); s = makeXonoticDecibelsSlider(-20, 0, 0.5, "mastervolume"); - me.TD(me, 1, 1, e = makeXonoticSliderCheckBox(-1000000, 1, s, "Master:")); + me.TD(me, 1, 1, e = makeXonoticSliderCheckBox(-1000000, 1, s, _("Master:"))); me.TD(me, 1, 2, s); me.TR(me); me.TDempty(me, 0.2); s = makeXonoticDecibelsSlider(-20, 0, 0.5, "bgmvolume"); - makeMulti(s, "snd_csqcchannel2volume"); - me.TD(me, 1, 0.8, e = makeXonoticSliderCheckBox(-1000000, 1, s, "Music:")); + makeMulti(s, "snd_channel8volume"); + me.TD(me, 1, 0.8, e = makeXonoticSliderCheckBox(-1000000, 1, s, _("Music:"))); me.TD(me, 1, 2, s); + setDependentStringNotEqual(e, "mastervolume", "0"); + setDependentStringNotEqual(s, "mastervolume", "0"); me.TR(me); me.TDempty(me, 0.2); s = makeXonoticDecibelsSlider(-20, 0, 0.5, "snd_staticvolume"); - me.TD(me, 1, 0.8, e = makeXonoticSliderCheckBox(-1000000, 1, s, "Ambient:")); - makeMulti(s, "snd_entchannel2volume"); + makeMulti(s, "snd_channel9volume"); + me.TD(me, 1, 0.8, e = makeXonoticSliderCheckBox(-1000000, 1, s, ZCTX(_("VOL^Ambient:")))); me.TD(me, 1, 2, s); - setDependentStringNotEqual(e, "volume", "0"); - setDependentStringNotEqual(s, "volume", "0"); + setDependentStringNotEqual(e, "mastervolume", "0"); + setDependentStringNotEqual(s, "mastervolume", "0"); me.TR(me); me.TDempty(me, 0.2); - s = makeXonoticDecibelsSlider(-20, 0, 0.5, "snd_worldchannel0volume"); - me.TD(me, 1, 0.8, e = makeXonoticSliderCheckBox(-1000000, 1, s, "Info:")); - makeMulti(s, "snd_csqcchannel0volume"); + s = makeXonoticDecibelsSlider(-20, 0, 0.5, "snd_channel0volume"); + me.TD(me, 1, 0.8, e = makeXonoticSliderCheckBox(-1000000, 1, s, _("Info:"))); me.TD(me, 1, 2, s); - setDependentStringNotEqual(e, "volume", "0"); - setDependentStringNotEqual(s, "volume", "0"); + setDependentStringNotEqual(e, "mastervolume", "0"); + setDependentStringNotEqual(s, "mastervolume", "0"); me.TR(me); me.TDempty(me, 0.2); - s = makeXonoticDecibelsSlider(-20, 0, 0.5, "snd_entchannel3volume"); - makeMulti(s, "snd_playerchannel0volume snd_playerchannel3volume snd_csqcchannel3volume"); - me.TD(me, 1, 0.8, e = makeXonoticSliderCheckBox(-1000000, 1, s, "Items:")); + s = makeXonoticDecibelsSlider(-20, 0, 0.5, "snd_channel3volume"); + me.TD(me, 1, 0.8, e = makeXonoticSliderCheckBox(-1000000, 1, s, _("Items:"))); me.TD(me, 1, 2, s); - setDependentStringNotEqual(e, "volume", "0"); - setDependentStringNotEqual(s, "volume", "0"); + setDependentStringNotEqual(e, "mastervolume", "0"); + setDependentStringNotEqual(s, "mastervolume", "0"); me.TR(me); me.TDempty(me, 0.2); - s = makeXonoticDecibelsSlider(-20, 0, 0.5, "snd_playerchannel6volume"); - makeMulti(s, "snd_csqcchannel6volume"); - me.TD(me, 1, 0.8, e = makeXonoticSliderCheckBox(-1000000, 1, s, "Pain:")); + s = makeXonoticDecibelsSlider(-20, 0, 0.5, "snd_channel6volume"); + me.TD(me, 1, 0.8, e = makeXonoticSliderCheckBox(-1000000, 1, s, _("Pain:"))); me.TD(me, 1, 2, s); - setDependentStringNotEqual(e, "volume", "0"); - setDependentStringNotEqual(s, "volume", "0"); + setDependentStringNotEqual(e, "mastervolume", "0"); + setDependentStringNotEqual(s, "mastervolume", "0"); me.TR(me); me.TDempty(me, 0.2); - s = makeXonoticDecibelsSlider(-20, 0, 0.5, "snd_playerchannel7volume"); - makeMulti(s, "snd_entchannel7volume"); - me.TD(me, 1, 0.8, e = makeXonoticSliderCheckBox(-1000000, 1, s, "Player:")); + s = makeXonoticDecibelsSlider(-20, 0, 0.5, "snd_channel7volume"); + me.TD(me, 1, 0.8, e = makeXonoticSliderCheckBox(-1000000, 1, s, _("Player:"))); me.TD(me, 1, 2, s); - setDependentStringNotEqual(e, "volume", "0"); - setDependentStringNotEqual(s, "volume", "0"); + setDependentStringNotEqual(e, "mastervolume", "0"); + setDependentStringNotEqual(s, "mastervolume", "0"); me.TR(me); me.TDempty(me, 0.2); - s = makeXonoticDecibelsSlider(-20, 0, 0.5, "snd_entchannel4volume"); - makeMulti(s, "snd_playerchannel4volume snd_entchannel6volume snd_csqcchannel4volume"); - me.TD(me, 1, 0.8, e = makeXonoticSliderCheckBox(-1000000, 1, s, "Shots:")); + s = makeXonoticDecibelsSlider(-20, 0, 0.5, "snd_channel4volume"); + me.TD(me, 1, 0.8, e = makeXonoticSliderCheckBox(-1000000, 1, s, _("Shots:"))); me.TD(me, 1, 2, s); - setDependentStringNotEqual(e, "volume", "0"); - setDependentStringNotEqual(s, "volume", "0"); + setDependentStringNotEqual(e, "mastervolume", "0"); + setDependentStringNotEqual(s, "mastervolume", "0"); me.TR(me); me.TDempty(me, 0.2); - s = makeXonoticDecibelsSlider(-20, 0, 0.5, "snd_playerchannel2volume"); - me.TD(me, 1, 0.8, e = makeXonoticSliderCheckBox(-1000000, 1, s, "Voice:")); + s = makeXonoticDecibelsSlider(-20, 0, 0.5, "snd_channel2volume"); + me.TD(me, 1, 0.8, e = makeXonoticSliderCheckBox(-1000000, 1, s, _("Voice:"))); me.TD(me, 1, 2, s); - setDependentStringNotEqual(e, "volume", "0"); - setDependentStringNotEqual(s, "volume", "0"); + setDependentStringNotEqual(e, "mastervolume", "0"); + setDependentStringNotEqual(s, "mastervolume", "0"); me.TR(me); me.TDempty(me, 0.2); - s = makeXonoticDecibelsSlider(-20, 0, 0.5, "snd_playerchannel1volume"); - makeMulti(s, "snd_playerchannel5volume snd_entchannel1volume snd_entchannel5volume"); - me.TD(me, 1, 0.8, e = makeXonoticSliderCheckBox(-1000000, 1, s, "Weapons:")); + s = makeXonoticDecibelsSlider(-20, 0, 0.5, "snd_channel1volume"); + makeMulti(s, "snd_channel5volume"); // @!#%'n Tuba + me.TD(me, 1, 0.8, e = makeXonoticSliderCheckBox(-1000000, 1, s, _("Weapons:"))); me.TD(me, 1, 2, s); - setDependentStringNotEqual(e, "volume", "0"); - setDependentStringNotEqual(s, "volume", "0"); + setDependentStringNotEqual(e, "mastervolume", "0"); + setDependentStringNotEqual(s, "mastervolume", "0"); me.TR(me); me.gotoRC(me, 0, 3.5); me.setFirstColumn(me, me.currentColumn); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Frequency:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Frequency:"))); me.TD(me, 1, 2, e = makeXonoticTextSlider("snd_speed")); - e.addValue(e, "8 kHz", "8000"); - e.addValue(e, "11.025 kHz", "11025"); - e.addValue(e, "16 kHz", "16000"); - e.addValue(e, "22.05 kHz", "22050"); - e.addValue(e, "24 kHz", "24000"); - e.addValue(e, "32 kHz", "32000"); - e.addValue(e, "44.1 kHz", "44100"); - e.addValue(e, "48 kHz", "48000"); + e.addValue(e, _("8 kHz"), "8000"); + e.addValue(e, _("11.025 kHz"), "11025"); + e.addValue(e, _("16 kHz"), "16000"); + e.addValue(e, _("22.05 kHz"), "22050"); + e.addValue(e, _("24 kHz"), "24000"); + e.addValue(e, _("32 kHz"), "32000"); + e.addValue(e, _("44.1 kHz"), "44100"); + e.addValue(e, _("48 kHz"), "48000"); e.configureXonoticTextSliderValues(e); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Channels:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Channels:"))); me.TD(me, 1, 2, e = makeXonoticTextSlider("snd_channels")); - e.addValue(e, "Mono", "1"); - e.addValue(e, "Stereo", "2"); - e.addValue(e, "2.1", "3"); - e.addValue(e, "3.1", "4"); - e.addValue(e, "4.1", "5"); - e.addValue(e, "5.1", "6"); - e.addValue(e, "6.1", "7"); - e.addValue(e, "7.1", "8"); + e.addValue(e, _("Mono"), "1"); + e.addValue(e, _("Stereo"), "2"); + e.addValue(e, _("2.1"), "3"); + e.addValue(e, _("4"), "4"); + e.addValue(e, _("5"), "5"); + e.addValue(e, _("5.1"), "6"); + e.addValue(e, _("6.1"), "7"); + e.addValue(e, _("7.1"), "8"); e.configureXonoticTextSliderValues(e); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "snd_swapstereo", "Swap Stereo")); + me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "snd_swapstereo", _("Swap Stereo"))); setDependent(e, "snd_channels", 1.5, 0.5); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "snd_spatialization_control", "Headphone friendly mode")); + me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "snd_spatialization_control", _("Headphone friendly mode"))); setDependent(e, "snd_channels", 1.5, 0.5); me.TR(me); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Spatial voices:")); - me.TD(me, 1, 2/3, e = makeXonoticRadioButton(1, "cl_voice_directional", "0", "None")); - me.TD(me, 1, 2/3, e = makeXonoticRadioButton(1, "cl_voice_directional", "2", "Taunts")); - me.TD(me, 1, 2/3, e = makeXonoticRadioButton(1, "cl_voice_directional", "1", "All")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "menu_snd_attenuation_method", _("New style sound attenuation"))); + me.TR(me); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Spatial voices:"))); + me.TD(me, 1, 2/3, e = makeXonoticRadioButton(1, "cl_voice_directional", "0", ZCTX(_("VOCS^None")))); + me.TD(me, 1, 2/3, e = makeXonoticRadioButton(1, "cl_voice_directional", "2", ZCTX(_("VOCS^Taunts")))); + me.TD(me, 1, 2/3, e = makeXonoticRadioButton(1, "cl_voice_directional", "1", ZCTX(_("VOCS^All")))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, "Taunt range:")); + me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Taunt range:"))); setDependent(e, "cl_voice_directional", 0.5, -0.5); me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_voice_directional_taunt_attenuation")); - e.addValue(e, "Very short", "3"); - e.addValue(e, "Short", "2"); - e.addValue(e, "Normal", "0.5"); - e.addValue(e, "Long", "0.25"); - e.addValue(e, "Full", "0.015625"); + e.addValue(e, ZCTX(_("RNG^Very short")), "3"); + e.addValue(e, ZCTX(_("RNG^Short")), "2"); + e.addValue(e, ZCTX(_("RNG^Normal")), "0.5"); + e.addValue(e, ZCTX(_("RNG^Long")), "0.25"); + e.addValue(e, ZCTX(_("RNG^Full")), "0.015625"); e.configureXonoticTextSliderValues(e); setDependent(e, "cl_voice_directional", 0.5, -0.5); me.TR(me); sl = makeXonoticSlider(0.15, 1, 0.05, "cl_autotaunt"); sl.valueDisplayMultiplier = 100; sl.valueDigits = 0; - me.TD(me, 1, 1, e = makeXonoticSliderCheckBox(0, 1, sl, "Automatic taunts")); + me.TD(me, 1, 3, e = makeXonoticSliderCheckBox(0, 1, sl, _("Automatic taunts"))); if(sl.value != e.savedValue) e.savedValue = 0.65; // default me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, "Frequency:")); + me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Frequency:"))); me.TD(me, 1, 2, sl); me.TR(me); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Time warning:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Time warning:"))); me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_sound_maptime_warning")); - e.addValue(e, "None", "0"); - e.addValue(e, "1 minute", "1"); - e.addValue(e, "5 minutes", "2"); - e.addValue(e, "Both", "3"); + e.addValue(e, ZCTX(_("WRN^None")), "0"); + e.addValue(e, _("1 minute"), "1"); + e.addValue(e, _("5 minutes"), "2"); + e.addValue(e, ZCTX(_("WRN^Both")), "3"); e.configureXonoticTextSliderValues(e); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_hitsound", "Hit indicator")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_hitsound", _("Hit indicator"))); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(2, 0, "menu_sounds", "Menu sounds")); + me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(2, 0, "menu_sounds", _("Menu sounds"))); me.gotoRC(me, me.rows - 1, 0); - me.TD(me, 1, me.columns, makeXonoticCommandButton("Apply immediately", '0 0 0', "snd_restart; sendcvar cl_hitsound; sendcvar cl_autotaunt; sendcvar cl_voice_directional; sendcvar cl_voice_directional_taunt_attenuation", COMMANDBUTTON_APPLY)); + me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "snd_restart; snd_attenuation_method_$menu_snd_attenuation_method; sendcvar cl_hitsound; sendcvar cl_autotaunt; sendcvar cl_voice_directional; sendcvar cl_voice_directional_taunt_attenuation", COMMANDBUTTON_APPLY)); } #endif diff --git a/qcsrc/menu/xonotic/dialog_settings_effects.c b/qcsrc/menu/xonotic/dialog_settings_effects.c index 19b232f8ca..385252bcb1 100644 --- a/qcsrc/menu/xonotic/dialog_settings_effects.c +++ b/qcsrc/menu/xonotic/dialog_settings_effects.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticEffectsSettingsTab) EXTENDS(XonoticTab) METHOD(XonoticEffectsSettingsTab, fill, void(entity)) - ATTRIB(XonoticEffectsSettingsTab, title, string, "Effects") + ATTRIB(XonoticEffectsSettingsTab, title, string, _("Effects")) ATTRIB(XonoticEffectsSettingsTab, intendedWidth, float, 0.9) ATTRIB(XonoticEffectsSettingsTab, rows, float, 17) ATTRIB(XonoticEffectsSettingsTab, columns, float, 6.5) @@ -30,80 +30,55 @@ float someShadowCvarIsEnabled(entity box) return FALSE; } -float updateCompression() -{ - float fh; - float have_dds, have_jpg, have_tga; - if((have_dds = ((fh = fopen("dds/particles/particlefont.dds", FILE_READ)) >= 0))) - fclose(fh); - if((have_jpg = ((fh = fopen("particles/particlefont.jpg", FILE_READ)) >= 0))) - fclose(fh); - if((have_tga = ((fh = fopen("particles/particlefont.tga", FILE_READ)) >= 0))) - fclose(fh); - if(have_dds && (have_jpg || have_tga)) - { - cvar_set("gl_texturecompression", "0"); - return 1; - } - else if(have_dds) - { - cvar_set("gl_texturecompression", "0"); - cvar_set("r_texture_dds_load", "1"); - return 0; - } - else - { - cvar_set("gl_texturecompression", cvar_string("r_texture_dds_load")); - return 2; - } -} - void XonoticEffectsSettingsTab_fill(entity me) { entity e, s; float n; me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Quality preset:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Quality preset:"))); n = 5 + 2 * !!cvar("developer"); if(cvar("developer")) - me.TD(me, 1, 5.5 / n, e = makeXonoticCommandButton("OMG!", '1 0 1', "exec effects-omg.cfg", 0)); - me.TD(me, 1, 5.5 / n, e = makeXonoticCommandButton("Low", '0 0 0', "exec effects-low.cfg", 0)); - me.TD(me, 1, 5.5 / n, e = makeXonoticCommandButton("Medium", '0 0 0', "exec effects-med.cfg", 0)); - me.TD(me, 1, 5.5 / n, e = makeXonoticCommandButton("Normal", '0 0 0', "exec effects-normal.cfg", 0)); - me.TD(me, 1, 5.5 / n, e = makeXonoticCommandButton("High", '0 0 0', "exec effects-high.cfg", 0)); - me.TD(me, 1, 5.5 / n, e = makeXonoticCommandButton("Ultra", '0 0 0', "exec effects-ultra.cfg", 0)); + me.TD(me, 1, 5.5 / n, e = makeXonoticCommandButton(ZCTX(_("PRE^OMG!")), '1 0 1', "exec effects-omg.cfg", 0)); + me.TD(me, 1, 5.5 / n, e = makeXonoticCommandButton(ZCTX(_("PRE^Low")), '0 0 0', "exec effects-low.cfg", 0)); + me.TD(me, 1, 5.5 / n, e = makeXonoticCommandButton(ZCTX(_("PRE^Medium")), '0 0 0', "exec effects-med.cfg", 0)); + me.TD(me, 1, 5.5 / n, e = makeXonoticCommandButton(ZCTX(_("PRE^Normal")), '0 0 0', "exec effects-normal.cfg", 0)); + me.TD(me, 1, 5.5 / n, e = makeXonoticCommandButton(ZCTX(_("PRE^High")), '0 0 0', "exec effects-high.cfg", 0)); + me.TD(me, 1, 5.5 / n, e = makeXonoticCommandButton(ZCTX(_("PRE^Ultra")), '0 0 0', "exec effects-ultra.cfg", 0)); if(cvar("developer")) - me.TD(me, 1, 5.5 / n, e = makeXonoticCommandButton("Ultimate", '0 0 0', "exec effects-ultimate.cfg", 0)); + me.TD(me, 1, 5.5 / n, e = makeXonoticCommandButton(ZCTX(_("PRE^Ultimate")), '0 0 0', "exec effects-ultimate.cfg", 0)); me.TR(me); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Geometry detail:")); + me.TD(me, 1, 1.1, e = makeXonoticTextLabel(0, _("Geometry detail:"))); me.TD(me, 1, 2, e = makeXonoticTextSlider("r_subdivisions_tolerance")); - e.addValue(e, "Lowest", "16"); - e.addValue(e, "Low", "8"); - e.addValue(e, "Normal", "4"); - e.addValue(e, "Good", "3"); - e.addValue(e, "Best", "2"); - e.addValue(e, "Insane", "1"); + e.addValue(e, ZCTX(_("DET^Lowest")), "16"); + e.addValue(e, ZCTX(_("DET^Low")), "8"); + e.addValue(e, ZCTX(_("DET^Normal")), "4"); + e.addValue(e, ZCTX(_("DET^Good")), "3"); + e.addValue(e, ZCTX(_("DET^Best")), "2"); + e.addValue(e, ZCTX(_("DET^Insane")), "1"); e.configureXonoticTextSliderValues(e); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Antialiasing:")); + me.TD(me, 1, 1.1, e = makeXonoticTextLabel(0, _("Antialiasing:"))); me.TD(me, 1, 2, e = makeXonoticTextSlider("vid_samples")); - e.addValue(e, "Disabled", "1"); - e.addValue(e, "2x", "2"); - e.addValue(e, "4x", "4"); + e.addValue(e, ZCTX(_("AA^Disabled")), "1"); + e.addValue(e, _("2x"), "2"); + e.addValue(e, _("4x"), "4"); e.configureXonoticTextSliderValues(e); + setDependent(e, "r_viewfbo", 0, 0); me.TR(me); + me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(2, 0, "r_viewfbo", _("High-quality frame buffer"))); + setDependent(e, "vid_samples", 1, 1); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Texture resolution:")); + me.TD(me, 1, 1.1, e = makeXonoticTextLabel(0, _("Texture resolution:"))); me.TD(me, 1, 2, e = makeXonoticPicmipSlider()); if(cvar("developer")) - e.addValue(e, "Leet", "1337"); - e.addValue(e, "Lowest", "2"); - e.addValue(e, "Low", "1"); - e.addValue(e, "Normal", "0"); - e.addValue(e, "Good", "-1"); - e.addValue(e, "Best", "-2"); + e.addValue(e, ZCTX(_("RES^Leet")), "1337"); + e.addValue(e, ZCTX(_("RES^Lowest")), "2"); + e.addValue(e, ZCTX(_("RES^Low")), "1"); + e.addValue(e, ZCTX(_("RES^Normal")), "0"); + e.addValue(e, ZCTX(_("RES^Good")), "-1"); + e.addValue(e, ZCTX(_("RES^Best")), "-2"); e.configureXonoticTextSliderValues(e); me.TR(me); me.TDempty(me, 0.2); @@ -116,108 +91,107 @@ void XonoticEffectsSettingsTab_fill(entity me) case 0: break; case 1: - me.TD(me, 1, 2.8, e = makeXonoticCheckBox(1, "r_texture_dds_load", "Avoid lossy texture compression")); + me.TD(me, 1, 2.8, e = makeXonoticCheckBox(1, "r_texture_dds_load", _("Avoid lossy texture compression"))); break; case 2: - me.TD(me, 1, 2.8, e = makeXonoticCheckBox(1, "r_texture_dds_load", "Avoid lossy texture compression")); + me.TD(me, 1, 2.8, e = makeXonoticCheckBox(1, "r_texture_dds_load", _("Avoid lossy texture compression"))); makeMulti(e, "gl_texturecompression"); break; } } me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Anisotropy:")); + me.TD(me, 1, 1.1, e = makeXonoticTextLabel(0, _("Anisotropy:"))); me.TD(me, 1, 2, e = makeXonoticTextSlider("gl_texture_anisotropy")); - e.addValue(e, "Disabled", "1"); - e.addValue(e, "2x", "2"); - e.addValue(e, "4x", "4"); - e.addValue(e, "8x", "8"); - e.addValue(e, "16x", "16"); + e.addValue(e, ZCTX(_("ANISO^Disabled")), "1"); + e.addValue(e, _("2x"), "2"); + e.addValue(e, _("4x"), "4"); + e.addValue(e, _("8x"), "8"); + e.addValue(e, _("16x"), "16"); e.configureXonoticTextSliderValues(e); me.TR(me); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Particle quality:")); - me.TD(me, 1, 2, e = makeXonoticSlider(0.2, 1.0, 0.1, "cl_particles_quality")); + me.TD(me, 1, 1.1, e = makeXonoticTextLabel(0, _("Particle quality:"))); + me.TD(me, 1, 1.9, e = makeXonoticSlider(0.2, 1.0, 0.1, "cl_particles_quality")); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Particle dist.:")); - me.TD(me, 1, 2, e = makeXonoticSlider(500, 2000, 100, "r_drawparticles_drawdistance")); + me.TD(me, 1, 1.1, e = makeXonoticTextLabel(0, _("Particle distance:"))); + me.TD(me, 1, 1.9, e = makeXonoticSlider(500, 2000, 100, "r_drawparticles_drawdistance")); me.TR(me); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_decals", "Decals")); + me.TD(me, 1, 1.5, e = makeXonoticCheckBox(0, "cl_decals", _("Decals"))); + me.TD(me, 1, 1.5, e = makeXonoticCheckBox(0, "cl_decals_models", _("Decals on models"))); + setDependent(e, "cl_decals", 1, 1); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, "Distance:")); + me.TD(me, 1, 0.9, e = makeXonoticTextLabel(0, _("Distance:"))); setDependent(e, "cl_decals", 1, 1); - me.TD(me, 1, 2, e = makeXonoticSlider(200, 500, 20, "r_drawdecals_drawdistance")); + me.TD(me, 1, 1.9, e = makeXonoticSlider(200, 500, 20, "r_drawdecals_drawdistance")); setDependent(e, "cl_decals", 1, 1); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, "Time:")); + me.TD(me, 1, 0.9, e = makeXonoticTextLabel(0, _("Time:"))); setDependent(e, "cl_decals", 1, 1); - me.TD(me, 1, 2, e = makeXonoticSlider(1, 20, 1, "cl_decals_time")); + me.TD(me, 1, 1.9, e = makeXonoticSlider(1, 20, 1, "cl_decals_time")); setDependent(e, "cl_decals", 1, 1); me.gotoRC(me, 2, 3.5); me.setFirstColumn(me, me.currentColumn); - me.TD(me, 1, 2, e = makeXonoticCheckBox(1, "mod_q3bsp_nolightmaps", "Use lightmaps")); - me.TD(me, 1, 1.9, e = makeXonoticCheckBox(0, "r_glsl_deluxemapping", "Deluxe mapping")); + me.TD(me, 1, 1.2, e = makeXonoticCheckBox(1, "mod_q3bsp_nolightmaps", _("Use lightmaps"))); + me.TD(me, 1, 1.2, e = makeXonoticCheckBox(0, "r_glsl_deluxemapping", _("Deluxe mapping"))); setDependentAND(e, "vid_gl20", 1, 1, "mod_q3bsp_nolightmaps", 0, 0); - me.TD(me, 1, 0.7, e = makeXonoticCheckBox(0, "r_shadow_gloss", "Gloss")); - setDependentAND3(e, "vid_gl20", 1, 1, "r_glsl_deluxemapping", 1, 2, "mod_q3bsp_nolightmaps", 0, 0); + me.TD(me, 1, 0.6, e = makeXonoticCheckBox(0, "r_shadow_gloss", _("Gloss"))); // FIXME move this box elsewhere, it has nothing to do with Q3BSP lightmaps + setDependent(e, "vid_gl20", 1, 1); me.TR(me); - me.TD(me, 1, 1.5, e = makeXonoticCheckBox(0, "r_glsl_offsetmapping", "Offset mapping")); + me.TD(me, 1, 1.2, e = makeXonoticCheckBox(0, "r_glsl_offsetmapping", _("Offset mapping"))); setDependent(e, "vid_gl20", 1, 1); - me.TD(me, 1, 1.9, e = makeXonoticCheckBox(0, "r_glsl_offsetmapping_reliefmapping", "Relief mapping")); + me.TD(me, 1, 1.8, e = makeXonoticCheckBox(0, "r_glsl_offsetmapping_reliefmapping", _("Relief mapping"))); setDependentAND(e, "vid_gl20", 1, 1, "r_glsl_offsetmapping", 1, 1); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "r_water", "Reflections:")); + me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "r_water", _("Reflections:"))); setDependent(e, "vid_gl20", 1, 1); me.TD(me, 1, 2, e = makeXonoticTextSlider("r_water_resolutionmultiplier")); - e.addValue(e, "Blurred", "0.25"); - e.addValue(e, "Good", "0.5"); - e.addValue(e, "Sharp", "1"); + e.addValue(e, _("Blurred"), "0.25"); + e.addValue(e, ZCTX(_("REFL^Good")), "0.5"); + e.addValue(e, _("Sharp"), "1"); e.configureXonoticTextSliderValues(e); setDependentAND(e, "vid_gl20", 1, 1, "r_water", 1, 1); me.TR(me); if(cvar("developer")) - me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(3, 0, "r_showsurfaces", "Show surfaces")); + me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(3, 0, "r_showsurfaces", _("Show surfaces"))); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticRadioButton(1, string_null, string_null, "No dynamic lighting")); + me.TD(me, 1, 3, e = makeXonoticRadioButton(1, string_null, string_null, _("No dynamic lighting"))); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticRadioButton(1, "gl_flashblend", string_null, "Flash blend approximation")); + me.TD(me, 1, 3, e = makeXonoticRadioButton(1, "gl_flashblend", string_null, _("Flash blend approximation"))); me.TR(me); - me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "r_shadow_realtime_dlight", string_null, "Realtime dynamic lighting")); - me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "r_shadow_realtime_dlight_shadows", "Shadows")); + me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "r_shadow_realtime_dlight", string_null, _("Realtime dynamic lighting"))); + me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "r_shadow_realtime_dlight_shadows", _("Shadows"))); setDependent(e, "r_shadow_realtime_dlight", 1, 1); me.TR(me); - me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "r_shadow_realtime_world", "Realtime world lighting")); - me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "r_shadow_realtime_world_shadows", "Shadows")); + me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "r_shadow_realtime_world", _("Realtime world lighting"))); + me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "r_shadow_realtime_world_shadows", _("Shadows"))); setDependent(e, "r_shadow_realtime_world", 1, 1); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.8, e = makeXonoticCheckBox(0, "r_shadow_usenormalmap", "Use normal maps")); + me.TD(me, 1, 1.8, e = makeXonoticCheckBox(0, "r_shadow_usenormalmap", _("Use normal maps"))); setDependentOR(e, "r_shadow_realtime_dlight", 1, 1, "r_shadow_realtime_world", 1, 1); - me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "r_shadow_shadowmapping", "Soft shadows")); + me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "r_shadow_shadowmapping", _("Soft shadows"))); setDependentWeird(e, someShadowCvarIsEnabled); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "r_coronas", "Coronas")); + me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "r_coronas", _("Coronas"))); + me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "r_coronas_occlusionquery", _("Use Occlusion Queries"))); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "r_bloom", "Bloom")); - setDependent(e, "r_hdr", 0, 0); - me.TD(me, 1, 2, e = makeXonoticCheckBoxEx(2, 0, "r_hdr", "High Dynamic Range (HDR)")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "r_bloom", _("High Dynamic Range (HDR)"))); me.TR(me); s = makeXonoticSlider(0.1, 1, 0.1, "r_motionblur"); - me.TD(me, 1, 1, e = makeXonoticSliderCheckBox(0, 1, s, "Motion blur:")); + me.TD(me, 1, 1, e = makeXonoticSliderCheckBox(0, 1, s, _("Motion blur:"))); if(s.value != e.savedValue) e.savedValue = 0.5; // default me.TD(me, 1, 2, s); me.TR(me); - s = makeXonoticSlider(0.1, 1, 0.1, "r_damageblur"); - me.TD(me, 1, 1, e = makeXonoticSliderCheckBox(0, 1, s, "Damage blur:")); - if(s.value != e.savedValue) - e.savedValue = 0.4; // default - me.TD(me, 1, 2, s); + e = makeXonoticCheckBoxEx(0.5, 0, "hud_postprocessing_maxbluralpha", _("Blur and sharpen postprocessing")); + makeMulti(e, "hud_powerup"); + me.TD(me, 1, 2, e); me.gotoRC(me, me.rows - 1, 0); - me.TD(me, 1, me.columns, makeXonoticCommandButton("Apply immediately", '0 0 0', "vid_restart", COMMANDBUTTON_APPLY)); + me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "vid_restart", COMMANDBUTTON_APPLY)); } #endif diff --git a/qcsrc/menu/xonotic/dialog_settings_input.c b/qcsrc/menu/xonotic/dialog_settings_input.c index df3bd084a5..440d00d8b1 100644 --- a/qcsrc/menu/xonotic/dialog_settings_input.c +++ b/qcsrc/menu/xonotic/dialog_settings_input.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticInputSettingsTab) EXTENDS(XonoticTab) METHOD(XonoticInputSettingsTab, fill, void(entity)) - ATTRIB(XonoticInputSettingsTab, title, string, "Input") + ATTRIB(XonoticInputSettingsTab, title, string, _("Input")) ATTRIB(XonoticInputSettingsTab, intendedWidth, float, 0.9) ATTRIB(XonoticInputSettingsTab, rows, float, 17) ATTRIB(XonoticInputSettingsTab, columns, float, 6.5) @@ -23,55 +23,54 @@ void XonoticInputSettingsTab_fill(entity me) entity kb; me.TR(me); - me.TD(me, 1, 3, e = makeXonoticTextLabel(0, "Key bindings:")); + me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Key bindings:"))); me.TR(me); - me.TD(me, me.rows - 2, 3.3, kb = makeXonoticKeyBinder()); - me.gotoRC(me, me.rows - 1, 0); + me.TD(me, me.rows - 4, 3.3, kb = makeXonoticKeyBinder()); + me.gotoRC(me, me.rows - 3, 0); me.TR(me); - me.TD(me, 1, 1.1, e = makeXonoticButton("Change key...", '0 0 0')); + me.TD(me, 1, 1.1, e = makeXonoticButton(_("Change key..."), '0 0 0')); e.onClick = KeyBinder_Bind_Change; e.onClickEntity = kb; kb.keyGrabButton = e; - me.TD(me, 1, 1.1, e = makeXonoticButton("Edit...", '0 0 0')); + me.TD(me, 1, 1.1, e = makeXonoticButton(_("Edit..."), '0 0 0')); e.onClick = KeyBinder_Bind_Edit; e.onClickEntity = kb; kb.userbindEditButton = e; kb.userbindEditDialog = main.userbindEditDialog; main.userbindEditDialog.keybindBox = kb; - me.TD(me, 1, 1.1, e = makeXonoticButton("Clear", '0 0 0')); + me.TD(me, 1, 1.1, e = makeXonoticButton(_("Clear"), '0 0 0')); e.onClick = KeyBinder_Bind_Clear; e.onClickEntity = kb; me.gotoRC(me, 0, 3.5); me.setFirstColumn(me, me.currentColumn); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Sensitivity:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Sensitivity:"))); me.TD(me, 1, 2, e = makeXonoticSlider(1, 32, 0.2, "sensitivity")); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "UI mouse speed:")); - me.TD(me, 1, 2, e = makeXonoticSlider(0.2, 4.0, 0.1, "menu_mouse_speed")); + if(cvar("menu_mouse_absolute") == 0) // TODO remove this entirely later + { + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("UI mouse speed:"))); + me.TD(me, 1, 2, e = makeXonoticSlider(0.2, 4.0, 0.1, "menu_mouse_speed")); + } me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "m_filter", "Mouse filter")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "m_filter", _("Mouse filter"))); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(1.022, "m_pitch", "Invert mouse")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(1.022, "m_pitch", _("Invert mouse"))); me.TR(me); if(cvar_type("joy_enable") & CVAR_TYPEFLAG_ENGINE) - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "joy_enable", "Use joystick input")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "joy_enable", _("Use joystick input"))); else if(cvar_type("joystick") & CVAR_TYPEFLAG_ENGINE) - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "joystick", "Use joystick input")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "joystick", _("Use joystick input"))); me.TR(me); if(cvar_type("vid_dgamouse") & CVAR_TYPEFLAG_ENGINE) - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "vid_dgamouse", "Turn off OS mouse acceleration")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "vid_dgamouse", _("Turn off OS mouse acceleration"))); else if(cvar_type("apple_mouse_noaccel") & CVAR_TYPEFLAG_ENGINE) - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "apple_mouse_noaccel", "Turn off OS mouse acceleration")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "apple_mouse_noaccel", _("Turn off OS mouse acceleration"))); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "con_closeontoggleconsole", "\"enter console\" also closes")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "con_closeontoggleconsole", _("\"enter console\" also closes"))); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Show binds:")); - me.TD(me, 1, 2, e = makeXonoticTextSlider("sbar_showbinds")); - e.addValue(e, "Actions", "0"); - e.addValue(e, "Bound keys", "1"); - e.addValue(e, "Both", "2"); - e.configureXonoticTextSliderValues(e); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(2, 0, "cl_showpressedkeys", "Show pressed keys")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(1, "cl_movement_track_canjump", _("Holding jump key keeps jumping"))); + me.gotoRC(me, me.rows - 1, 0); + me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "sendcvar cl_movement_track_canjump", COMMANDBUTTON_APPLY)); } #endif diff --git a/qcsrc/menu/xonotic/dialog_settings_input_userbind.c b/qcsrc/menu/xonotic/dialog_settings_input_userbind.c index 3cdfa95b73..aaf182fcd8 100644 --- a/qcsrc/menu/xonotic/dialog_settings_input_userbind.c +++ b/qcsrc/menu/xonotic/dialog_settings_input_userbind.c @@ -2,7 +2,7 @@ CLASS(XonoticUserbindEditDialog) EXTENDS(XonoticDialog) METHOD(XonoticUserbindEditDialog, loadUserBind, void(entity, string, string, string)) METHOD(XonoticUserbindEditDialog, fill, void(entity)) - ATTRIB(XonoticUserbindEditDialog, title, string, "User defined key bind") + ATTRIB(XonoticUserbindEditDialog, title, string, _("User defined key bind")) ATTRIB(XonoticUserbindEditDialog, color, vector, SKINCOLOR_DIALOG_USERBIND) ATTRIB(XonoticUserbindEditDialog, intendedWidth, float, 0.7) ATTRIB(XonoticUserbindEditDialog, rows, float, 4) @@ -36,19 +36,19 @@ void XonoticUserbindEditDialog_fill(entity me) { entity e; me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Name:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Name:"))); me.TD(me, 1, me.columns - 1, me.nameBox = makeXonoticInputBox(0, string_null)); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Command when pressed:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Command when pressed:"))); me.TD(me, 1, me.columns - 1, me.commandPressBox = makeXonoticInputBox(0, string_null)); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Command when released:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Command when released:"))); me.TD(me, 1, me.columns - 1, me.commandReleaseBox = makeXonoticInputBox(0, string_null)); me.TR(me); - me.TD(me, 1, me.columns / 2, e = makeXonoticButton("Save", '0 0 0')); + me.TD(me, 1, me.columns / 2, e = makeXonoticButton(_("Save"), '0 0 0')); e.onClick = XonoticUserbindEditDialog_Save; e.onClickEntity = me; - me.TD(me, 1, me.columns / 2, e = makeXonoticButton("Cancel", '0 0 0')); + me.TD(me, 1, me.columns / 2, e = makeXonoticButton(_("Cancel"), '0 0 0')); e.onClick = Dialog_Close; e.onClickEntity = me; } diff --git a/qcsrc/menu/xonotic/dialog_settings_misc.c b/qcsrc/menu/xonotic/dialog_settings_misc.c index 14293d7f2c..61295359aa 100644 --- a/qcsrc/menu/xonotic/dialog_settings_misc.c +++ b/qcsrc/menu/xonotic/dialog_settings_misc.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticMiscSettingsTab) EXTENDS(XonoticTab) METHOD(XonoticMiscSettingsTab, fill, void(entity)) - ATTRIB(XonoticMiscSettingsTab, title, string, "Misc") + ATTRIB(XonoticMiscSettingsTab, title, string, _("Misc")) ATTRIB(XonoticMiscSettingsTab, intendedWidth, float, 0.9) ATTRIB(XonoticMiscSettingsTab, rows, float, 17) ATTRIB(XonoticMiscSettingsTab, columns, float, 6.5) @@ -23,54 +23,49 @@ void XonoticMiscSettingsTab_fill(entity me) entity sk; me.TR(me); - me.TD(me, 1, 3, e = makeXonoticTextLabel(0, "Menu skins:")); + me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Menu skins:"))); me.TR(me); me.TD(me, me.rows - 2, 3, sk = makeXonoticSkinList()); me.gotoRC(me, me.rows - 1, 0); - me.TD(me, 1, 3, e = makeXonoticButton("Apply immediately", '0 0 0')); + me.TD(me, 1, 3, e = makeXonoticButton(_("Apply immediately"), '0 0 0')); e.onClick = SetSkin_Click; e.onClickEntity = sk; me.gotoRC(me, 0, 3.5); me.setFirstColumn(me, me.currentColumn); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "showtime", "Show current time")); + me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Text language:"))); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "showdate", "Show current date")); + me.TD(me, 3, 3, sk = makeXonoticLanguageList()); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "showfps", "Show frames per second")); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_showspeed", "Speedometer")); me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 2.8/3, e = makeXonoticRadioButton(1, "cl_showspeed_unit", "0", "qu/s (hidden)")); - setDependent(e, "cl_showspeed", 1, 1); - me.TD(me, 1, 2.8/3, e = makeXonoticRadioButton(1, "cl_showspeed_unit", "1", "qu/s")); - setDependent(e, "cl_showspeed", 1, 1); - me.TD(me, 1, 2.8/3, e = makeXonoticRadioButton(1, "cl_showspeed_unit", "2", "m/s")); - setDependent(e, "cl_showspeed", 1, 1); + me.TD(me, 1, 3, e = makeXonoticButton(_("Apply immediately"), '0 0 0')); + e.onClick = SetLanguage_Click; + e.onClickEntity = sk; + me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 2.8/3, e = makeXonoticRadioButton(1, "cl_showspeed_unit", "3", "km/h")); - setDependent(e, "cl_showspeed", 1, 1); - me.TD(me, 1, 2.8/3, e = makeXonoticRadioButton(1, "cl_showspeed_unit", "4", "mph")); - setDependent(e, "cl_showspeed", 1, 1); - me.TD(me, 1, 2.8/3, e = makeXonoticRadioButton(1, "cl_showspeed_unit", "5", "knots")); - setDependent(e, "cl_showspeed", 1, 1); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_showacceleration", "Show accelerometer")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "showtime", _("Show current time"))); me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 2.8/2, e = makeXonoticTextLabel(0, "Accelerometer scale:")); - setDependent(e, "cl_showacceleration", 1, 1); - me.TD(me, 1, 2.8/2, e = makeXonoticSlider(0.2, 2, 0.2, "cl_showacceleration_scale")); - setDependent(e, "cl_showacceleration", 1, 1); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "showdate", _("Show current date"))); me.TR(me); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "showfps", _("Show frames per second"))); me.TR(me); - me.TDempty(me, 0.2); - me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "cl_maxfps_alwayssleep", "Minimize input latency")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_maxfps_alwayssleep", _("Minimize input latency"))); + + if(cvar("developer")) + { + me.TR(me); + me.TR(me); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Menu Tooltips:"))); + me.TD(me, 1, 0.4, e = makeXonoticRadioButton(2, "menu_tooltips", "0", _("Off"))); + me.TD(me, 1, 0.8, e = makeXonoticRadioButton(2, "menu_tooltips", "1", _("Standard"))); + me.TD(me, 1, 0.8, e = makeXonoticRadioButton(2, "menu_tooltips", "2", _("Advanced"))); + } + me.TR(me); me.TR(me); me.TDempty(me, 0.5); - me.TD(me, 1, 2, e = makeXonoticButton("Advanced settings...", '0 0 0')); + me.TD(me, 1, 2, e = makeXonoticButton(_("Advanced settings..."), '0 0 0')); e.onClick = DialogOpenButton_Click; e.onClickEntity = main.cvarsDialog; } diff --git a/qcsrc/menu/xonotic/dialog_settings_misc_cvars.c b/qcsrc/menu/xonotic/dialog_settings_misc_cvars.c index 0d846caf2a..be2b64259c 100644 --- a/qcsrc/menu/xonotic/dialog_settings_misc_cvars.c +++ b/qcsrc/menu/xonotic/dialog_settings_misc_cvars.c @@ -1,9 +1,8 @@ #ifdef INTERFACE CLASS(XonoticCvarsDialog) EXTENDS(XonoticDialog) - METHOD(XonoticCvarsDialog, toString, string(entity)) METHOD(XonoticCvarsDialog, fill, void(entity)) METHOD(XonoticCvarsDialog, showNotify, void(entity)) - ATTRIB(XonoticCvarsDialog, title, string, "Advanced settings") + ATTRIB(XonoticCvarsDialog, title, string, _("Advanced settings")) ATTRIB(XonoticCvarsDialog, color, vector, SKINCOLOR_DIALOG_CVARS) ATTRIB(XonoticCvarsDialog, intendedWidth, float, 0.8) ATTRIB(XonoticCvarsDialog, rows, float, 25) @@ -16,17 +15,13 @@ void XonoticCvarsDialog_showNotify(entity me) { loadAllCvars(me); } -string XonoticCvarsDialog_toString(entity me) -{ - return "XXX"; -} void XonoticCvarsDialog_fill(entity me) { entity e, cvarlist, btn; cvarlist = makeXonoticCvarList(); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Cvar filter:")); - me.TD(me, 1, 0.5, btn = makeXonoticButton("Clear", '0 0 0')); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Cvar filter:"))); + me.TD(me, 1, 0.5, btn = makeXonoticButton(_("Clear"), '0 0 0')); me.TD(me, 1, me.columns - 1.5, e = makeXonoticInputBox(0, string_null)); e.onChange = CvarList_Filter_Change; e.onChangeEntity = cvarlist; @@ -36,19 +31,21 @@ void XonoticCvarsDialog_fill(entity me) me.TR(me); me.TD(me, me.rows - me.currentRow - 7, me.columns, cvarlist); me.gotoRC(me, me.rows - 7, 0); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Setting:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Setting:"))); me.TD(me, 1, me.columns - 1, e = makeXonoticTextLabel(0, string_null)); cvarlist.cvarNameBox = e; me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Type:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Type:"))); me.TD(me, 1, me.columns - 1, e = makeXonoticTextLabel(0, string_null)); cvarlist.cvarTypeBox = e; me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Value:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Value:"))); me.TD(me, 1, me.columns - 2, e = makeXonoticInputBox(0, string_null)); cvarlist.cvarValueBox = e; e.onChange = CvarList_Value_Change; e.onChangeEntity = cvarlist; + e.onEnter = CvarList_End_Editing; + e.onEnterEntity = cvarlist; me.TD(me, 1, 1, e = makeXonoticButton(string_null, SKINCOLOR_CVARLIST_REVERTBUTTON)); cvarlist.cvarDefaultBox = e; e.onClick = CvarList_Revert_Click; @@ -56,12 +53,12 @@ void XonoticCvarsDialog_fill(entity me) e.allowCut = 1; e.marginLeft = e.marginRight = 0.5; me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Description:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Description:"))); me.TD(me, 1, me.columns - 1, e = makeXonoticTextLabel(0, string_null)); cvarlist.cvarDescriptionBox = e; e.allowWrap = 1; me.gotoRC(me, me.rows - 1, 0); - me.TD(me, 1, me.columns, e = makeXonoticButton("OK", '0 0 0')); + me.TD(me, 1, me.columns, e = makeXonoticButton(_("OK"), '0 0 0')); e.onClick = Dialog_Close; e.onClickEntity = me; } diff --git a/qcsrc/menu/xonotic/dialog_settings_network.c b/qcsrc/menu/xonotic/dialog_settings_network.c index 6e0c472afb..9b6b7c3303 100644 --- a/qcsrc/menu/xonotic/dialog_settings_network.c +++ b/qcsrc/menu/xonotic/dialog_settings_network.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticNetworkSettingsTab) EXTENDS(XonoticTab) METHOD(XonoticNetworkSettingsTab, fill, void(entity)) - ATTRIB(XonoticNetworkSettingsTab, title, string, "Network") + ATTRIB(XonoticNetworkSettingsTab, title, string, _("Network")) ATTRIB(XonoticNetworkSettingsTab, intendedWidth, float, 0.9) ATTRIB(XonoticNetworkSettingsTab, rows, float, 17) ATTRIB(XonoticNetworkSettingsTab, columns, float, 6.5) @@ -23,38 +23,38 @@ void XonoticNetworkSettingsTab_fill(entity me) entity e; me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_movement", "Client-side movement prediction")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_movement", _("Client-side movement prediction"))); me.TR(me); - //me.TD(me, 1, 3, e = makeXonoticCheckBox(1, "cl_nolerp", "Network update smoothing")); + //me.TD(me, 1, 3, e = makeXonoticCheckBox(1, "cl_nolerp", _("Network update smoothing"))); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "shownetgraph", "Show netgraph")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "shownetgraph", _("Show netgraph"))); me.TR(me); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Network speed:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Network speed:"))); me.TD(me, 1, 2, e = makeXonoticTextSlider("_cl_rate")); - e.addValue(e, "56k", "4000"); - e.addValue(e, "ISDN", "7000"); - e.addValue(e, "Slow ADSL", "15000"); - e.addValue(e, "Fast ADSL", "20000"); - e.addValue(e, "Broadband", "66666"); + e.addValue(e, _("56k"), "4000"); + e.addValue(e, _("ISDN"), "7000"); + e.addValue(e, _("Slow ADSL"), "15000"); + e.addValue(e, _("Fast ADSL"), "20000"); + e.addValue(e, _("Broadband"), "66666"); e.configureXonoticTextSliderValues(e); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Input packets/s:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Input packets/s:"))); me.TD(me, 1, 2, e = makeXonoticSlider(20, 100, 1, "cl_netfps")); me.TR(me); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticTextLabel(0, "HTTP downloads:")); + me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("HTTP downloads:"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, "Downloads:")); + me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Downloads:"))); me.TD(me, 1, 2, e = makeXonoticSlider(1, 5, 1, "cl_curl_maxdownloads")); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, "Speed (kB/s):")); + me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Speed (kB/s):"))); me.TD(me, 1, 2, e = makeXonoticSlider(10, 1500, 10, "cl_curl_maxspeed")); me.TR(me); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Client UDP port:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Client UDP port:"))); me.TD(me, 1, 0.64, e = makeXonoticInputBox(0, "cl_port")); } #endif diff --git a/qcsrc/menu/xonotic/dialog_settings_video.c b/qcsrc/menu/xonotic/dialog_settings_video.c index 0aa5e68cc3..474798c178 100644 --- a/qcsrc/menu/xonotic/dialog_settings_video.c +++ b/qcsrc/menu/xonotic/dialog_settings_video.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticVideoSettingsTab) EXTENDS(XonoticTab) METHOD(XonoticVideoSettingsTab, fill, void(entity)) - ATTRIB(XonoticVideoSettingsTab, title, string, "Video") + ATTRIB(XonoticVideoSettingsTab, title, string, _("Video")) ATTRIB(XonoticVideoSettingsTab, intendedWidth, float, 0.9) ATTRIB(XonoticVideoSettingsTab, rows, float, 17) ATTRIB(XonoticVideoSettingsTab, columns, float, 6.5) @@ -23,86 +23,85 @@ void XonoticVideoSettingsTab_fill(entity me) entity e; me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Resolution:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Resolution:"))); me.TD(me, 1, 2, e = makeXonoticResolutionSlider()); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Font/UI size:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Font/UI size:"))); me.TD(me, 1, 2, e = makeXonoticTextSlider("menu_vid_scale")); - e.addValue(e, "Unreadable", "-1"); - e.addValue(e, "Tiny", "-0.75"); - e.addValue(e, "Little", "-0.5"); - e.addValue(e, "Small", "-0.25"); - e.addValue(e, "Medium", "0"); - e.addValue(e, "Large", "0.25"); - e.addValue(e, "Huge", "0.5"); - e.addValue(e, "Gigantic", "0.75"); - e.addValue(e, "Colossal", "1"); + e.addValue(e, ZCTX(_("SZ^Unreadable")), "-1"); + e.addValue(e, ZCTX(_("SZ^Tiny")), "-0.75"); + e.addValue(e, ZCTX(_("SZ^Little")), "-0.5"); + e.addValue(e, ZCTX(_("SZ^Small")), "-0.25"); + e.addValue(e, ZCTX(_("SZ^Medium")), "0"); + e.addValue(e, ZCTX(_("SZ^Large")), "0.25"); + e.addValue(e, ZCTX(_("SZ^Huge")), "0.5"); + e.addValue(e, ZCTX(_("SZ^Gigantic")), "0.75"); + e.addValue(e, ZCTX(_("SZ^Colossal")), "1"); e.configureXonoticTextSliderValues(e); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Color depth:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Color depth:"))); me.TD(me, 1, 2, e = makeXonoticSlider(16, 32, 16, "vid_bitsperpixel")); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "vid_fullscreen", "Full screen")); - me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "vid_vsync", "Vertical Synchronization")); + me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "vid_fullscreen", _("Full screen"))); + me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "vid_vsync", _("Vertical Synchronization"))); me.TR(me); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "vid_gl20", _("Use OpenGL 2.0 shaders (GLSL)"))); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "vid_gl20", "Use OpenGL 2.0 shaders (GLSL)")); - me.TR(me); - me.TR(me); - me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "r_coronas_occlusionquery", "Use Occlusion Queries")); + me.TDempty(me, 0.2); + me.TD(me, 1, 2.8, e = makeXonoticCheckBox(0, "v_glslgamma", _("Use GLSL to handle color control"))); + setDependent(e, "vid_gl20", 1, 1); me.TR(me); me.TR(me); - me.TD(me, 1, 3, e = makeXonoticTextLabel(0, "Vertex Buffer Objects (VBOs)")); + me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Vertex Buffer Objects (VBOs)"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 0.9, e = makeXonoticRadioButton(1, "gl_vbo", "0", "Off")); - me.TD(me, 1, 2.1, e = makeXonoticRadioButton(1, "gl_vbo", "3", "Vertices, some Tris (compatible)")); + me.TD(me, 1, 0.9, e = makeXonoticRadioButton(1, "gl_vbo", "0", ZCTX(_("VBO^Off")))); + me.TD(me, 1, 1.9, e = makeXonoticRadioButton(1, "gl_vbo", "3", _("Vertices, some Tris (compatible)"))); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 0.9, e = makeXonoticRadioButton(1, "gl_vbo", "2", "Vertices")); - me.TD(me, 1, 2.1, e = makeXonoticRadioButton(1, "gl_vbo", "1", "Vertices and Triangles")); + me.TD(me, 1, 0.9, e = makeXonoticRadioButton(1, "gl_vbo", "2", _("Vertices"))); + me.TD(me, 1, 1.9, e = makeXonoticRadioButton(1, "gl_vbo", "1", _("Vertices and Triangles"))); + me.TR(me); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Depth first:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Depth first:"))); me.TD(me, 1, 2, e = makeXonoticTextSlider("r_depthfirst")); - e.addValue(e, "Disabled", "0"); - e.addValue(e, "World", "1"); - e.addValue(e, "All", "2"); + e.addValue(e, ZCTX(_("DF^Disabled")), "0"); + e.addValue(e, ZCTX(_("DF^World")), "1"); + e.addValue(e, ZCTX(_("DF^All")), "2"); e.configureXonoticTextSliderValues(e); me.TR(me); - if(cvar_type("apple_multithreadedgl") & CVAR_TYPEFLAG_ENGINE) - me.TD(me, 1, 3, e = makeXonoticCheckBox(1, "apple_multithreadedgl", "Disable multithreaded OpenGL")); - me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "gl_finish", "Wait for GPU to finish each frame")); + me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "gl_finish", _("Wait for GPU to finish each frame"))); me.gotoRC(me, 0, 3.5); me.setFirstColumn(me, me.currentColumn); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Brightness:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Brightness:"))); me.TD(me, 1, 2, e = makeXonoticSlider(0.0, 0.5, 0.02, "v_brightness")); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Contrast:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Contrast:"))); me.TD(me, 1, 2, e = makeXonoticSlider(1.0, 3.0, 0.05, "v_contrast")); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Gamma:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Gamma:"))); + setDependentAND(e, "r_glsl", 1, 1, "v_glslgamma", 1, 1); me.TD(me, 1, 2, e = makeXonoticSlider(0.5, 2.0, 0.05, "v_gamma")); + setDependentAND(e, "r_glsl", 1, 1, "v_glslgamma", 1, 1); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Contrast boost:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Contrast boost:"))); + setDependentAND(e, "r_glsl", 1, 1, "v_glslgamma", 1, 1); me.TD(me, 1, 2, e = makeXonoticSlider(1.0, 5.0, 0.1, "v_contrastboost")); + setDependentAND(e, "r_glsl", 1, 1, "v_glslgamma", 1, 1); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Saturation:")); - setDependent(e, "vid_gl20", 1, 1); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Saturation:"))); + setDependent(e, "r_glsl", 1, 1); me.TD(me, 1, 2, e = makeXonoticSlider(0.5, 2.0, 0.05, "r_glsl_saturation")); - setDependent(e, "vid_gl20", 1, 1); - me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "v_glslgamma", "Use GLSL to handle color control")); - setDependent(e, "vid_gl20", 1, 1); + setDependent(e, "r_glsl", 1, 1); me.TR(me); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Ambient:")); - me.TD(me, 1, 2, e = makeXonoticSlider(0, 20.0, 1.0, "r_ambient")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, ZCTX(_("LIT^Ambient:")))); + me.TD(me, 1, 2, e = makeXonoticSlider(0, 20.0, 0.25, "r_ambient")); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Intensity:")); + me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Intensity:"))); me.TD(me, 1, 2, e = makeXonoticSlider(0.5, 2.0, 0.05, "r_hdr_scenebrightness")); me.gotoRC(me, me.rows - 1, 0); - me.TD(me, 1, me.columns, makeXonoticCommandButton("Apply immediately", '0 0 0', "menu_cmd setresolution; vid_restart; menu_restart; togglemenu; defer 0.1 \"menu_cmd videosettings\"", COMMANDBUTTON_APPLY)); + me.TD(me, 1, me.columns, makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "menu_cmd sync; vid_restart; menu_restart; togglemenu; defer 0.1 \"menu_cmd videosettings\"", COMMANDBUTTON_APPLY)); } #endif diff --git a/qcsrc/menu/xonotic/dialog_singleplayer.c b/qcsrc/menu/xonotic/dialog_singleplayer.c index 560192ff1d..6e1be0067a 100644 --- a/qcsrc/menu/xonotic/dialog_singleplayer.c +++ b/qcsrc/menu/xonotic/dialog_singleplayer.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticSingleplayerDialog) EXTENDS(XonoticDialog) METHOD(XonoticSingleplayerDialog, fill, void(entity)) - ATTRIB(XonoticSingleplayerDialog, title, string, "Singleplayer") + ATTRIB(XonoticSingleplayerDialog, title, string, _("Singleplayer")) ATTRIB(XonoticSingleplayerDialog, color, vector, SKINCOLOR_DIALOG_SINGLEPLAYER) ATTRIB(XonoticSingleplayerDialog, intendedWidth, float, 0.80) ATTRIB(XonoticSingleplayerDialog, rows, float, 24) @@ -14,40 +14,97 @@ ENDCLASS(XonoticSingleplayerDialog) void InstantAction_LoadMap(entity btn, entity dummy) { - float glob, i, n, fh; - string s; - glob = search_begin("maps/*.instantaction", TRUE, TRUE); - if(glob < 0) - return; - i = ceil(random() * search_getsize(glob)) - 1; - fh = fopen(search_getfilename(glob, i), FILE_READ); - search_end(glob); - if(fh < 0) - return; - while((s = fgets(fh))) + float pmin, pmax, pstep; + + cvar_set("timelimit_override", "10"); + cvar_set("g_lms_lives_override", "9"); + + if(random() < 0.4) // 40% are DM + { + MapInfo_SwitchGameType(MAPINFO_TYPE_DEATHMATCH); + pmin = 2; + pmax = 8; + pstep = 1; + } + else if(random() < 0.5) // half of the remaining 60%, i.e. 30%, are CTF + { + MapInfo_SwitchGameType(MAPINFO_TYPE_CTF); + pmin = 4; + pmax = 12; + pstep = 2; + } + else if(random() < 0.5) // half of the remaining 30%, i.e. 15%, are TDM + { + MapInfo_SwitchGameType(MAPINFO_TYPE_TEAM_DEATHMATCH); + pmin = 4; + pmax = 8; + pstep = 2; + } + else if(random() < 0.666) // 2/3 of the remaining 15%, i.e. 10%, are KH { - if(substring(s, 0, 4) == "set ") - s = substring(s, 4, strlen(s) - 4); - n = tokenize_console(s); - if(argv(0) == "bot_number") - cvar_set("bot_number", argv(1)); - else if(argv(0) == "skill") - cvar_set("skill", argv(1)); - else if(argv(0) == "timelimit") - cvar_set("timelimit_override", argv(1)); - else if(argv(0) == "fraglimit") - cvar_set("fraglimit_override", argv(1)); - else if(argv(0) == "changelevel") + MapInfo_SwitchGameType(MAPINFO_TYPE_KEYHUNT); + pmin = 6; + pmax = 6; + pstep = 6; // works both for 2 and 3 teams + // TODO find team count of map, set pstep=2 or 3, and use 2v2(v2) games at least + } + else // somehow distribute the remaining 5% + { + float r; + r = floor(random() * 4); + switch(r) { - fclose(fh); - localcmd("\nmenu_loadmap_prepare\n"); - MapInfo_SwitchGameType(MAPINFO_TYPE_DEATHMATCH); - MapInfo_LoadMap(argv(1)); - cvar_set("lastlevel", "1"); - return; + default: + case 0: + MapInfo_SwitchGameType(MAPINFO_TYPE_LMS); + pmin = 2; + pmax = 6; + pstep = 1; + cvar_set("timelimit_override", "-1"); + break; + case 1: + MapInfo_SwitchGameType(MAPINFO_TYPE_DOMINATION); + pmin = 2; + pmax = 8; + pstep = 2; + break; + case 2: + MapInfo_SwitchGameType(MAPINFO_TYPE_ONSLAUGHT); + pmin = 6; + pmax = 16; + pstep = 2; + break; + case 3: + MapInfo_SwitchGameType(MAPINFO_TYPE_ASSAULT); + pmin = 4; + pmax = 16; + pstep = 2; + break; + // CA, Freezetag: bot AI does not work, add them once it does } } - fclose(fh); + + // find random map + MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0); + string s; + do + { + float m; + m = floor(random() * MapInfo_count); + s = MapInfo_BSPName_ByID(m); + } + while(!fexists(sprintf("maps/%s.waypoints", s))); + MapInfo_LoadMap(s, 1); + + // configure bots + float p; + pmin = pstep * ceil(pmin / pstep); + pmax = pstep * floor(pmax / pstep); + p = pmin + pstep * floor(random() * ((pmax - pmin) / pstep + 1)); + cvar_set("bot_number", ftos(p - 1)); + + // make sure we go back to menu + cvar_set("lastlevel", "1"); } void XonoticSingleplayerDialog_fill(entity me) @@ -56,14 +113,14 @@ void XonoticSingleplayerDialog_fill(entity me) me.TR(me); me.TDempty(me, (me.columns - 3) / 2); - me.TD(me, 2, 3, e = makeXonoticBigButton("Instant action! (random map with bots)", '0 0 0')); + me.TD(me, 2, 3, e = makeXonoticBigButton(_("Instant action! (random map with bots)"), '0 0 0')); e.onClick = InstantAction_LoadMap; e.onClickEntity = NULL; me.TR(me); me.TR(me); me.TR(me); me.TD(me, 1, 1, btnPrev = makeXonoticButton("<<", '0 0 0')); - me.TD(me, 1, me.columns - 2, lblTitle = makeXonoticTextLabel(0.5, "???")); + me.TD(me, 1, me.columns - 2, lblTitle = makeXonoticTextLabel(0.5, _("???"))); me.TD(me, 1, 1, btnNext = makeXonoticButton(">>", '0 0 0')); me.TR(me); me.TD(me, me.rows - 5, me.columns, me.campaignBox = makeXonoticCampaignList()); @@ -77,7 +134,7 @@ void XonoticSingleplayerDialog_fill(entity me) me.campaignBox.campaignGo(me.campaignBox, 0); me.gotoRC(me, me.rows - 1, 0); - me.TD(me, 1, me.columns, e = makeXonoticButton("Start Singleplayer!", '0 0 0')); + me.TD(me, 1, me.columns, e = makeXonoticButton(_("Start Singleplayer!"), '0 0 0')); e.onClick = CampaignList_LoadMap; e.onClickEntity = me.campaignBox; } diff --git a/qcsrc/menu/xonotic/dialog_singleplayer_winner.c b/qcsrc/menu/xonotic/dialog_singleplayer_winner.c index 5d377e6d0a..8e584b8a8a 100644 --- a/qcsrc/menu/xonotic/dialog_singleplayer_winner.c +++ b/qcsrc/menu/xonotic/dialog_singleplayer_winner.c @@ -1,7 +1,7 @@ #ifdef INTERFACE CLASS(XonoticWinnerDialog) EXTENDS(XonoticDialog) METHOD(XonoticWinnerDialog, fill, void(entity)) - ATTRIB(XonoticWinnerDialog, title, string, "Winner") + ATTRIB(XonoticWinnerDialog, title, string, _("Winner")) ATTRIB(XonoticWinnerDialog, color, vector, SKINCOLOR_DIALOG_SINGLEPLAYER) ATTRIB(XonoticWinnerDialog, intendedWidth, float, 0.32) ATTRIB(XonoticWinnerDialog, rows, float, 12) @@ -18,7 +18,7 @@ void XonoticWinnerDialog_fill(entity me) me.TD(me, me.rows - 2, me.columns, e = makeXonoticImage("/gfx/winner", -1)); me.gotoRC(me, me.rows - 1, 0); - me.TD(me, 1, me.columns, e = makeXonoticButton("OK", '0 0 0')); + me.TD(me, 1, me.columns, e = makeXonoticButton(_("OK"), '0 0 0')); e.onClick = Dialog_Close; e.onClickEntity = me; } diff --git a/qcsrc/menu/xonotic/dialog_teamselect.c b/qcsrc/menu/xonotic/dialog_teamselect.c index e0908ee364..7fb154c8a2 100644 --- a/qcsrc/menu/xonotic/dialog_teamselect.c +++ b/qcsrc/menu/xonotic/dialog_teamselect.c @@ -2,7 +2,7 @@ CLASS(XonoticTeamSelectDialog) EXTENDS(XonoticRootDialog) METHOD(XonoticTeamSelectDialog, fill, void(entity)) // to be overridden by user to fill the dialog with controls METHOD(XonoticTeamSelectDialog, showNotify, void(entity)) - ATTRIB(XonoticTeamSelectDialog, title, string, "Team Selection") // ;) + ATTRIB(XonoticTeamSelectDialog, title, string, _("Team Selection")) // ;) ATTRIB(XonoticTeamSelectDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT) ATTRIB(XonoticTeamSelectDialog, intendedWidth, float, 0.4) ATTRIB(XonoticTeamSelectDialog, rows, float, 5) @@ -38,17 +38,17 @@ void XonoticTeamSelectDialog_fill(entity me) { entity e; me.TR(me); - me.TD(me, 2, 4, e = makeTeamButton("join 'best' team (auto-select)", '0 0 0', "cmd selectteam auto; cmd join")); + me.TD(me, 2, 4, e = makeTeamButton(_("join 'best' team (auto-select)"), '0 0 0', "cmd selectteam auto; cmd join")); e.preferredFocusPriority = 1; me.TR(me); me.TR(me); - me.TD(me, 2, 1, me.team1 = makeTeamButton("red", '1 0.5 0.5', "cmd selectteam red; cmd join")); - me.TD(me, 2, 1, me.team2 = makeTeamButton("blue", '0.5 0.5 1', "cmd selectteam blue; cmd join")); - me.TD(me, 2, 1, me.team3 = makeTeamButton("yellow", '1 1 0.5', "cmd selectteam yellow; cmd join")); - me.TD(me, 2, 1, me.team4 = makeTeamButton("pink", '1 0.5 1', "cmd selectteam pink; cmd join")); + me.TD(me, 2, 1, me.team1 = makeTeamButton(_("red"), '1 0.5 0.5', "cmd selectteam red; cmd join")); + me.TD(me, 2, 1, me.team2 = makeTeamButton(_("blue"), '0.5 0.5 1', "cmd selectteam blue; cmd join")); + me.TD(me, 2, 1, me.team3 = makeTeamButton(_("yellow"), '1 1 0.5', "cmd selectteam yellow; cmd join")); + me.TD(me, 2, 1, me.team4 = makeTeamButton(_("pink"), '1 0.5 1', "cmd selectteam pink; cmd join")); me.TR(me); me.TR(me); - me.TD(me, 1, 4, makeXonoticCommandButton("spectate", '0 0 0', "cmd spectate", 1)); + me.TD(me, 1, 4, makeXonoticCommandButton(_("spectate"), '0 0 0', "cmd spectate", 1)); } #endif diff --git a/qcsrc/menu/xonotic/gametypelist.c b/qcsrc/menu/xonotic/gametypelist.c new file mode 100644 index 0000000000..cbc239946a --- /dev/null +++ b/qcsrc/menu/xonotic/gametypelist.c @@ -0,0 +1,85 @@ +#ifdef INTERFACE +CLASS(XonoticGametypeList) EXTENDS(XonoticListBox) + METHOD(XonoticGametypeList, configureXonoticGametypeList, void(entity)) + ATTRIB(XonoticGametypeList, rowsPerItem, float, 1) + METHOD(XonoticGametypeList, drawListBoxItem, void(entity, float, vector, float)) + METHOD(XonoticGametypeList, resizeNotify, void(entity, vector, vector, vector, vector)) + METHOD(XonoticGametypeList, setSelected, void(entity, float)) + METHOD(XonoticGametypeList, loadCvars, void(entity)) + METHOD(XonoticGametypeList, saveCvars, void(entity)) + + ATTRIB(XonoticGametypeList, realFontSize, vector, '0 0 0') + ATTRIB(XonoticGametypeList, realUpperMargin, float, 0) + ATTRIB(XonoticGametypeList, columnNameOrigin, float, 0) + ATTRIB(XonoticGametypeList, columnNameSize, float, 0) +ENDCLASS(XonoticGametypeList) +entity makeXonoticGametypeList(); +#endif + +#ifdef IMPLEMENTATION + +entity makeXonoticGametypeList(void) +{ + entity me; + me = spawnXonoticGametypeList(); + me.configureXonoticGametypeList(me); + return me; +} +void XonoticGametypeList_configureXonoticGametypeList(entity me) +{ + me.loadCvars(me); + me.configureXonoticListBox(me); + me.nItems = GameType_GetCount(); +} +void XonoticGametypeList_setSelected(entity me, float i) +{ + SUPER(XonoticGametypeList).setSelected(me, i); + me.saveCvars(me); +} + +void XonoticGametypeList_loadCvars(entity me) +{ + float t; + t = MapInfo_CurrentGametype(); + float i; + for(i = 0; i < GameType_GetCount(); ++i) + if(t == GameType_GetID(i)) + break; + if(i >= GameType_GetCount()) + { + for(i = 0; i < GameType_GetCount(); ++i) + if(t == MAPINFO_TYPE_DEATHMATCH) + break; + if(i >= GameType_GetCount()) + i = 0; + } + me.setSelected(me, i); + // do we need this: me.parent.gameTypeChangeNotify(me.parent); // to make sure +} +void XonoticGametypeList_saveCvars(entity me) +{ + float t; + t = GameType_GetID(me.selectedItem); + if(t == MapInfo_CurrentGametype()) + return; + MapInfo_SwitchGameType(t); + me.parent.gameTypeChangeNotify(me.parent); +} +void XonoticGametypeList_drawListBoxItem(entity me, float i, vector absSize, float isSelected) +{ + string s; + if(isSelected) + draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED); + s = MapInfo_Type_ToText(GameType_GetID(i)); + draw_Text(me.realUpperMargin * eY + (me.columnNameOrigin + (me.columnNameSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, '1 1 1', SKINALPHA_TEXT, 0); +} +void XonoticGametypeList_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize) +{ + SUPER(XonoticServerList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize); + me.realFontSize_y = me.fontSize / (absSize_y * me.itemHeight); + me.realFontSize_x = me.fontSize / (absSize_x * (1 - me.controlWidth)); + me.realUpperMargin = 0.5 * (1 - me.realFontSize_y); + me.columnNameOrigin = 0; + me.columnNameSize = 1; +} +#endif diff --git a/qcsrc/menu/xonotic/inputbox.c b/qcsrc/menu/xonotic/inputbox.c index e457414b4a..2a9c094b8e 100644 --- a/qcsrc/menu/xonotic/inputbox.c +++ b/qcsrc/menu/xonotic/inputbox.c @@ -20,6 +20,8 @@ CLASS(XonoticInputBox) EXTENDS(InputBox) METHOD(XonoticInputBox, loadCvars, void(entity)) METHOD(XonoticInputBox, saveCvars, void(entity)) METHOD(XonoticInputBox, keyDown, float(entity, float, float, float)) + + ATTRIB(XonoticInputBox, saveImmediately, float, 0) ENDCLASS(XonoticInputBox) entity makeXonoticInputBox(float, string); #endif @@ -54,6 +56,8 @@ void XonoticInputBox_setText(entity me, string new) { SUPER(XonoticInputBox).setText(me, new); me.onChange(me, me.onChangeEntity); + if(me.saveImmediately) + me.saveCvars(me); } else SUPER(XonoticInputBox).setText(me, new); diff --git a/qcsrc/menu/xonotic/keybinder.c b/qcsrc/menu/xonotic/keybinder.c index 3117c65e48..1107e60abc 100644 --- a/qcsrc/menu/xonotic/keybinder.c +++ b/qcsrc/menu/xonotic/keybinder.c @@ -47,7 +47,7 @@ void Xonotic_KeyBinds_Read() string s; Xonotic_KeyBinds_Count = 0; - fh = fopen("keybinds.txt", FILE_READ); + fh = fopen(language_filename("keybinds.txt"), FILE_READ); if(fh < 0) return; while((s = fgets(fh))) @@ -70,6 +70,17 @@ entity makeXonoticKeyBinder() me.configureXonoticKeyBinder(me); return me; } +void replace_bind(string from, string to) +{ + float n, j, k; + n = tokenize(findkeysforcommand(from, 0)); // uses '...' strings + for(j = 0; j < n; ++j) + { + k = stof(argv(j)); + if(k != -1) + localcmd("\nbind \"", keynumtostring(k), "\" \"", to, "\"\n"); + } +} void XonoticKeyBinder_configureXonoticKeyBinder(entity me) { me.configureXonoticListBox(me); @@ -77,6 +88,18 @@ void XonoticKeyBinder_configureXonoticKeyBinder(entity me) Xonotic_KeyBinds_Read(); me.nItems = Xonotic_KeyBinds_Count; me.setSelected(me, 0); + + // TEMP: Xonotic 0.1 to later + replace_bind("impulse 1", "weapon_group_1"); + replace_bind("impulse 2", "weapon_group_2"); + replace_bind("impulse 3", "weapon_group_3"); + replace_bind("impulse 4", "weapon_group_4"); + replace_bind("impulse 5", "weapon_group_5"); + replace_bind("impulse 6", "weapon_group_6"); + replace_bind("impulse 7", "weapon_group_7"); + replace_bind("impulse 8", "weapon_group_8"); + replace_bind("impulse 9", "weapon_group_9"); + replace_bind("impulse 14", "weapon_group_0"); } void XonoticKeyBinder_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize) { @@ -118,7 +141,7 @@ void XonoticKeyBinder_keyGrabbed(entity me, float key, float ascii) if(func == "") return; - n = tokenize(findkeysforcommand(func)); // uses '...' strings + n = tokenize(findkeysforcommand(func, 0)); // uses '...' strings nvalid = 0; for(j = 0; j < n; ++j) { @@ -137,6 +160,7 @@ void XonoticKeyBinder_keyGrabbed(entity me, float key, float ascii) } } localcmd("\nbind \"", keynumtostring(key), "\" \"", func, "\"\n"); + localcmd("-zoom\n"); // to make sure we aren't in togglezoom'd state } void XonoticKeyBinder_editUserbind(entity me, string theName, string theCommandPress, string theCommandRelease) { @@ -189,7 +213,7 @@ void KeyBinder_Bind_Clear(entity btn, entity me) if(func == "") return; - n = tokenize(findkeysforcommand(func)); // uses '...' strings + n = tokenize(findkeysforcommand(func, 0)); // uses '...' strings for(j = 0; j < n; ++j) { k = stof(argv(j)); @@ -197,7 +221,7 @@ void KeyBinder_Bind_Clear(entity btn, entity me) //localcmd("\nunbind \"", keynumtostring(k), "\"\n"); localcmd("\nbind \"", keynumtostring(k), "\" \"", KEY_NOT_BOUND_CMD, "\"\n"); } - + localcmd("-zoom\n"); // to make sure we aren't in togglezoom'd state } void XonoticKeyBinder_clickListBoxItem(entity me, float i, vector where) { @@ -307,7 +331,7 @@ void XonoticKeyBinder_drawListBoxItem(entity me, float i, vector absSize, float draw_Text(me.realUpperMargin * eY + extraMargin * eX, s, me.realFontSize, theColor, theAlpha, 0); if(func != "") { - n = tokenize(findkeysforcommand(func)); // uses '...' strings + n = tokenize(findkeysforcommand(func, 0)); // uses '...' strings s = ""; for(j = 0; j < n; ++j) { diff --git a/qcsrc/menu/xonotic/languagelist.c b/qcsrc/menu/xonotic/languagelist.c new file mode 100644 index 0000000000..0ea54dbcaf --- /dev/null +++ b/qcsrc/menu/xonotic/languagelist.c @@ -0,0 +1,184 @@ +#ifdef INTERFACE +CLASS(XonoticLanguageList) EXTENDS(XonoticListBox) + METHOD(XonoticLanguageList, configureXonoticLanguageList, void(entity)) + ATTRIB(XonoticLanguageList, rowsPerItem, float, 1) + METHOD(XonoticLanguageList, drawListBoxItem, void(entity, float, vector, float)) + METHOD(XonoticLanguageList, resizeNotify, void(entity, vector, vector, vector, vector)) + METHOD(XonoticLanguageList, setSelected, void(entity, float)) + METHOD(XonoticLanguageList, loadCvars, void(entity)) + METHOD(XonoticLanguageList, saveCvars, void(entity)) + + ATTRIB(XonoticLanguageList, realFontSize, vector, '0 0 0') + ATTRIB(XonoticLanguageList, realUpperMargin, float, 0) + ATTRIB(XonoticLanguageList, columnNameOrigin, float, 0) + ATTRIB(XonoticLanguageList, columnNameSize, float, 0) + + METHOD(XonoticLanguageList, clickListBoxItem, void(entity, float, vector)) // double click handling + METHOD(XonoticLanguageList, keyDown, float(entity, float, float, float)) // enter handling + ATTRIB(XonoticLanguageList, lastClickedLanguage, float, -1) + ATTRIB(XonoticLanguageList, lastClickedTime, float, 0) + + METHOD(XonoticLanguageList, destroy, void(entity)) + + ATTRIB(XonoticLanguageList, languagelist, float, -1) + METHOD(XonoticLanguageList, getLanguages, void(entity)) + METHOD(XonoticLanguageList, setLanguage, void(entity)) + METHOD(XonoticLanguageList, languageParameter, string(entity, float, float)) + + ATTRIB(XonoticLanguageList, name, string, "languageselector") // change this to make it noninteractive (for first run dialog) + + ATTRIB(XonoticLanguageList, doubleClickCommand, string, "menu_restart\ntogglemenu\ndefer 0.1 \"menu_cmd languageselect\"") +ENDCLASS(XonoticLanguageList) + +entity makeXonoticLanguageList(); +void SetLanguage_Click(entity btn, entity me); +#endif + +#ifdef IMPLEMENTATION + +#define LANGPARM_ID 0 +#define LANGPARM_NAME 1 +#define LANGPARM_NAME_LOCALIZED 2 +#define LANGPARM_COUNT 3 + +entity makeXonoticLanguageList() +{ + entity me; + me = spawnXonoticLanguageList(); + me.configureXonoticLanguageList(me); + return me; +} + +void XonoticLanguageList_configureXonoticLanguageList(entity me) +{ + me.configureXonoticListBox(me); + me.getLanguages(me); + me.loadCvars(me); +} + +void XonoticLanguageList_drawListBoxItem(entity me, float i, vector absSize, float isSelected) +{ + string s; + if(isSelected) + draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED); + s = me.languageParameter(me, i, LANGPARM_NAME_LOCALIZED); + draw_Text(me.realUpperMargin * eY + (me.columnNameOrigin + (me.columnNameSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, '1 1 1', SKINALPHA_TEXT, 0); +} + +void XonoticLanguageList_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize) +{ + SUPER(XonoticLanguageList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize); + me.realFontSize_y = me.fontSize / (absSize_y * me.itemHeight); + me.realFontSize_x = me.fontSize / (absSize_x * (1 - me.controlWidth)); + me.realUpperMargin = 0.5 * (1 - me.realFontSize_y); + me.columnNameOrigin = 0; + me.columnNameSize = 1; +} + +void XonoticLanguageList_setSelected(entity me, float i) +{ + SUPER(XonoticLanguageList).setSelected(me, i); + me.saveCvars(me); +} + +void XonoticLanguageList_loadCvars(entity me) +{ + string s; + float i, n; + s = cvar_string("prvm_language"); + n = me.nItems; + + // default to English + for(i = 0; i < n; ++i) + { + if(me.languageParameter(me, i, LANGPARM_ID) == "en") + { + me.selectedItem = i; + break; + } + } + + // otherwise, find the language + for(i = 0; i < n; ++i) + { + if(me.languageParameter(me, i, LANGPARM_ID) == s) + { + me.selectedItem = i; + break; + } + } +} + +void XonoticLanguageList_saveCvars(entity me) +{ + cvar_set("prvm_language", me.languageParameter(me, me.selectedItem, LANGPARM_ID)); +} + +void XonoticLanguageList_clickListBoxItem(entity me, float i, vector where) +{ + if(i == me.lastClickedLanguage) + if(time < me.lastClickedTime + 0.3) + { + // DOUBLE CLICK! + me.setSelected(me, i); + me.setLanguage(me); + } + me.lastClickedLanguage = i; + me.lastClickedTime = time; +} + +float XonoticLanguageList_keyDown(entity me, float scan, float ascii, float shift) +{ + if(scan == K_ENTER || scan == K_KP_ENTER) { + me.setLanguage(me); + return 1; + } + else + return SUPER(XonoticLanguageList).keyDown(me, scan, ascii, shift); +} + +void XonoticLanguageList_destroy(entity me) +{ + buf_del(me.languagelist); +} + +void XonoticLanguageList_getLanguages(entity me) +{ + float buf, i, n, fh; + string s; + + buf = buf_create(); + + fh = fopen("languages.txt", FILE_READ); + while((s = fgets(fh))) + { + n = tokenize_console(s); + if(n < 3) + continue; + bufstr_set(buf, i * LANGPARM_COUNT + LANGPARM_ID, argv(0)); + bufstr_set(buf, i * LANGPARM_COUNT + LANGPARM_NAME, argv(1)); + bufstr_set(buf, i * LANGPARM_COUNT + LANGPARM_NAME_LOCALIZED, argv(2)); + ++i; + } + fclose(fh); + + me.languagelist = buf; + me.nItems = i; +} + +void XonoticLanguageList_setLanguage(entity me) +{ + localcmd(sprintf("\n%s\n", me.doubleClickCommand)); +} + +string XonoticLanguageList_languageParameter(entity me, float i, float key) +{ + return bufstr_get(me.languagelist, i * LANGPARM_COUNT + key); +} + +void SetLanguage_Click(entity btn, entity me) +{ + me.setLanguage(me); +} + +#endif diff --git a/qcsrc/menu/xonotic/mainwindow.c b/qcsrc/menu/xonotic/mainwindow.c index 72e5faac36..20627c7a57 100644 --- a/qcsrc/menu/xonotic/mainwindow.c +++ b/qcsrc/menu/xonotic/mainwindow.c @@ -1,6 +1,8 @@ #ifdef INTERFACE CLASS(MainWindow) EXTENDS(ModalController) METHOD(MainWindow, configureMainWindow, void(entity)) + METHOD(MainWindow, draw, void(entity)) + ATTRIB(MainWindow, firstRunDialog, entity, NULL) ATTRIB(MainWindow, advancedDialog, entity, NULL) ATTRIB(MainWindow, mutatorsDialog, entity, NULL) ATTRIB(MainWindow, weaponsDialog, entity, NULL) @@ -12,26 +14,45 @@ CLASS(MainWindow) EXTENDS(ModalController) ATTRIB(MainWindow, cvarsDialog, entity, NULL) ATTRIB(MainWindow, mainNexposee, entity, NULL) ATTRIB(MainWindow, fadedAlpha, float, SKINALPHA_BEHIND) + ATTRIB(MainWindow, dialogToShow, entity, NULL) ENDCLASS(MainWindow) #endif #ifdef IMPLEMENTATION +void MainWindow_draw(entity me) +{ + SUPER(MainWindow).draw(me); + + if(me.dialogToShow) + { + DialogOpenButton_Click_withCoords(world, me.dialogToShow, '0 0 0', eX * conwidth + eY * conheight); + me.dialogToShow = NULL; + } +} void DemoButton_Click(entity me, entity other) { - if(me.text == "Do not press this button again!") + if(me.text == _("Do not press this button again!")) DialogOpenButton_Click(me, other); else - me.setText(me, "Do not press this button again!"); + me.setText(me, _("Do not press this button again!")); } void MainWindow_configureMainWindow(entity me) { entity n, i; + me.firstRunDialog = i = spawnXonoticFirstRunDialog(); + i.configureDialog(i); + me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z); + i = spawnXonoticTeamSelectDialog(); i.configureDialog(i); me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z); + + i = spawnXonoticSandboxToolsDialog(); + i.configureDialog(i); + me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z); i = spawnXonoticHUDExitDialog(); i.configureDialog(i); @@ -97,6 +118,14 @@ void MainWindow_configureMainWindow(entity me) i.configureDialog(i); me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z); + i = spawnXonoticHUDPhysicsDialog(); + i.configureDialog(i); + me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z); + + i = spawnXonoticHUDCenterprintDialog(); + i.configureDialog(i); + me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z); + me.advancedDialog = i = spawnXonoticAdvancedDialog(); i.configureDialog(i); me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z); @@ -173,6 +202,9 @@ void MainWindow_configureMainWindow(entity me) me.moveItemAfter(me, n, NULL); me.initializeDialog(me, n); + + if(cvar_string("_cl_name") == "Player") + me.dialogToShow = me.firstRunDialog; } #endif diff --git a/qcsrc/menu/xonotic/maplist.c b/qcsrc/menu/xonotic/maplist.c index 8b5ce6d6a7..14bf48ec9e 100644 --- a/qcsrc/menu/xonotic/maplist.c +++ b/qcsrc/menu/xonotic/maplist.c @@ -186,10 +186,14 @@ void XonoticMapList_drawListBoxItem(entity me, float i, vector absSize, float is draw_Fill('0 0 0', '1 1 0', SKINCOLOR_MAPLIST_INCLUDEDBG, SKINALPHA_MAPLIST_INCLUDEDBG); s = ftos(p); - draw_Picture(me.columnPreviewOrigin * eX, strcat("/maps/", MapInfo_Map_bspname), me.columnPreviewSize * eX + eY, '1 1 1', theAlpha); + if(draw_PictureSize(strcat("/maps/", MapInfo_Map_bspname)) == '0 0 0') + draw_Picture(me.columnPreviewOrigin * eX, "nopreview_map", me.columnPreviewSize * eX + eY, '1 1 1', theAlpha); + else + draw_Picture(me.columnPreviewOrigin * eX, strcat("/maps/", MapInfo_Map_bspname), me.columnPreviewSize * eX + eY, '1 1 1', theAlpha); + if(included) draw_Picture(me.checkMarkOrigin, "checkmark", me.checkMarkSize, '1 1 1', 1); - s = draw_TextShortenToWidth(strcat(MapInfo_Map_bspname, ": ", MapInfo_Map_title), me.columnNameSize, 0, me.realFontSize); + s = draw_TextShortenToWidth(MapInfo_Map_titlestring, 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, SKINCOLOR_MAPLIST_TITLE, theAlpha, 0); s = draw_TextShortenToWidth(MapInfo_Map_author, me.columnNameSize, 0, me.realFontSize); draw_Text(me.realUpperMargin2 * eY + (me.columnNameOrigin + 1.00 * (me.columnNameSize - draw_TextWidth(s, 0, me.realFontSize))) * eX, s, me.realFontSize, SKINCOLOR_MAPLIST_AUTHOR, theAlpha, 0); @@ -242,7 +246,7 @@ void MapList_All(entity btn, entity me) { float i; string s; - MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, MAPINFO_FLAG_FORBIDDEN, 0); // all + MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, MAPINFO_FLAG_FORBIDDEN | MAPINFO_FLAG_HIDDEN, 0); // all s = ""; for(i = 0; i < MapInfo_count; ++i) s = strcat(s, " ", MapInfo_BSPName_ByID(i)); @@ -275,26 +279,30 @@ void MapList_LoadMap(entity btn, entity me) m = MapInfo_BSPName_ByID(i); if not(m) { - print("Huh? Can't play this (m is NULL). Refiltering so this won't happen again.\n"); + print(_("Huh? Can't play this (m is NULL). Refiltering so this won't happen again.\n")); + me.refilter(me); return; } if(MapInfo_CheckMap(m)) { localcmd("\nmenu_loadmap_prepare\n"); if(cvar("menu_use_default_hostname")) - localcmd("hostname \"", strdecolorize(cvar_string("_cl_name")), "'s Xonotic server\"\n"); - MapInfo_LoadMap(m); + localcmd("hostname \"", sprintf(_("%s's Xonotic Server"), strdecolorize(cvar_string("_cl_name"))), "\"\n"); + MapInfo_LoadMap(m, 1); } else { - print("Huh? Can't play this (invalid game type). Refiltering so this won't happen again.\n"); + print(_("Huh? Can't play this (invalid game type). Refiltering so this won't happen again.\n")); me.refilter(me); + return; } } float XonoticMapList_keyDown(entity me, float scan, float ascii, float shift) { string ch, save; + if(me.nItems <= 0) + return SUPER(XonoticMapList).keyDown(me, scan, ascii, shift); if(scan == K_ENTER || scan == K_KP_ENTER) { // pop up map info screen diff --git a/qcsrc/menu/xonotic/playermodel.c b/qcsrc/menu/xonotic/playermodel.c index bbef3a6b1c..61eb4a6816 100644 --- a/qcsrc/menu/xonotic/playermodel.c +++ b/qcsrc/menu/xonotic/playermodel.c @@ -47,7 +47,7 @@ void XonoticPlayerModelSelector_configureXonoticPlayerModelSelector(entity me) float sortbuf, glob, i; string fn; - glob = search_begin(get_model_datafilename(string_null, -1, "txt"), TRUE, TRUE); + glob = search_begin(language_filename(get_model_datafilename(string_null, -1, "txt")), TRUE, TRUE); if (glob < 0) return; @@ -77,11 +77,11 @@ void XonoticPlayerModelSelector_configureXonoticPlayerModelSelector(entity me) bufstr_set(me.bufModels, BUFMODELS_COUNT*i+BUFMODELS_SKIN, ftos(get_model_parameters_modelskin)); get_model_parameters_desc = strcat(get_model_parameters_desc, "\n"); if(get_model_parameters_sex) - get_model_parameters_desc = strcat(get_model_parameters_desc, "\nSex: ", get_model_parameters_sex); + get_model_parameters_desc = strcat(get_model_parameters_desc, sprintf("\nSex: %s", get_model_parameters_sex)); if(get_model_parameters_weight) - get_model_parameters_desc = strcat(get_model_parameters_desc, "\nWeight: ", ftos(get_model_parameters_weight), " kg"); + get_model_parameters_desc = strcat(get_model_parameters_desc, sprintf("\nWeight: %g kg", get_model_parameters_weight)); if(get_model_parameters_age) - get_model_parameters_desc = strcat(get_model_parameters_desc, "\nAge: ", ftos(get_model_parameters_age)); + get_model_parameters_desc = strcat(get_model_parameters_desc, sprintf("\nAge: %g", get_model_parameters_age)); while(substring(get_model_parameters_desc, -1, 1) == "\n") get_model_parameters_desc = substring(get_model_parameters_desc, 0, -2); bufstr_set(me.bufModels, BUFMODELS_COUNT*i+BUFMODELS_DESC, get_model_parameters_desc); @@ -137,7 +137,10 @@ void XonoticPlayerModelSelector_go(entity me, float d) me.currentModelDescription = strzone(bufstr_get(me.bufModels, BUFMODELS_COUNT*me.idxModels+BUFMODELS_DESC)); // fix the image - me.src = me.currentModelImage; + if(draw_PictureSize(me.currentModelImage) == '0 0 0') + me.src = "nopreview_player"; + else + me.src = me.currentModelImage; me.updateAspect(me); } @@ -171,7 +174,7 @@ void XonoticPlayerModelSelector_draw(entity me) if (me.numModels <= 0) { - draw_CenterText('0.5 0.5 0', "<no model found>", me.realFontSize, '1 1 1', 0.6, FALSE); + draw_CenterText('0.5 0.5 0', _("<no model found>"), me.realFontSize, '1 1 1', 0.6, FALSE); return; } diff --git a/qcsrc/menu/xonotic/rootdialog.c b/qcsrc/menu/xonotic/rootdialog.c index efc00822d8..e8c9db364e 100644 --- a/qcsrc/menu/xonotic/rootdialog.c +++ b/qcsrc/menu/xonotic/rootdialog.c @@ -3,7 +3,7 @@ CLASS(XonoticRootDialog) EXTENDS(XonoticDialog) // still to be customized by user /* ATTRIB(XonoticDialog, closable, float, 1) - ATTRIB(XonoticDialog, title, string, "Form1") // ;) + ATTRIB(XonoticDialog, title, string, _("Form1")) // ;) ATTRIB(XonoticDialog, color, vector, '1 0.5 1') ATTRIB(XonoticDialog, intendedWidth, float, 0) ATTRIB(XonoticDialog, rows, float, 3) diff --git a/qcsrc/menu/xonotic/serverlist.c b/qcsrc/menu/xonotic/serverlist.c index 3d5d3e843c..82fdbfb5eb 100644 --- a/qcsrc/menu/xonotic/serverlist.c +++ b/qcsrc/menu/xonotic/serverlist.c @@ -63,6 +63,7 @@ void ServerList_ShowFull_Click(entity box, entity me); void ServerList_Filter_Change(entity box, entity me); void ServerList_Favorite_Click(entity btn, entity me); void ServerList_Info_Click(entity btn, entity me); +void ServerList_Update_favoriteButton(entity btn, entity me); #endif #ifdef IMPLEMENTATION @@ -107,6 +108,8 @@ float IsFavorite(string srv) if(srv == "") return FALSE; srv = netaddress_resolve(srv, 26000); + if(srv == "") + return FALSE; p = crypto_getidfp(srv); n = tokenize_console(cvar_string("net_slist_favorites")); for(i = 0; i < n; ++i) @@ -176,6 +179,14 @@ void ToggleFavorite(string srv) resorthostcache(); } +void ServerList_Update_favoriteButton(entity btn, entity me) +{ + if(IsFavorite(me.ipAddressBox.text)) + me.favoriteButton.setText(me.favoriteButton, _("Remove")); + else + me.favoriteButton.setText(me.favoriteButton, _("Bookmark")); +} + entity makeXonoticServerList() { entity me; @@ -227,7 +238,7 @@ void XonoticServerList_refreshServerList(entity me, float mode) } else */ { - float m, o; + float m, o, i, n; // moin moin string s, typestr, modstr; s = me.filterString; @@ -246,12 +257,26 @@ void XonoticServerList_refreshServerList(entity me, float mode) m = SLIST_MASK_AND - 1; resethostcachemasks(); + + // ping: reject negative ping (no idea why this happens in the first place, engine bug) + sethostcachemasknumber(++m, SLIST_FIELD_PING, 0, SLIST_TEST_GREATEREQUAL); + + // show full button if(!me.filterShowFull) - sethostcachemasknumber(++m, SLIST_FIELD_FREESLOTS, 1, SLIST_TEST_GREATEREQUAL); + { + sethostcachemasknumber(++m, SLIST_FIELD_FREESLOTS, 1, SLIST_TEST_GREATEREQUAL); // legacy + sethostcachemaskstring(++m, SLIST_FIELD_QCSTATUS, ":S0:", SLIST_TEST_NOTCONTAIN); // g_maxplayers support + } + + // show empty button if(!me.filterShowEmpty) sethostcachemasknumber(++m, SLIST_FIELD_NUMHUMANS, 1, SLIST_TEST_GREATEREQUAL); + + // gametype filtering if(typestr != "") sethostcachemaskstring(++m, SLIST_FIELD_QCSTATUS, strcat(typestr, ":"), SLIST_TEST_STARTSWITH); + + // mod filtering if(modstr != "") { if(substring(modstr, 0, 1) == "!") @@ -259,6 +284,13 @@ void XonoticServerList_refreshServerList(entity me, float mode) else sethostcachemaskstring(++m, SLIST_FIELD_MOD, resolvemod(modstr), SLIST_TEST_EQUAL); } + + // server banning + n = tokenizebyseparator(_Nex_ExtResponseSystem_BannedServers, " "); + for(i = 0; i < n; ++i) + if(argv(i) != "") + sethostcachemaskstring(++m, SLIST_FIELD_CNAME, argv(i), SLIST_TEST_NOTSTARTSWITH); + m = SLIST_MASK_OR - 1; if(s != "") { @@ -290,6 +322,13 @@ void XonoticServerList_draw(entity me) { float i, found, owned; + if(_Nex_ExtResponseSystem_BannedServersNeedsRefresh) + { + if(!me.needsRefresh) + me.needsRefresh = 2; + _Nex_ExtResponseSystem_BannedServersNeedsRefresh = 0; + } + if(me.currentSortField == -1) { me.setSortOrder(me, SLIST_FIELD_PING, +1); @@ -311,6 +350,7 @@ void XonoticServerList_draw(entity me) me.connectButton.disabled = ((me.nItems == 0) && (me.ipAddressBox.text == "")); me.infoButton.disabled = ((me.nItems == 0) || !owned); + me.favoriteButton.disabled = ((me.nItems == 0) && (me.ipAddressBox.text == "")); found = 0; if(me.selectedServer) @@ -350,12 +390,7 @@ void XonoticServerList_draw(entity me) if(me.ipAddressBoxFocused != me.ipAddressBox.focused) { if(me.ipAddressBox.focused || me.ipAddressBoxFocused < 0) - { - if(IsFavorite(me.ipAddressBox.text)) - me.favoriteButton.setText(me.favoriteButton, "Remove"); - else - me.favoriteButton.setText(me.favoriteButton, "Bookmark"); - } + ServerList_Update_favoriteButton(NULL, me); me.ipAddressBoxFocused = me.ipAddressBox.focused; } @@ -392,24 +427,24 @@ void ServerList_TypeSort_Click(entity btn, entity me) else s = ""; - for(i = 1; ; ++i) // 20 modes ought to be enough for anyone + for(i = 1; ; i *= 2) // 20 modes ought to be enough for anyone { - t = GametypeNameFromType(i); + t = MapInfo_Type_ToString(i); if(i > 1) - if(t == GametypeNameFromType(0)) // it repeats (default case) + if(t == "") // it repeats (default case) { // no type was found // choose the first one - s = t; + s = MapInfo_Type_ToString(1); break; } - if(s == GametypeNameFromType(i)) + if(s == t) { // the type was found // choose the next one - s = GametypeNameFromType(i + 1); - if(s == GametypeNameFromType(0)) - s = ""; + s = MapInfo_Type_ToString(i * 2); + if(s == "") + s = MapInfo_Type_ToString(1); break; } } @@ -455,17 +490,17 @@ void ServerList_ShowFull_Click(entity box, entity me) me.ipAddressBox.cursorPos = 0; me.ipAddressBoxFocused = -1; } -void XonoticServerList_setSortOrder(entity me, float field, float direction) +void XonoticServerList_setSortOrder(entity me, float fld, float direction) { - if(me.currentSortField == field) + if(me.currentSortField == fld) direction = -me.currentSortOrder; me.currentSortOrder = direction; - me.currentSortField = field; - me.sortButton1.forcePressed = (field == SLIST_FIELD_PING); - me.sortButton2.forcePressed = (field == SLIST_FIELD_NAME); - me.sortButton3.forcePressed = (field == SLIST_FIELD_MAP); + me.currentSortField = fld; + me.sortButton1.forcePressed = (fld == SLIST_FIELD_PING); + me.sortButton2.forcePressed = (fld == SLIST_FIELD_NAME); + me.sortButton3.forcePressed = (fld == SLIST_FIELD_MAP); me.sortButton4.forcePressed = 0; - me.sortButton5.forcePressed = (field == SLIST_FIELD_NUMHUMANS); + me.sortButton5.forcePressed = (fld == SLIST_FIELD_NUMHUMANS); me.selectedItem = 0; if(me.selectedServer) strunzone(me.selectedServer); @@ -498,11 +533,11 @@ void XonoticServerList_resizeNotify(entity me, vector relOrigin, vector relSize, me.realUpperMargin = 0.5 * (1 - me.realFontSize_y); me.columnIconsOrigin = 0; - me.columnIconsSize = me.realFontSize_x * 3 * me.iconsSizeFactor; + me.columnIconsSize = me.realFontSize_x * 4 * me.iconsSizeFactor; me.columnPingSize = me.realFontSize_x * 3; me.columnMapSize = me.realFontSize_x * 10; me.columnTypeSize = me.realFontSize_x * 4; - me.columnPlayersSize = me.realFontSize_x * 4; + me.columnPlayersSize = me.realFontSize_x * 5; me.columnNameSize = 1 - me.columnPlayersSize - me.columnMapSize - me.columnPingSize - me.columnIconsSize - me.columnTypeSize - 5 * me.realFontSize_x; me.columnPingOrigin = me.columnIconsOrigin + me.columnIconsSize + me.realFontSize_x; me.columnNameOrigin = me.columnPingOrigin + me.columnPingSize + me.realFontSize_x; @@ -510,11 +545,11 @@ void XonoticServerList_resizeNotify(entity me, vector relOrigin, vector relSize, me.columnTypeOrigin = me.columnMapOrigin + me.columnMapSize + me.realFontSize_x; me.columnPlayersOrigin = me.columnTypeOrigin + me.columnTypeSize + me.realFontSize_x; - me.positionSortButton(me, me.sortButton1, me.columnPingOrigin, me.columnPingSize, "Ping", ServerList_PingSort_Click); - me.positionSortButton(me, me.sortButton2, me.columnNameOrigin, me.columnNameSize, "Host name", ServerList_NameSort_Click); - me.positionSortButton(me, me.sortButton3, me.columnMapOrigin, me.columnMapSize, "Map", ServerList_MapSort_Click); - me.positionSortButton(me, me.sortButton4, me.columnTypeOrigin, me.columnTypeSize, "Type", ServerList_TypeSort_Click); - me.positionSortButton(me, me.sortButton5, me.columnPlayersOrigin, me.columnPlayersSize, "Players", ServerList_PlayerSort_Click); + me.positionSortButton(me, me.sortButton1, me.columnPingOrigin, me.columnPingSize, _("Ping"), ServerList_PingSort_Click); + me.positionSortButton(me, me.sortButton2, me.columnNameOrigin, me.columnNameSize, _("Host name"), ServerList_NameSort_Click); + me.positionSortButton(me, me.sortButton3, me.columnMapOrigin, me.columnMapSize, _("Map"), ServerList_MapSort_Click); + me.positionSortButton(me, me.sortButton4, me.columnTypeOrigin, me.columnTypeSize, _("Type"), ServerList_TypeSort_Click); + me.positionSortButton(me, me.sortButton5, me.columnPlayersOrigin, me.columnPlayersSize, _("Players"), ServerList_PlayerSort_Click); float f; f = me.currentSortField; @@ -560,17 +595,43 @@ void XonoticServerList_clickListBoxItem(entity me, float i, vector where) void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float isSelected) { // layout: Ping, Server name, Map name, NP, TP, MP - string s; float p, q; float isv4, isv6; vector theColor; float theAlpha; + float m, pure, freeslots, j, sflags; + string s, typestr, versionstr, k, v; if(isSelected) draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED); - if(gethostcachenumber(SLIST_FIELD_NUMPLAYERS, i) >= gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i)) + s = gethostcachestring(SLIST_FIELD_QCSTATUS, i); + m = tokenizebyseparator(s, ":"); + if(m >= 2) + { + typestr = argv(0); + versionstr = argv(1); + } + freeslots = -1; + sflags = -1; + for(j = 2; j < m; ++j) + { + if(argv(j) == "") + break; + k = substring(argv(j), 0, 1); + v = substring(argv(j), 1, -1); + if(k == "P") + pure = stof(v); + else if(k == "S") + freeslots = stof(v); + else if(k == "F") + sflags = stof(v); + } + + if(gethostcachenumber(SLIST_FIELD_FREESLOTS, i) <= 0) theAlpha = SKINALPHA_SERVERLIST_FULL; + else if(freeslots == 0) + theAlpha = SKINALPHA_SERVERLIST_FULL; // g_maxplayers support else if not(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i)) theAlpha = SKINALPHA_SERVERLIST_EMPTY; else @@ -634,7 +695,7 @@ void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float } if(q == 3) q = 5; - if(q >= 3) + else if(q >= 3) q -= 2; // possible status: // 0: crypto off @@ -644,7 +705,6 @@ void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float // 4: AES recommended and will be used // 5: AES required - s = gethostcachestring(SLIST_FIELD_QCSTATUS, i); { vector iconSize; iconSize_y = me.realFontSize_y * me.iconsSizeFactor; @@ -667,10 +727,16 @@ void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float iconPos_x += iconSize_x; } - draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_aeslevel", ftos(q)), iconSize, '1 1 1', 1); + if(q > 0) + draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_aeslevel", ftos(q)), iconSize, '1 1 1', 1); iconPos_x += iconSize_x; - draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_pure", ftos(strstrofs(s, ":P0:", 0) >= 0)), iconSize, '1 1 1', 1); + if(pure == 0) + draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_pure1"), iconSize, '1 1 1', 1); + iconPos_x += iconSize_x; + + if(sflags >= 0 && (sflags & SERVERFLAG_PLAYERSTATS)) + draw_Picture(iconPos, strcat(SKINGFX_SERVERLIST_ICON, "_stats1"), iconSize, '1 1 1', 1); iconPos_x += iconSize_x; } @@ -680,13 +746,7 @@ void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float draw_Text(me.realUpperMargin * eY + me.columnNameOrigin * eX, s, me.realFontSize, theColor, theAlpha, 0); s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_MAP, i), me.columnMapSize, 0, me.realFontSize); draw_Text(me.realUpperMargin * eY + (me.columnMapOrigin + (me.columnMapSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0); - s = gethostcachestring(SLIST_FIELD_QCSTATUS, i); - p = strstrofs(s, ":", 0); - if(p >= 0) - s = substring(s, 0, p); - else - s = ""; - s = draw_TextShortenToWidth(s, me.columnMapSize, 0, me.realFontSize); + s = draw_TextShortenToWidth(typestr, me.columnTypeSize, 0, me.realFontSize); draw_Text(me.realUpperMargin * eY + (me.columnTypeOrigin + (me.columnTypeSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0); s = strcat(ftos(gethostcachenumber(SLIST_FIELD_NUMHUMANS, i)), "/", ftos(gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i))); draw_Text(me.realUpperMargin * eY + (me.columnPlayersOrigin + (me.columnPlayersSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0); @@ -707,8 +767,11 @@ float XonoticServerList_keyDown(entity me, float scan, float ascii, float shift) } else if(scan == K_MOUSE2 || scan == K_SPACE) { - main.serverInfoDialog.loadServerInfo(main.serverInfoDialog, me.selectedItem); - DialogOpenButton_Click_withCoords(me, main.serverInfoDialog, org, sz); + if(me.nItems != 0) + { + main.serverInfoDialog.loadServerInfo(main.serverInfoDialog, me.selectedItem); + DialogOpenButton_Click_withCoords(me, main.serverInfoDialog, org, sz); + } } else if(scan == K_INS || scan == K_MOUSE3 || scan == K_KP_INS) { diff --git a/qcsrc/menu/xonotic/skinlist.c b/qcsrc/menu/xonotic/skinlist.c index 864b3054a5..68314cd027 100644 --- a/qcsrc/menu/xonotic/skinlist.c +++ b/qcsrc/menu/xonotic/skinlist.c @@ -102,10 +102,13 @@ void XonoticSkinList_getSkins(entity me) { s = search_getfilename(glob, i); bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_NAME, substring(s, 9, strlen(s) - 24)); // the * part - bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_TITLE, "<TITLE>"); - bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_AUTHOR, "<AUTHOR>"); - bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_PREVIEW, strcat("/gfx/menu/", substring(s, 9, strlen(s) - 24), "/skinpreview")); - fh = fopen(s, FILE_READ); + bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_TITLE, _("<TITLE>")); + bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_AUTHOR, _("<AUTHOR>")); + if(draw_PictureSize(strcat("/gfx/menu/", substring(s, 9, strlen(s) - 24), "/skinpreview")) == '0 0 0') + bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_PREVIEW, "nopreview_menuskin"); + else + bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_PREVIEW, strcat("/gfx/menu/", substring(s, 9, strlen(s) - 24), "/skinpreview")); + fh = fopen(language_filename(s), FILE_READ); if(fh < 0) { print("Warning: can't open skinvalues.txt file\n"); @@ -160,7 +163,7 @@ void XonoticSkinList_drawListBoxItem(entity me, float i, vector absSize, float i draw_Picture(me.columnPreviewOrigin * eX, s, me.columnPreviewSize * eX + eY, '1 1 1', 1); s = me.skinParameter(me, i, SKINPARM_NAME); - s = strcat(s, ": ", me.skinParameter(me, i, SKINPARM_TITLE)); + s = sprintf(_("%s: %s"), s, me.skinParameter(me, i, SKINPARM_TITLE)); s = draw_TextShortenToWidth(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, SKINCOLOR_SKINLIST_TITLE, SKINALPHA_TEXT, 0); diff --git a/qcsrc/menu/xonotic/slider.c b/qcsrc/menu/xonotic/slider.c index 46a01bb5ac..e833bb1251 100644 --- a/qcsrc/menu/xonotic/slider.c +++ b/qcsrc/menu/xonotic/slider.c @@ -45,8 +45,7 @@ void XonoticSlider_configureXonoticSlider(entity me, float theValueMin, float th { me.cvarName = theCvar; me.loadCvars(me); - if(tooltipdb >= 0) - me.tooltip = getZonedTooltipForIdentifier(theCvar); + me.tooltip = getZonedTooltipForIdentifier(theCvar); } } void XonoticSlider_setValue(entity me, float val) diff --git a/qcsrc/menu/xonotic/slider_decibels.c b/qcsrc/menu/xonotic/slider_decibels.c index 0e4b4e3720..24edb4cb91 100644 --- a/qcsrc/menu/xonotic/slider_decibels.c +++ b/qcsrc/menu/xonotic/slider_decibels.c @@ -47,10 +47,10 @@ void XonoticDecibelsSlider_saveCvars(entity me) string XonoticDecibelsSlider_valueToText(entity me, float v) { if(v < -33) - return "OFF"; + return CTX(_("VOL^OFF")); else if(v >= -0.1) - return "MAX"; - return strcat(SUPER(XonoticDecibelsSlider).valueToText(me, v), " dB"); + return CTX(_("VOL^MAX")); + return sprintf(_("%s dB"), SUPER(XonoticDecibelsSlider).valueToText(me, v)); } #endif diff --git a/qcsrc/menu/xonotic/slider_picmip.c b/qcsrc/menu/xonotic/slider_picmip.c index e906242fe4..ddedc4bab2 100644 --- a/qcsrc/menu/xonotic/slider_picmip.c +++ b/qcsrc/menu/xonotic/slider_picmip.c @@ -3,6 +3,7 @@ CLASS(XonoticPicmipSlider) EXTENDS(XonoticTextSlider) METHOD(XonoticPicmipSlider, configureXonoticPicmipSlider, void(entity)) METHOD(XonoticPicmipSlider, draw, void(entity)) METHOD(XonoticPicmipSlider, autofix, void(entity)) + ATTRIB(XonoticPicmipSlider, have_s3tc, float, 0) ENDCLASS(XonoticPicmipSlider) entity makeXonoticPicmipSlider(); // note: you still need to call addValue and configureXonoticTextSliderValues! #endif @@ -19,23 +20,26 @@ void XonoticPicmipSlider_configureXonoticPicmipSlider(entity me) { me.configureXonoticTextSlider(me, "gl_picmip"); me.autofix(me); + me.have_s3tc = GL_Have_TextureCompression(); } -float texmemsize() +float texmemsize(float s3tc) { return ( - 2500 * pow(0.5, max(0, cvar("gl_picmip") + cvar("gl_picmip_other"))) - + 1500 * pow(0.5, max(0, cvar("gl_picmip") + cvar("gl_picmip_world"))) - ) * ((cvar("r_texture_dds_load") || cvar("gl_texturecompression")) ? 0.4 : 1.0); // TC: normalmaps 50%, other 25%, few incompressible, guessing 40% as conservative average + 2500 * pow(0.25, max(0, cvar("gl_picmip") + cvar("gl_picmip_other"))) + + 1500 * pow(0.25, max(0, cvar("gl_picmip") + cvar("gl_picmip_world"))) + ) * ((s3tc && (cvar("r_texture_dds_load") || cvar("gl_texturecompression"))) ? 0.2 : 1.0); // TC: normalmaps 50%, other 25%, few incompressible, guessing 40% as conservative average } void XonoticPicmipSlider_autofix(entity me) { float max_hard, max_soft; + if(cvar("menu_picmip_bypass")) + return; max_hard = cvar("sys_memsize_virtual"); max_soft = cvar("sys_memsize_physical"); if(max_hard > 0) { - while(me.value > 0 && texmemsize() > max_hard) + while(me.value > 0 && texmemsize(me.have_s3tc) > max_hard) me.setValue(me, me.value - 1); } // TODO also check the soft limit! diff --git a/qcsrc/menu/xonotic/slider_resolution.c b/qcsrc/menu/xonotic/slider_resolution.c index de34a410d9..2e3ea4ce4c 100644 --- a/qcsrc/menu/xonotic/slider_resolution.c +++ b/qcsrc/menu/xonotic/slider_resolution.c @@ -34,8 +34,8 @@ void updateConwidths() if(f < 1) c = c * f; // ensures that c_x <= r_x and c_y <= r_y - minfactor = min(1, 640 / c_x); // can be > 1 only if c_x is <640 - maxfactor = max3(1, r_x / c_x, r_y / c_y); // can be < 1 only if r_x < c_x and r_y < c_y + minfactor = min(1, 640 / c_x); // can be > 1 only if c_x is <640 + maxfactor = max(1, r_x / c_x, r_y / c_y); // can be < 1 only if r_x < c_x and r_y < c_y dprint("min factor: ", ftos(minfactor), "\n"); dprint("max factor: ", ftos(maxfactor), "\n"); @@ -62,7 +62,7 @@ entity makeXonoticResolutionSlider() } void XonoticResolutionSlider_addResolution(entity me, float w, float h, float pixelheight) { - me.addValue(me, strzone(strcat(ftos(w), "x", ftos(h))), strzone(strcat(ftos(w), " ", ftos(h), " ", ftos(pixelheight)))); + me.addValue(me, strzone(sprintf(_("%dx%d"), w, h)), strzone(strcat(ftos(w), " ", ftos(h), " ", ftos(pixelheight)))); // FIXME (in case you ever want to dynamically instantiate this): THIS IS NEVER FREED } void XonoticResolutionSlider_configureXonoticResolutionSlider(entity me) @@ -83,11 +83,24 @@ void XonoticResolutionSlider_configureXonoticResolutionSlider(entity me) if(r == r0) continue; r0 = r; - if(r_x < 640 || r_y < 400) + if(r_x < 640 || r_y < 480) + continue; + if(r_x > 2 * r_y) // likely dualscreen resolution, skip this one continue; me.addResolution(me, r_x, r_y, r_z); } + if(me.nValues == 0) + { + me.addResolution(me, 640, 480, 1); + me.addResolution(me, 800, 600, 1); + me.addResolution(me, 1024, 768, 1); + me.addResolution(me, 1280, 960, 1); + me.addResolution(me, 1280, 1024, 1); + me.addResolution(me, 1650, 1080, 1); + me.addResolution(me, 1920, 1080, 1); + } + me.configureXonoticTextSliderValues(me); } void XonoticResolutionSlider_loadCvars(entity me) diff --git a/qcsrc/menu/xonotic/util.qc b/qcsrc/menu/xonotic/util.qc index 1cb4cf50db..74fe810fe7 100644 --- a/qcsrc/menu/xonotic/util.qc +++ b/qcsrc/menu/xonotic/util.qc @@ -1,11 +1,21 @@ -float tooltipdb; +float GL_CheckExtension(string ext) +{ + return (strstrofs(strcat(" ", cvar_string("gl_info_extensions"), " "), strcat(" ", ext, " "), 0) >= 0); +} + +float GL_Have_TextureCompression() +{ + return (GL_CheckExtension("GL_EXT_texture_compression_s3tc") && GL_CheckExtension("GL_ARB_texture_compression")); +} + void loadTooltips() { - tooltipdb = db_load("tooltips.db"); + tooltipdb = db_load(language_filename("tooltips.db")); } void unloadTooltips() { - db_close(tooltipdb); + if(tooltipdb >= 0) + db_close(tooltipdb); tooltipdb = -1; } string getZonedTooltipForIdentifier(string s) @@ -13,14 +23,20 @@ string getZonedTooltipForIdentifier(string s) string t; if(s == "") return string_null; - t = db_get(tooltipdb, s); - if(t == "-") - return string_null; - if(t != "") - return strzone(t); - t = cvar_description(s); - if(t != "" && t != "custom cvar") - return strzone(t); + if(tooltipdb >= 0) + { + t = db_get(tooltipdb, s); + if(t == "-") + return string_null; + if(t != "") + return strzone(t); + } + if(prvm_language == "en" || prvm_language == "") + { + t = cvar_description(s); + if(t != "" && t != "custom cvar") + return strzone(t); + } dprint("WARNING: no tooltip set for ", s, "\n"); return string_null; } @@ -55,6 +71,12 @@ void loadAllCvars(entity root) .string cvarNames_Multi; .void(entity me) saveCvars_Multi; +string getCvarsMulti(entity me) +{ + if (me.cvarNames_Multi) + return me.cvarNames_Multi; + return string_null; +} void saveCvarsMulti(entity me) { float n, i; @@ -233,6 +255,7 @@ void setDependentWeird(entity e, float(entity) func) float _Nex_ExtResponseSystem_Queried; string _Nex_ExtResponseSystem_UpdateTo; +string _Nex_ExtResponseSystem_UpdateToURL; void URI_Get_Callback(float id, float status, string data) { @@ -250,7 +273,7 @@ void URI_Get_Callback(float id, float status, string data) } else { - print("Received HTTP request data for an invalid id ", ftos(id), ".\n"); + print(sprintf(_("Received HTTP request data for an invalid id %d.\n"), id)); } } @@ -260,22 +283,22 @@ void UpdateNotification_URI_Get_Callback(float id, float status, string data) if(_Nex_ExtResponseSystem_UpdateTo) { - print("error: UpdateNotification_URI_Get_Callback has been called before\n"); + dprint("error: UpdateNotification_URI_Get_Callback has been called before\n"); return; } if(status != 0) { - print(sprintf("error receiving update notification: status is %d\n", status)); + print(sprintf(_("error receiving update notification: status is %d\n"), status)); return; } if(substring(data, 0, 1) == "<") { - print("error: received HTML instead of an update notification\n"); + print(_("error: received HTML instead of an update notification\n")); return; } if(strstrofs(data, "\r", 0) != -1) { - print("error: received carriage returns from update notification server\n"); + print(_("error: received carriage returns from update notification server\n")); return; } @@ -296,10 +319,18 @@ void UpdateNotification_URI_Get_Callback(float id, float status, string data) { // update needed if(n >= 2) - print(sprintf("Update can be downloaded at:\n%s\n", argv(1))); + print(sprintf(_("Update can be downloaded at:\n%s\n"), argv(1))); + if(n >= 3) + _Nex_ExtResponseSystem_UpdateToURL = strzone(argv(2)); } _Nex_ExtResponseSystem_UpdateTo = strzone(_Nex_ExtResponseSystem_UpdateTo); + + if(n >= 4) + { + _Nex_ExtResponseSystem_BannedServers = strzone(argv(3)); + _Nex_ExtResponseSystem_BannedServersNeedsRefresh = 1; + } } } @@ -317,7 +348,7 @@ float preMenuInit() draw_reset_cropped(); sz = eX * 0.025 + eY * 0.025 * (draw_scale_x / draw_scale_y); - draw_CenterText('0.5 0.5 0' - 1.25 * sz_y * eY, "Autogenerating mapinfo for newly added maps...", sz, '1 1 1', 1, 0); + draw_CenterText('0.5 0.5 0' - 1.25 * sz_y * eY, _("Autogenerating mapinfo for newly added maps..."), sz, '1 1 1', 1, 0); boxA = '0.05 0.5 0' + 0.25 * sz_y * eY; boxB = '0.95 0.5 0' + 1.25 * sz_y * eY; @@ -347,7 +378,7 @@ void postMenuDraw() if(autocvar_menu_watermark != "") { vector fs = '48 48 0'; - draw_CenterText('0.5 0.1 0', autocvar_menu_watermark, globalToBoxSize('32 32 0', draw_scale), '1 1 1', 0.05, 1); + draw_CenterText('0.5 0.1 0', sprintf(_("^1%s TEST BUILD"), autocvar_menu_watermark), globalToBoxSize('32 32 0', draw_scale), '1 1 1', 0.05, 1); } } void preMenuDraw() @@ -404,16 +435,25 @@ void preMenuDraw() // TODO rather turn this into a dialog fs = ((1/draw_scale_x) * eX + (1/draw_scale_y) * eY) * 12; line = eY * fs_y; - sz_x = draw_TextWidth(" http://www.xonotic.com/ ", 0, fs); + string l1, l2; + l1 = sprintf(_("Update to %s now!"), _Nex_ExtResponseSystem_UpdateTo); + l2 = "http://www.xonotic.org/"; + if(_Nex_ExtResponseSystem_UpdateToURL) + l2 = _Nex_ExtResponseSystem_UpdateToURL; + + sz_x = draw_TextWidth(" ", 0, fs) + max( + draw_TextWidth(l1, 0, fs), + draw_TextWidth(l2, 0, fs) + ); sz_y = 3 * fs_y; - draw_alpha = sin(time * 0.112 - 0.3) * 10; + draw_alpha = bound(0, sin(time * 0.112 - 0.3) * 10, 1); mid = eX * (0.5 + 0.5 * (1 - sz_x) * cos(time * 0.071)) + eY * (0.5 + 0.5 * (1 - sz_y) * sin(time * 0.071)); draw_Fill(mid - 0.5 * sz, sz, '1 1 0', 1); - draw_CenterText(mid - 1 * line, strcat("Update to ", _Nex_ExtResponseSystem_UpdateTo, " now!"), fs, '1 0 0', 1, 0); - draw_CenterText(mid - 0 * line, "http://www.xonotic.org/", fs, '0 0 1', 1, 0); + draw_CenterText(mid - 1 * line, l1, fs, '1 0 0', 1, 0); + draw_CenterText(mid - 0 * line, l2, fs, '0 0 1', 1, 0); } if not(campaign_name_previous) campaign_name_previous = strzone(strcat(campaign_name, "x")); // force unequal @@ -447,10 +487,154 @@ string resolvemod(string m) return m; } -string HUD_Panel_GetSettingName(float theSetting) +float updateCompression() { - switch(theSetting) { - case HUD_MENU_ENABLE: return ""; break; - default: return ""; + float have_dds, have_jpg, have_tga; + float can_dds; + have_dds = (fexists("dds/particles/particlefont.dds")); + have_jpg = (fexists("particles/particlefont.jpg")); + have_tga = (fexists("particles/particlefont.tga")); + can_dds = GL_Have_TextureCompression(); + if(have_dds && (have_jpg || have_tga)) + { + // both? Let's only use good quality precompressed files + // but ONLY if we actually support it! + if(can_dds) + { + // these builds are meant to have GOOD quality, so let's not compress non-skinframes + cvar_set("gl_texturecompression", "0"); + return 1; + + //cvar_set("gl_texturecompression", cvar_string("r_texture_dds_load")); + //return 2; + } + else + { + cvar_set("gl_texturecompression", "0"); + cvar_set("r_texture_dds_load", "0"); + return 0; + } } + else if(have_dds) + { + // DDS only? We probably always want texture compression + cvar_set("gl_texturecompression", "1"); + cvar_set("r_texture_dds_load", "1"); + if(!can_dds) + print(_("^1ERROR: Texture compression is required but not supported.\n^1Expect visual problems.\n")); + return 0; + } + else + { + // TGA only? Allow runtime compression + if(can_dds) + { + cvar_set("gl_texturecompression", cvar_string("r_texture_dds_load")); + return 2; + } + else + { + cvar_set("gl_texturecompression", "0"); + cvar_set("r_texture_dds_load", "0"); + return 0; + } + } +} + +// note: include only those that should be in the menu! +#define GAMETYPES \ + GAMETYPE(MAPINFO_TYPE_ARENA) \ + GAMETYPE(MAPINFO_TYPE_ASSAULT) \ + GAMETYPE(MAPINFO_TYPE_CTF) \ + GAMETYPE(MAPINFO_TYPE_CA) \ + GAMETYPE(MAPINFO_TYPE_DEATHMATCH) \ + GAMETYPE(MAPINFO_TYPE_DOMINATION) \ + GAMETYPE(MAPINFO_TYPE_FREEZETAG) \ + GAMETYPE(MAPINFO_TYPE_KEEPAWAY) \ + GAMETYPE(MAPINFO_TYPE_KEYHUNT) \ + GAMETYPE(MAPINFO_TYPE_LMS) \ + GAMETYPE(MAPINFO_TYPE_NEXBALL) \ + GAMETYPE(MAPINFO_TYPE_ONSLAUGHT) \ + GAMETYPE(MAPINFO_TYPE_RACE) \ + GAMETYPE(MAPINFO_TYPE_CTS) \ + GAMETYPE(MAPINFO_TYPE_RUNEMATCH) \ + GAMETYPE(MAPINFO_TYPE_TEAM_DEATHMATCH) \ + /* nothing */ + +float GameType_GetID(float cnt) +{ + float i; + i = 0; +#define GAMETYPE(id) if(i++ == cnt) return id; + GAMETYPES +#undef GAMETYPE + return 0; +} +float GameType_GetCount() +{ + float i; + i = 0; +#define GAMETYPE(id) ++i; + GAMETYPES +#undef GAMETYPE + return i; +} + +void dialog_hudpanel_common_notoggle(entity me, string panelname) +{ + float i; + entity e; + + me.TR(me); + me.TD(me, 1, 1.4, e = makeXonoticTextLabel(0, _("Background:"))); + me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg")))); + e.addValue(e, _("Default"), ""); + e.addValue(e, _("Disable"), "0"); + e.addValue(e, strzone(strcat("border_", panelname)), strzone(strcat("border_", panelname))); + e.configureXonoticTextSliderValues(e); + me.TR(me); + me.TDempty(me, 0.2); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Color:"))); + me.TD(me, 2, 2.6, e = makeXonoticColorpickerString(strzone(strcat("hud_panel_", panelname, "_bg_color")), "hud_panel_bg_color")); + setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_bg_color")), ""); + me.TR(me); + me.TDempty(me, 0.2); + me.TD(me, 1, 1.0, e = makeXonoticCheckBoxString("", "1 1 1", strzone(strcat("hud_panel_", panelname, "_bg_color")), _("Use default"))); + me.TR(me); + me.TDempty(me, 0.2); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Border size:"))); + me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_border")))); + e.addValue(e, _("Default"), ""); + e.addValue(e, _("Disable"), "0"); + for(i = 1; i <= 10; ++i) + e.addValue(e, strzone(ftos_decimals(i * 2, 0)), strzone(ftos(i * 2))); + e.configureXonoticTextSliderValues(e); + me.TR(me); + me.TDempty(me, 0.2); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Alpha:"))); + me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_alpha")))); + e.addValue(e, _("Default"), ""); + for(i = 1; i <= 10; ++i) + e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); + e.configureXonoticTextSliderValues(e); + me.TR(me); + me.TDempty(me, 0.2); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Team Color:"))); + me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_color_team")))); + e.addValue(e, _("Default"), ""); + e.addValue(e, _("Disable"), "0"); + for(i = 1; i <= 10; ++i) + e.addValue(e, strzone(ftos_decimals(i/10, 1)), strzone(ftos(i/10))); + e.configureXonoticTextSliderValues(e); + me.TR(me); + me.TDempty(me, 0.4); + me.TD(me, 1, 3.6, e = makeXonoticCheckBox(0, "hud_configure_teamcolorforced", _("Test team color in configure mode"))); + me.TR(me); + me.TDempty(me, 0.2); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Padding:"))); + me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_bg_padding")))); + e.addValue(e, _("Default"), ""); + for(i = 0; i <= 10; ++i) + e.addValue(e, strzone(ftos_decimals(i - 5, 0)), strzone(ftos(i - 5))); + e.configureXonoticTextSliderValues(e); } diff --git a/qcsrc/menu/xonotic/util.qh b/qcsrc/menu/xonotic/util.qh index ace912dc21..6165fb3606 100644 --- a/qcsrc/menu/xonotic/util.qh +++ b/qcsrc/menu/xonotic/util.qh @@ -1,8 +1,12 @@ +float GL_CheckExtension(string ext); +float GL_Have_TextureCompression(); + void forAllDescendants(entity root, void(entity, entity) funcPre, void(entity, entity) funcPost, entity pass); void saveAllCvars(entity root); void loadAllCvars(entity root); void makeMulti(entity me, string otherCvars); +string getCvarsMulti(entity me); void makeCallback(entity me, entity cbent, void(entity, entity) cbfunc); void setDependent(entity e, string theCvarName, float theCvarMin, float theCvarMax); @@ -19,8 +23,6 @@ string getZonedTooltipForIdentifier(string s); string resolvemod(string m); -string HUD_Panel_GetSettingName(float setting); - float URI_GET_DISCARD = 0; float URI_GET_UPDATENOTIFICATION = 1; @@ -31,3 +33,19 @@ float URI_GET_CURL_END = 9; void Curl_URI_Get_Callback(float id, float status, string data); void URI_Get_Callback(float id, float status, string data); + +// game type list box stuff (does not NEED to contain all game types, other +// types stay available via console) +float GameType_GetID(float cnt); +float GameType_GetCount(); + +void dialog_hudpanel_common_notoggle(entity me, string panelname); +#define DIALOG_HUDPANEL_COMMON_NOTOGGLE() \ + dialog_hudpanel_common_notoggle(me, panelname) +#define DIALOG_HUDPANEL_COMMON() \ + me.TR(me); \ + me.TD(me, 1, 4, e = makeXonoticCheckBox(0, strzone(strcat("hud_panel_", panelname)), _("Enable panel"))); \ + DIALOG_HUDPANEL_COMMON_NOTOGGLE() + +string _Nex_ExtResponseSystem_BannedServers; +float _Nex_ExtResponseSystem_BannedServersNeedsRefresh; diff --git a/qcsrc/qc-client.cbp b/qcsrc/qc-client.cbp deleted file mode 100644 index 056b98ef27..0000000000 --- a/qcsrc/qc-client.cbp +++ /dev/null @@ -1,92 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> -<CodeBlocks_project_file> - <FileVersion major="1" minor="6" /> - <Project> - <Option title="qc-client" /> - <Option makefile="client" /> - <Option makefile_is_custom="1" /> - <Option pch_mode="2" /> - <Option compiler="qaukec" /> - <Build> - <Target title="Debug"> - <Option output="bin\Debug\qc-server" prefix_auto="1" extension_auto="1" /> - <Option object_output="obj\Debug\" /> - <Option type="1" /> - <Option compiler="qaukec" /> - <Compiler> - <Add option="-g" /> - </Compiler> - <MakeCommands> - <Build command="$make -src $makefile" /> - <CompileFile command="" /> - <Clean command="" /> - <DistClean command="" /> - </MakeCommands> - </Target> - <Target title="Release"> - <Option output="bin\Release\qc-server" prefix_auto="1" extension_auto="1" /> - <Option object_output="obj\Release\" /> - <Option type="1" /> - <Option compiler="qaukec" /> - <Compiler> - <Add option="-O2" /> - </Compiler> - <Linker> - <Add option="-s" /> - </Linker> - <MakeCommands> - <Build command="$make -src $makefile" /> - <CompileFile command="" /> - <Clean command="" /> - <DistClean command="" /> - </MakeCommands> - </Target> - </Build> - <Compiler> - <Add option="-Wall" /> - </Compiler> - <Unit filename="client\Defs.qc" /> - <Unit filename="client\Main.qc" /> - <Unit filename="client\View.qc" /> - <Unit filename="client\autocvars.qh" /> - <Unit filename="client\bgmscript.qc" /> - <Unit filename="client\bgmscript.qh" /> - <Unit filename="client\casings.qc" /> - <Unit filename="client\csqc_builtins.qc" /> - <Unit filename="client\csqc_constants.qc" /> - <Unit filename="client\ctf.qc" /> - <Unit filename="client\damage.qc" /> - <Unit filename="client\effects.qc" /> - <Unit filename="client\gibs.qc" /> - <Unit filename="client\hook.qc" /> - <Unit filename="client\interpolate.qc" /> - <Unit filename="client\interpolate.qh" /> - <Unit filename="client\laser.qc" /> - <Unit filename="client\main.qh" /> - <Unit filename="client\mapvoting.qc" /> - <Unit filename="client\miscfunctions.qc" /> - <Unit filename="client\modeleffects.qc" /> - <Unit filename="client\movetypes.qc" /> - <Unit filename="client\movetypes.qh" /> - <Unit filename="client\particles.qc" /> - <Unit filename="client\prandom.qc" /> - <Unit filename="client\prandom.qh" /> - <Unit filename="client\pre.qh" /> - <Unit filename="client\progs.src" /> - <Unit filename="client\projectile.qc" /> - <Unit filename="client\rubble.qc" /> - <Unit filename="client\sbar.qc" /> - <Unit filename="client\sortlist.qc" /> - <Unit filename="client\teamplay.qc" /> - <Unit filename="client\teamradar.qc" /> - <Unit filename="client\teamradar.qh" /> - <Unit filename="client\tuba.qc" /> - <Unit filename="client\wall.qc" /> - <Unit filename="client\waypointsprites.qc" /> - <Unit filename="client\waypointsprites.qh" /> - <Extensions> - <code_completion /> - <debugger /> - </Extensions> - </Project> -</CodeBlocks_project_file> diff --git a/qcsrc/qc-common.cbp b/qcsrc/qc-common.cbp deleted file mode 100644 index 95f1ba836e..0000000000 --- a/qcsrc/qc-common.cbp +++ /dev/null @@ -1,65 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> -<CodeBlocks_project_file> - <FileVersion major="1" minor="6" /> - <Project> - <Option title="qc-common" /> - <Option makefile="none" /> - <Option makefile_is_custom="1" /> - <Option pch_mode="2" /> - <Option compiler="qaukec" /> - <Build> - <Target title="Debug"> - <Option output="bin\Debug\qc-server" prefix_auto="1" extension_auto="1" /> - <Option object_output="obj\Debug\" /> - <Option type="1" /> - <Option compiler="qaukec" /> - <Compiler> - <Add option="-g" /> - </Compiler> - <MakeCommands> - <Build command="$make -src $makefile" /> - <CompileFile command="" /> - <Clean command="" /> - <DistClean command="" /> - </MakeCommands> - </Target> - <Target title="Release"> - <Option output="bin\Release\qc-server" prefix_auto="1" extension_auto="1" /> - <Option object_output="obj\Release\" /> - <Option type="1" /> - <Option compiler="qaukec" /> - <Compiler> - <Add option="-O2" /> - </Compiler> - <Linker> - <Add option="-s" /> - </Linker> - <MakeCommands> - <Build command="$make -src $makefile" /> - <CompileFile command="" /> - <Clean command="" /> - <DistClean command="" /> - </MakeCommands> - </Target> - </Build> - <Compiler> - <Add option="-Wall" /> - </Compiler> - <Unit filename="common\campaign_common.qh" /> - <Unit filename="common\campaign_file.qc" /> - <Unit filename="common\campaign_setup.qc" /> - <Unit filename="common\constants.qh" /> - <Unit filename="common\gamecommand.qc" /> - <Unit filename="common\items.qc" /> - <Unit filename="common\items.qh" /> - <Unit filename="common\mapinfo.qc" /> - <Unit filename="common\mapinfo.qh" /> - <Unit filename="common\util-pre.qh" /> - <Unit filename="common\util.qc" /> - <Unit filename="common\util.qh" /> - <Extensions> - <code_completion /> - <debugger /> - </Extensions> - </Project> -</CodeBlocks_project_file> diff --git a/qcsrc/qc-server.cbp b/qcsrc/qc-server.cbp deleted file mode 100644 index eaa30d2d46..0000000000 --- a/qcsrc/qc-server.cbp +++ /dev/null @@ -1,213 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> -<CodeBlocks_project_file> - <FileVersion major="1" minor="6" /> - <Project> - <Option title="qc-server" /> - <Option makefile="server/" /> - <Option makefile_is_custom="1" /> - <Option pch_mode="2" /> - <Option compiler="qaukec" /> - <Build> - <Target title="Debug"> - <Option output="bin\Debug\qc-server" prefix_auto="1" extension_auto="1" /> - <Option object_output="obj\Debug\" /> - <Option type="1" /> - <Option compiler="qaukec" /> - <Compiler> - <Add option="-g" /> - </Compiler> - <MakeCommands> - <Build command="$make -DVEHICLES_ENABLED -DRELEASE -src $makefile" /> - <CompileFile command="" /> - <Clean command="" /> - <DistClean command="" /> - </MakeCommands> - </Target> - <Target title="Release"> - <Option output="bin\Release\qc-server" prefix_auto="1" extension_auto="1" /> - <Option object_output="obj\Release\" /> - <Option type="1" /> - <Option compiler="qaukec" /> - <Compiler> - <Add option="-O2" /> - </Compiler> - <Linker> - <Add option="-s" /> - </Linker> - <MakeCommands> - <Build command="$make -DVEHICLES_ENABLED -DRELEASE -src $makefile" /> - <CompileFile command="" /> - <Clean command="" /> - <DistClean command="" /> - </MakeCommands> - </Target> - </Build> - <Compiler> - <Add option="-Wall" /> - </Compiler> - <Unit filename="anticheat.qc" /> - <Unit filename="anticheat.qh" /> - <Unit filename="antilag.qc" /> - <Unit filename="antilag.qh" /> - <Unit filename="arena.qc" /> - <Unit filename="assault.qc" /> - <Unit filename="bot\aim.qc" /> - <Unit filename="bot\aim.qh" /> - <Unit filename="bot\bot.qc" /> - <Unit filename="bot\bot.qh" /> - <Unit filename="bot\havocbot\havocbot.qc" /> - <Unit filename="bot\havocbot\havocbot.qh" /> - <Unit filename="bot\havocbot\role_ctf.qc" /> - <Unit filename="bot\havocbot\role_keyhunt.qc" /> - <Unit filename="bot\havocbot\role_onslaught.qc" /> - <Unit filename="bot\havocbot\roles.qc" /> - <Unit filename="bot\navigation.qc" /> - <Unit filename="bot\navigation.qh" /> - <Unit filename="bot\scripting.qc" /> - <Unit filename="bot\waypoints.qc" /> - <Unit filename="bot\waypoints.qh" /> - <Unit filename="builtins.qh" /> - <Unit filename="campaign.qc" /> - <Unit filename="campaign.qh" /> - <Unit filename="cheats.qc" /> - <Unit filename="cheats.qh" /> - <Unit filename="cl_client.qc" /> - <Unit filename="cl_impulse.qc" /> - <Unit filename="cl_physics.qc" /> - <Unit filename="cl_player.qc" /> - <Unit filename="cl_weapons.qc" /> - <Unit filename="cl_weaponsystem.qc" /> - <Unit filename="clientcommands.qc" /> - <Unit filename="constants.qh" /> - <Unit filename="csqceffects.qc" /> - <Unit filename="csqcprojectile.qc" /> - <Unit filename="csqcprojectile.qh" /> - <Unit filename="ctf.qc" /> - <Unit filename="defs.qh" /> - <Unit filename="domination.qc" /> - <Unit filename="ent_cs.qc" /> - <Unit filename="extensions.qh" /> - <Unit filename="func_breakable.qc" /> - <Unit filename="g_casings.qc" /> - <Unit filename="g_damage.qc" /> - <Unit filename="g_hook.qc" /> - <Unit filename="g_hook.qh" /> - <Unit filename="g_lights.qc" /> - <Unit filename="g_models.qc" /> - <Unit filename="g_subs.qc" /> - <Unit filename="g_swamp.qc" /> - <Unit filename="g_tetris.qc" /> - <Unit filename="g_triggers.qc" /> - <Unit filename="g_violence.qc" /> - <Unit filename="g_world.qc" /> - <Unit filename="gamecommand.qc" /> - <Unit filename="ipban.qc" /> - <Unit filename="ipban.qh" /> - <Unit filename="miscfunctions.qc" /> - <Unit filename="mode_onslaught.qc" /> - <Unit filename="monsters\ai.qc" /> - <Unit filename="monsters\defs.qc" /> - <Unit filename="monsters\fight.qc" /> - <Unit filename="monsters\m_monsters.qc" /> - <Unit filename="monsters\mode_management.qc" /> - <Unit filename="monsters\monster_zombie.qc" /> - <Unit filename="movelib.qc" /> - <Unit filename="mutators\base.qc" /> - <Unit filename="mutators\base.qh" /> - <Unit filename="mutators\gamemode_keyhunt.qc" /> - <Unit filename="mutators\gamemode_keyhunt.qh" /> - <Unit filename="mutators\mutator_dodging.qc" /> - <Unit filename="mutators\mutator_dodging.qh" /> - <Unit filename="mutators\mutator_nix.qc" /> - <Unit filename="mutators\mutators.qh" /> - <Unit filename="nexball.qc" /> - <Unit filename="pathlib.qc" /> - <Unit filename="pathlib\costs.qc" /> - <Unit filename="pathlib\debug.qc" /> - <Unit filename="pathlib\expandnode.qc" /> - <Unit filename="pathlib\main.qc" /> - <Unit filename="pathlib\movenode.qc" /> - <Unit filename="pathlib\pathlib.qh" /> - <Unit filename="pathlib\utility.qc" /> - <Unit filename="playerdemo.qc" /> - <Unit filename="playerdemo.qh" /> - <Unit filename="portals.qc" /> - <Unit filename="portals.qh" /> - <Unit filename="post-builtins.qh" /> - <Unit filename="pre-builtins.qh" /> - <Unit filename="progs.src" /> - <Unit filename="race.qc" /> - <Unit filename="race.qh" /> - <Unit filename="runematch.qc" /> - <Unit filename="scores.qc" /> - <Unit filename="scores.qh" /> - <Unit filename="scores_rules.qc" /> - <Unit filename="steerlib.qc" /> - <Unit filename="sv_main.qc" /> - <Unit filename="sv_stats.qc" /> - <Unit filename="sys.qh" /> - <Unit filename="t_halflife.qc" /> - <Unit filename="t_items.qc" /> - <Unit filename="t_jumppads.qc" /> - <Unit filename="t_plats.qc" /> - <Unit filename="t_quake.qc" /> - <Unit filename="t_quake3.qc" /> - <Unit filename="t_swamp.qc" /> - <Unit filename="t_teleporters.qc" /> - <Unit filename="target_spawn.qc" /> - <Unit filename="teamplay.qc" /> - <Unit filename="tturrets\include\turrets.qh" /> - <Unit filename="tturrets\include\turrets_early.qh" /> - <Unit filename="tturrets\system\system_aimprocs.qc" /> - <Unit filename="tturrets\system\system_damage.qc" /> - <Unit filename="tturrets\system\system_main.qc" /> - <Unit filename="tturrets\system\system_misc.qc" /> - <Unit filename="tturrets\system\system_scoreprocs.qc" /> - <Unit filename="tturrets\units\unit_checkpoint.qc" /> - <Unit filename="tturrets\units\unit_common.qc" /> - <Unit filename="tturrets\units\unit_ewheel.qc" /> - <Unit filename="tturrets\units\unit_flac.qc" /> - <Unit filename="tturrets\units\unit_fusionreactor.qc" /> - <Unit filename="tturrets\units\unit_hellion.qc" /> - <Unit filename="tturrets\units\unit_hk.qc" /> - <Unit filename="tturrets\units\unit_machinegun.qc" /> - <Unit filename="tturrets\units\unit_mlrs.qc" /> - <Unit filename="tturrets\units\unit_phaser.qc" /> - <Unit filename="tturrets\units\unit_plasma.qc" /> - <Unit filename="tturrets\units\unit_targettrigger.qc" /> - <Unit filename="tturrets\units\unit_tessla.qc" /> - <Unit filename="tturrets\units\unit_walker.qc" /> - <Unit filename="vehicles\racer.qc" /> - <Unit filename="vehicles\raptor.qc" /> - <Unit filename="vehicles\spiderbot.qc" /> - <Unit filename="vehicles\vehicles.qc" /> - <Unit filename="vehicles\vehicles.qh" /> - <Unit filename="verbstack.qc" /> - <Unit filename="vote.qc" /> - <Unit filename="vote.qh" /> - <Unit filename="w_all.qc" /> - <Unit filename="w_campingrifle.qc" /> - <Unit filename="w_common.qc" /> - <Unit filename="w_crylink.qc" /> - <Unit filename="w_electro.qc" /> - <Unit filename="w_fireball.qc" /> - <Unit filename="w_grenadelauncher.qc" /> - <Unit filename="w_minelayer.qc" /> - <Unit filename="w_hagar.qc" /> - <Unit filename="w_hlac.qc" /> - <Unit filename="w_hook.qc" /> - <Unit filename="w_laser.qc" /> - <Unit filename="w_minstanex.qc" /> - <Unit filename="w_nex.qc" /> - <Unit filename="w_porto.qc" /> - <Unit filename="w_rocketlauncher.qc" /> - <Unit filename="w_shotgun.qc" /> - <Unit filename="w_tuba.qc" /> - <Unit filename="w_uzi.qc" /> - <Unit filename="waypointsprites.qc" /> - <Extensions> - <code_completion /> - <debugger /> - </Extensions> - </Project> -</CodeBlocks_project_file> diff --git a/qcsrc/server/accuracy.qc b/qcsrc/server/accuracy.qc index 4d63fd8200..de6b52752b 100644 --- a/qcsrc/server/accuracy.qc +++ b/qcsrc/server/accuracy.qc @@ -1,8 +1,7 @@ -.entity accuracy; .float accuracy_hit[WEP_MAXCOUNT]; .float accuracy_fired[WEP_MAXCOUNT]; -FTEQCC_YOU_SUCK_THIS_IS_NOT_UNREFERENCED(accuracy_hit); -FTEQCC_YOU_SUCK_THIS_IS_NOT_UNREFERENCED(accuracy_fired); +.float accuracy_cnt_hit[WEP_MAXCOUNT]; +.float accuracy_cnt_fired[WEP_MAXCOUNT]; float accuracy_byte(float n, float d) { @@ -74,6 +73,11 @@ void accuracy_set(entity e, float w, float fired, float hit) b = accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w])); a.(accuracy_hit[w]) = hit; a.(accuracy_fired[w]) = fired; + + if(hit) + a.(accuracy_cnt_hit[w]) = 1; + a.(accuracy_cnt_fired[w]) = 1; + if(b == accuracy_byte(hit, fired)) return; w = pow(2, w); @@ -84,6 +88,9 @@ void accuracy_set(entity e, float w, float fired, float hit) a.SendFlags |= w; } +.float hit_time; +.float fired_time; + void accuracy_add(entity e, float w, float fired, float hit) { entity a; @@ -97,6 +104,19 @@ void accuracy_add(entity e, float w, float fired, float hit) a.(accuracy_hit[w]) += hit; if(fired) a.(accuracy_fired[w]) += fired; + + if(hit && a.hit_time != time) // only run this once per frame + { + a.(accuracy_cnt_hit[w]) += 1; + a.hit_time = time; + } + + if(fired && a.fired_time != time) // only run this once per frame + { + a.(accuracy_cnt_fired[w]) += 1; + a.fired_time = time; + } + if(b == accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w]))) return; w = pow(2, w); diff --git a/qcsrc/server/anticheat.qc b/qcsrc/server/anticheat.qc index 1da6ad3ec6..d00c60b09d 100644 --- a/qcsrc/server/anticheat.qc +++ b/qcsrc/server/anticheat.qc @@ -1,3 +1,5 @@ +.float anticheat_jointime; + void mean_accumulate(entity e, .float a, .float c, float mean, float value, float weight) { if(weight == 0) @@ -67,14 +69,14 @@ void anticheat_physics() { if(time < self.anticheat_div0_evade_offset) self.anticheat_div0_evade_v_angle = self.v_angle; - MEAN_ACCUMULATE(anticheat_div0_evade, 1 - (self.anticheat_div0_evade_forward_initial * v_forward), 1); + MEAN_ACCUMULATE(anticheat_div0_evade, 0.5 - 0.5 * (self.anticheat_div0_evade_forward_initial * v_forward), 1); } - MEAN_ACCUMULATE(anticheat_div0_strafebot_old, movement_oddity(self.movement, self.anticheat_div0_strafebot_movement_prev), max(0, sys_frametime - frametime)); + MEAN_ACCUMULATE(anticheat_div0_strafebot_old, movement_oddity(self.movement, self.anticheat_div0_strafebot_movement_prev), 1); self.anticheat_div0_strafebot_movement_prev = self.movement; if(vlen(self.anticheat_div0_strafebot_forward_prev)) - MEAN_ACCUMULATE(anticheat_div0_strafebot_new, 1 - (self.anticheat_div0_strafebot_forward_prev * v_forward), max(0, sys_frametime - frametime)); + MEAN_ACCUMULATE(anticheat_div0_strafebot_new, 0.5 - 0.5 * (self.anticheat_div0_strafebot_forward_prev * v_forward), 1); self.anticheat_div0_strafebot_forward_prev = v_forward; // generic speedhack detection: correlate anticheat_speedhack_movetime (UPDATED BEFORE THIS) and server time @@ -88,7 +90,7 @@ void anticheat_physics() self.anticheat_speedhack_offset = f; else { - MEAN_ACCUMULATE(anticheat_speedhack, fabs(f - self.anticheat_speedhack_offset), 1); + MEAN_ACCUMULATE(anticheat_speedhack, max(0, f - self.anticheat_speedhack_offset), 1); self.anticheat_speedhack_offset += (f - self.anticheat_speedhack_offset) * frametime * 0.1; } @@ -151,14 +153,26 @@ void anticheat_prethink() self.anticheat_div0_evade_offset = 0; } +string anticheat_display(float f, float tmin, float mi, float ma) +{ + string s; + s = ftos(f); + if(f <= mi) + return strcat(s, ":N"); + if(f >= ma) + return strcat(s, ":Y"); + return strcat(s, ":-"); +} + void anticheat_report() { if(!autocvar_sv_eventlog) return; - GameLogEcho(strcat(":anticheat:speedhack:", ftos(self.playerid), ":", ftos(MEAN_EVALUATE(anticheat_speedhack)))); - GameLogEcho(strcat(":anticheat:div0_strafebot_old:", ftos(self.playerid), ":", ftos(MEAN_EVALUATE(anticheat_div0_strafebot_old)))); - GameLogEcho(strcat(":anticheat:div0_strafebot_new:", ftos(self.playerid), ":", ftos(MEAN_EVALUATE(anticheat_div0_strafebot_new)))); - GameLogEcho(strcat(":anticheat:div0_evade:", ftos(self.playerid), ":", ftos(MEAN_EVALUATE(anticheat_div0_evade)))); + GameLogEcho(strcat(":anticheat:_time:", ftos(self.playerid), ":", ftos(servertime - self.anticheat_jointime))); + GameLogEcho(strcat(":anticheat:speedhack:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack), 240, 0.1, 0.15))); + GameLogEcho(strcat(":anticheat:div0_strafebot_old:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_div0_strafebot_old), 120, 0.3, 0.4))); + GameLogEcho(strcat(":anticheat:div0_strafebot_new:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_div0_strafebot_new), 120, 0.3, 0.4))); + GameLogEcho(strcat(":anticheat:div0_evade:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_div0_evade), 120, 0.1, 0.2))); } void anticheat_serverframe() @@ -169,6 +183,7 @@ void anticheat_serverframe() void anticheat_init() { self.anticheat_speedhack_offset = 0; + self.anticheat_jointime = servertime; } void anticheat_shutdown() diff --git a/qcsrc/server/antilag.qc b/qcsrc/server/antilag.qc index 8a628a1bea..68ec68324d 100644 --- a/qcsrc/server/antilag.qc +++ b/qcsrc/server/antilag.qc @@ -3,6 +3,7 @@ .float antilag_times[ANTILAG_MAX_ORIGINS]; .float antilag_index; .vector antilag_saved_origin; +.float antilag_takenback; .float antilag_debug; @@ -14,6 +15,9 @@ void antilag_dummy() void antilag_record(entity e, float t) { + if(e.vehicle) + antilag_record(e.vehicle, t); + if(time < e.(antilag_times[e.antilag_index])) return; e.antilag_index = e.antilag_index + 1; @@ -24,6 +28,7 @@ void antilag_record(entity e, float t) if(e.antilag_debug) te_spark(antilag_takebackorigin(e, t - e.antilag_debug), '0 0 0', 32); + } // finds the index BEFORE t @@ -61,9 +66,11 @@ vector antilag_takebackorigin(entity e, float t) i0 = antilag_find(e, t); if(i0 < 0) { - i0 = e.antilag_index - 1; - if(i0 < 0) - i0 = ANTILAG_MAX_ORIGINS - 1; + // IN THE PRESENT + if(e.antilag_takenback) + return e.antilag_saved_origin; + else + return e.origin; } i1 = i0 + 1; if(i1 >= ANTILAG_MAX_ORIGINS) @@ -75,6 +82,7 @@ vector antilag_takebackorigin(entity e, float t) vector antilag_takebackavgvelocity(entity e, float t0, float t1) { vector o0, o1; + if(t0 >= t1) return '0 0 0'; o0 = antilag_takebackorigin(e, t0); @@ -84,11 +92,37 @@ vector antilag_takebackavgvelocity(entity e, float t0, float t1) void antilag_takeback(entity e, float t) { - e.antilag_saved_origin = e.origin; + if(e.vehicle) + antilag_takeback(e.vehicle, t); + + if(!e.antilag_takenback) + e.antilag_saved_origin = e.origin; + setorigin(e, antilag_takebackorigin(e, t)); + e.antilag_takenback = TRUE; } void antilag_restore(entity e) { + if(e.vehicle) + antilag_restore(e.vehicle); + + if(!e.antilag_takenback) + return; + setorigin(e, e.antilag_saved_origin); + e.antilag_takenback = FALSE; +} + +void antilag_clear(entity e) +{ + float i; + + antilag_restore(e); + for(i = 0; i < ANTILAG_MAX_ORIGINS; ++i) + { + e.(antilag_times[i]) = -2342; + e.(antilag_origins[i]) = self.origin; + } + e.antilag_index = ANTILAG_MAX_ORIGINS - 1; // next one is 0 } diff --git a/qcsrc/server/antilag.qh b/qcsrc/server/antilag.qh index 2a7343243d..cadb45a14d 100644 --- a/qcsrc/server/antilag.qh +++ b/qcsrc/server/antilag.qh @@ -1,9 +1,9 @@ void antilag_record(entity e, float t); -float antilag_find(entity e, float t); vector antilag_takebackorigin(entity e, float t); vector antilag_takebackavgvelocity(entity e, float t0, float t1); void antilag_takeback(entity e, float t); void antilag_restore(entity e); +void antilag_clear(entity e); #define ANTILAG_LATENCY(e) min(0.4, e.ping * 0.001) // add one ticrate? diff --git a/qcsrc/server/arena.qc b/qcsrc/server/arena.qc index 5110d373b8..c89c2b2efa 100644 --- a/qcsrc/server/arena.qc +++ b/qcsrc/server/arena.qc @@ -8,10 +8,8 @@ float arena_roundbased; entity spawnqueue_first; entity spawnqueue_last; entity champion; -string champion_name; float warmup; -float ca_players; -float required_ca_players; +float ca_teams_ok; .float caplayer; void PutObserverInServer(); @@ -29,8 +27,8 @@ float stopalivecheck; float redalive, bluealive, yellowalive, pinkalive; float totalalive; .float redalive_stat, bluealive_stat, yellowalive_stat, pinkalive_stat; -float redspawned, bluespawned, yellowspawned, pinkspawned; -float totalspawned; +float red_players, blue_players, yellow_players, pink_players; +float total_players; /** * Resets the state of all clients, items, flags, runes, keys, weapons, waypoints, ... of the map. @@ -70,10 +68,7 @@ void reset_map(float dorespawn) self.team = self.team_saved; if(self.flags & FL_PROJECTILE) // remove any projectiles left - { - stopsound(self, CHAN_PAIN); remove(self); - } } // Waypoints and assault start come LAST @@ -137,7 +132,7 @@ void reset_map(float dorespawn) } if(g_keyhunt) - kh_Controller_SetThink(autocvar_g_balance_keyhunt_delay_round+(game_starttime - time), "", kh_StartRound); + kh_Controller_SetThink_NoMsg(autocvar_g_balance_keyhunt_delay_round+(game_starttime - time), kh_StartRound); if(g_arena) if(champion && champion.classname == "player" && player_count > 1) @@ -207,35 +202,31 @@ float roundStartTime_prev; // prevent networkspam void Arena_Warmup() { float f; - string msg; entity e; if((!g_arena && !g_ca && !g_freezetag) || (g_arena && !arena_roundbased) || (time < game_starttime)) return; f = ceil(warmup - time); - if(f > 0) - champion = world; // this is done because a if(champion) will not execute if champion = world allowed_to_spawn = 0; if(inWarmupStage) allowed_to_spawn = 1; - if(ca_players < required_ca_players) + if(g_ca && !ca_teams_ok) allowed_to_spawn = 1; - msg = NEWLINES; if(time < warmup && !inWarmupStage) { if (g_ca) allowed_to_spawn = 1; if(champion && g_arena) - msg = strcat("The Champion is ", champion_name, "^7\n"); - //centerprint(self, strcat(msg, "The Champion is ", champion.netname, "^7\n")); + { + FOR_EACH_PLAYER(e) + centerprint(e, strcat("The Champion is ", champion.netname)); + } if(f != roundStartTime_prev) { - msg = strcat(msg, "Round will start in ", ftos(f),"\n"); - //centerprint(self, strcat("Round will start in ", ftos(f),"\n")); roundStartTime_prev = f; if(f == 5) Announce("prepareforbattle"); @@ -246,8 +237,8 @@ void Arena_Warmup() else if(f == 1) Announce("1"); - FOR_EACH_PLAYER(e) - centerprint(e, msg); + FOR_EACH_PLAYER(e) + Send_CSQC_Centerprint_Generic(e, CPID_ROUND_STARTING, "Round will start in %d", 1, f); } if (g_arena) { @@ -257,56 +248,62 @@ void Arena_Warmup() self.velocity = '0 0 0'; self.avelocity = '0 0 0'; self.movement = '0 0 0'; - //self.fixangle = TRUE; } } - else if(f > -1 && f != roundStartTime_prev) { roundStartTime_prev = f; Announce("begin"); - centerprint(self, "^1Begin!\n"); + FOR_EACH_PLAYER(e) + Send_CSQC_Centerprint_Generic(e, CPID_ROUND_STARTING, "^1Begin!", 1, 0); if(g_ca) { - ca_players = 0; + float start_red_ca_players, start_blue_ca_players; - FOR_EACH_PLAYER(e) - ca_players += 1; + FOR_EACH_PLAYER(e) { + if (e.team == COLOR_TEAM1) + start_red_ca_players += 1; + else if (e.team == COLOR_TEAM2) + start_blue_ca_players += 1; + } + // teams are ok if there's at least 1 player in each team + ca_teams_ok = (start_red_ca_players && start_blue_ca_players); } if(self.classname == "player" && self.health > 0 && self.movetype == MOVETYPE_NONE) self.movetype = MOVETYPE_WALK; + } + + // clear champion to avoid centerprinting again the champion msg + if (champion) + champion = world; } -void count_spawned_players() +void count_players() { - // TODO fix "*spawned" name, it should rather be "*players" or so - // not doing this now to prevent merge hell with Tag - // fix after merging with Tag - // count amount of players in each team - totalspawned = redspawned = bluespawned = yellowspawned = pinkspawned = 0; + total_players = red_players = blue_players = yellow_players = pink_players = 0; FOR_EACH_PLAYER(self) { if (self.team == COLOR_TEAM1) { - redspawned += 1; - totalspawned += 1; + red_players += 1; + total_players += 1; } else if (self.team == COLOR_TEAM2) { - bluespawned += 1; - totalspawned += 1; + blue_players += 1; + total_players += 1; } else if (self.team == COLOR_TEAM3) { - yellowspawned += 1; - totalspawned += 1; + yellow_players += 1; + total_players += 1; } else if (self.team == COLOR_TEAM4) { - pinkspawned += 1; - totalspawned += 1; + pink_players += 1; + total_players += 1; } } } @@ -328,7 +325,7 @@ void count_alive_players() totalalive += 1; } } - FOR_EACH_PLAYER(self) { + FOR_EACH_REALCLIENT(self) { self.redalive_stat = redalive; self.bluealive_stat = bluealive; } @@ -358,7 +355,7 @@ void count_alive_players() totalalive += 1; } } - FOR_EACH_PLAYER(self) { + FOR_EACH_REALCLIENT(self) { self.redalive_stat = redalive; self.bluealive_stat = bluealive; self.yellowalive_stat = yellowalive; @@ -375,9 +372,10 @@ void count_alive_players() * * Gets called in StartFrame() */ +float warntime; void Spawnqueue_Check() { - count_spawned_players(); + count_players(); if(g_ca || g_freezetag) // we want to perform this before the return block below (CA)... { count_alive_players(); @@ -386,26 +384,24 @@ void Spawnqueue_Check() return; if(g_ca) { - required_ca_players = max(2, fabs(autocvar_bot_vs_human + 1)); - - if(ca_players < required_ca_players && (redspawned && bluespawned)) { + if(!ca_teams_ok && (red_players && blue_players)) { reset_map(TRUE); } - else if(ca_players < required_ca_players) { - FOR_EACH_PLAYER(self) - centerprint(self, strcat("^1Need at least 1 player in each team to play CA", "^7\n")); + else if(!ca_teams_ok) { + if (time > warntime) + { + FOR_EACH_PLAYER(self) + Send_CSQC_Centerprint_Generic(self, CPID_ROUND_STARTING, "^1Need at least 1 player in each team to play CA", 2, 0); + warntime = time + 1; + } return; } else if(!next_round) { - if((redspawned && !bluespawned) || (bluespawned && !redspawned)) { + if((red_players && !blue_players) || (blue_players && !red_players)) { next_round = time + 5; - champion = find(world, classname, "player"); - if(champion_name) - strunzone(champion_name); - champion_name = strzone(champion.netname); } - else if((!redspawned && !bluespawned) || time - warmup > autocvar_g_ca_round_timelimit) { - FOR_EACH_CLIENT(self) centerprint(self, strcat("^7Round tied.", "^7\n")); + else if((!red_players && !blue_players) || time - warmup > autocvar_g_ca_round_timelimit) { + FOR_EACH_CLIENT(self) centerprint(self, "^7Round tied"); next_round = time + 5; } @@ -415,14 +411,14 @@ void Spawnqueue_Check() if(redalive && !bluealive) { play2all("ctf/red_capture.wav"); - FOR_EACH_CLIENT(self) centerprint(self, "^1 RED ^7team wins the round.\n"); + FOR_EACH_CLIENT(self) centerprint(self, "^1RED ^7team wins the round"); TeamScore_AddToTeam(COLOR_TEAM1, ST_SCORE, +1); stopalivecheck = TRUE; } else if(bluealive && !redalive) { play2all("ctf/blue_capture.wav"); - FOR_EACH_CLIENT(self) centerprint(self, "^4 BLUE ^7team wins the round.\n"); + FOR_EACH_CLIENT(self) centerprint(self, "^4BLUE ^7team wins the round"); TeamScore_AddToTeam(COLOR_TEAM2, ST_SCORE, +1); stopalivecheck = TRUE; } diff --git a/qcsrc/server/assault.qc b/qcsrc/server/assault.qc index 0d7da73572..2562dca3df 100644 --- a/qcsrc/server/assault.qc +++ b/qcsrc/server/assault.qc @@ -30,9 +30,6 @@ void assault_objective_reset() { } void assault_objective_use() { - if(other.classname == "info_player_deathmatch") // a spawn, a spawn - return; - // activate objective self.health = 100; //print("^2Activated objective ", self.targetname, "=", etos(self), "\n"); @@ -50,6 +47,13 @@ void assault_objective_use() { self = oldself; } +vector target_objective_spawn_evalfunc(entity player, entity spot, vector current) +{ + if(self.health < 0 || self.health >= ASSAULT_VALUE_INACTIVE) + return '-1 0 0'; + return current; +} + void spawnfunc_target_objective() { if(!g_assault) { @@ -60,6 +64,7 @@ void spawnfunc_target_objective() { self.use = assault_objective_use; assault_objective_reset(); self.reset = assault_objective_reset; + self.spawn_evalfunc = target_objective_spawn_evalfunc; } @@ -71,7 +76,11 @@ void assault_objective_decrease_use() { } if(other.assault_sprite) + { WaypointSprite_Disown(other.assault_sprite, waypointsprite_deadlifetime); + if(other.classname == "func_assault_destructible") + other.sprite = world; + } else return; // already activated! cannot activate again! @@ -102,7 +111,7 @@ void assault_objective_decrease_use() { centerprint(player, s); } } - + oldactivator = activator; activator = oldself; SUB_UseTargets(); @@ -114,7 +123,7 @@ void assault_objective_decrease_use() { void assault_setenemytoobjective() { - local entity objective; + entity objective; for(objective = world; (objective = find(objective, targetname, self.target)); ) { if(objective.classname == "target_objective") { if(self.enemy == world) @@ -148,18 +157,26 @@ void target_objective_decrease_activate() for(ent = world; (ent = find(ent, target, self.targetname)); ) { if(ent.assault_sprite != world) + { WaypointSprite_Disown(ent.assault_sprite, waypointsprite_deadlifetime); + if(ent.classname == "func_assault_destructible") + ent.sprite = world; + } - spr = WaypointSprite_SpawnFixed("<placeholder>", 0.5 * (ent.absmin + ent.absmax), ent, assault_sprite); + spr = WaypointSprite_SpawnFixed("<placeholder>", 0.5 * (ent.absmin + ent.absmax), ent, assault_sprite, RADARICON_OBJECTIVE, '1 0.5 0'); spr.assault_decreaser = self; spr.waypointsprite_visible_for_player = assault_decreaser_sprite_visible; spr.classname = "sprite_waypoint"; WaypointSprite_UpdateRule(spr, assault_attacker_team, SPRITERULE_TEAMPLAY); if(ent.classname == "func_assault_destructible") + { WaypointSprite_UpdateSprites(spr, "as-defend", "as-destroy", "as-destroy"); + WaypointSprite_UpdateMaxHealth(spr, ent.max_health); + WaypointSprite_UpdateHealth(spr, ent.health); + ent.sprite = spr; + } else WaypointSprite_UpdateSprites(spr, "as-defend", "as-push", "as-push"); - WaypointSprite_UpdateTeamRadar(spr, RADARICON_OBJECTIVE, '1 0.5 0'); } } @@ -198,6 +215,7 @@ void spawnfunc_func_assault_destructible() { return; } self.spawnflags = 3; + self.classname = "func_assault_destructible"; if(assault_attacker_team == COLOR_TEAM1) { self.team = COLOR_TEAM2; } else { @@ -262,7 +280,7 @@ void assault_roundstart_use() { activator = self; SUB_UseTargets(); - + #ifdef TTURRETS_ENABLED entity ent, oldself; @@ -304,9 +322,31 @@ void spawnfunc_target_assault_roundstart() { // trigger new round // reset objectives, toggle spawnpoints, reset triggers, ... -void assault_new_round() { +void vehicles_clearrturn(); +void vehicles_spawn(); +void assault_new_round() +{ + entity oldself; //bprint("ASSAULT: new round\n"); + oldself = self; + // Eject players from vehicles + FOR_EACH_PLAYER(self) + { + if(self.vehicle) + vehicles_exit(VHEF_RELESE); + } + + self = findchainflags(vehicle_flags, VHF_ISVEHICLE); + while(self) + { + vehicles_clearrturn(); + vehicles_spawn(); + self = self.chain; + } + + self = oldself; + // up round counter self.winning = self.winning + 1; @@ -318,7 +358,7 @@ void assault_new_round() { } - local entity ent; + entity ent; for(ent = world; (ent = nextent(ent)); ) { if(clienttype(ent) == CLIENTTYPE_NOTACLIENT) @@ -332,5 +372,5 @@ void assault_new_round() { // reset the level with a countdown cvar_set("timelimit", ftos(ceil(time - game_starttime) / 60)); - ReadyRestartForce(); // sets game_starttime + ReadyRestart_force(); // sets game_starttime } diff --git a/qcsrc/server/attic/monsters/ai.qc b/qcsrc/server/attic/monsters/ai.qc new file mode 100644 index 0000000000..59989e7a8c --- /dev/null +++ b/qcsrc/server/attic/monsters/ai.qc @@ -0,0 +1,891 @@ +void() movetarget_f; +void() t_movetarget; +void() FoundTarget; + +float MONSTER_WANDER = 64; // disable wandering around +float MONSTER_APPEAR = 128; // spawn invisible, and appear when triggered + +.float ismonster; +.float monsterawaitingteleport; // avoid awaking monsters in teleport rooms + +// when a monster becomes angry at a player, that monster will be used +// as the sight target the next frame so that monsters near that one +// will wake up even if they wouldn't have noticed the player +// +entity sight_entity; +float sight_entity_time; + +/* + +.enemy +Will be world if not currently angry at anyone. + +.movetarget +The next path spot to walk toward. If .enemy, ignore .movetarget. +When an enemy is killed, the monster will try to return to it's path. + +.huntt_ime +Set to time + something when the player is in sight, but movement straight for +him is blocked. This causes the monster to use wall following code for +movement direction instead of sighting on the player. + +.ideal_yaw +A yaw angle of the intended direction, which will be turned towards at up +to 45 deg / state. If the enemy is in view and hunt_time is not active, +this will be the exact line towards the enemy. + +.pausetime +A monster will leave it's stand state and head towards it's .movetarget when +time > .pausetime. + +walkmove(angle, speed) primitive is all or nothing +*/ + + +// +// globals +// +//float current_yaw; + +float(float v) anglemod = +{ + v = v - 360 * floor(v / 360); + return v; +} + +/* +============================================================================== + +MOVETARGET CODE + +The angle of the movetarget effects standing and bowing direction, but has no effect on movement, which allways heads to the next target. + +targetname +must be present. The name of this movetarget. + +target +the next spot to move to. If not present, stop here for good. + +pausetime +The number of seconds to spend standing or bowing for path_stand or path_bow + +============================================================================== +*/ + + +void() movetarget_f = +{ + if (!self.targetname) + objerror ("monster_movetarget: no targetname"); + + self.solid = SOLID_TRIGGER; + self.touch = t_movetarget; + setsize (self, '-8 -8 -8', '8 8 8'); +} + +/*QUAKED path_corner (0.5 0.3 0) (-8 -8 -8) (8 8 8) +Monsters will continue walking towards the next target corner. +*/ +void() path_corner = +{ + movetarget_f (); +} + +/* +============= +t_movetarget + +Something has bumped into a movetarget. If it is a monster +moving towards it, change the next destination and continue. +============== +*/ +void() t_movetarget = +{ + entity temp; + + if (other.health < 1) + return; + if (other.movetarget != self) + return; + + if (other.enemy) + return; // fighting, not following a path + + temp = self; + self = other; + other = temp; + + /* PLEASE FIX THE SOUND CHANNEL BEFORE ACTIVATING THIS + if (self.classname == "monster_ogre") + sound (self, CHAN_VOICE, "ogre/ogdrag.wav", 1, ATTN_IDLE);// play chainsaw drag sound + */ + +//dprint ("t_movetarget\n"); + self.goalentity = self.movetarget = find (world, targetname, other.target); + self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin); + if (!self.movetarget) + { + self.pausetime = time + 999999; + self.th_stand (); + return; + } +} + +void() monster_wanderpaththink = +{ + vector v, v1; + float b, c; + self.nextthink = time + random() * 10 + 1; + if (self.owner.health < 1) // dead, also handled in death code + { + self.owner.movetarget = world; + remove(self); + return; + } + b = -1; + c = 10; + while (c > 0) + { + c = c - 1; + v = randomvec(); + traceline(self.owner.origin, v * 1024 + self.owner.origin, FALSE, self); + v = trace_endpos - (normalize(v) * 16) - self.owner.origin; + if (vlen(v) > b) + { + b = vlen(v); + v1 = v; + } + } + setorigin(self, v1 + self.owner.origin); + self.owner.ideal_yaw = vectoyaw(self.origin - self.owner.origin); +} + +void() monster_wanderpathtouch = +{ + if (other.health < 1) + return; + if (other.movetarget != self) + return; + + if (other.enemy) + return; // fighting, not following a path + + /* PLEASE FIX THE SOUND CHANNEL BEFORE ACTIVATING THIS + if (other.classname == "monster_ogre") + sound (other, CHAN_VOICE, "ogre/ogdrag.wav", 1, ATTN_IDLE);// play chainsaw drag sound + */ + monster_wanderpaththink(); +} + +void() monster_spawnwanderpath = +{ + newmis = spawn(); + newmis.classname = "monster_wanderpath"; + newmis.solid = SOLID_TRIGGER; + newmis.touch = monster_wanderpathtouch; + setsize (newmis, '-8 -8 -8', '8 8 8'); + newmis.think = monster_wanderpaththink; + newmis.nextthink = time + random() * 10 + 1; + newmis.owner = self; + self.goalentity = self.movetarget = newmis; +} + +void() monster_checkbossflag = +{ +//#NO AUTOCVARS START +#if 0 + float healthboost; + float r; + + // monsterbosses cvar or spawnflag 64 causes a monster to be a miniboss + if ((self.spawnflags & 64) || (random() * 100 < cvar("monsterbosspercent"))) + { + self.radsuit_finished = time + 1000000000; + r = random() * 4; + if (r < 2) + { + self.super_damage_finished = time + 1000000000; + healthboost = 30 + self.health * 0.5; + self.effects = self.effects | (EF_FULLBRIGHT | EF_BLUE); + } + if (r >= 1) + { + healthboost = 30 + self.health * bound(0.5, skill * 0.5, 1.5); + self.effects = self.effects | (EF_FULLBRIGHT | EF_RED); + self.healthregen = max(self.healthregen, min(skill * 10, 30)); + } + self.health = self.health + healthboost; + self.max_health = self.health; + self.bodyhealth = self.bodyhealth * 2 + healthboost; + do + { + self.colormod_x = random(); + self.colormod_y = random(); + self.colormod_z = random(); + self.colormod = normalize(self.colormod); + } + while (self.colormod_x > 0.6 && self.colormod_y > 0.6 && self.colormod_z > 0.6); + } +#endif +//#NO AUTOCVARS END +} + + +//============================================================================ + +/* +============= +range + +returns the range catagorization of an entity reletive to self +0 melee range, will become hostile even if back is turned +1 visibility and infront, or visibility and show hostile +2 infront and show hostile +3 only triggered by damage +============= +*/ +float(entity targ) range = +{ + float r; + r = vlen ((self.origin + self.view_ofs) - (targ.origin + targ.view_ofs)); + if (r < 120) + return RANGE_MELEE; + if (r < 500) + return RANGE_NEAR; + if (r < 2000) // increased from 1000 for DP + return RANGE_MID; + return RANGE_FAR; +} + +/* +============= +visible + +returns 1 if the entity is visible to self, even if not infront () +============= +*/ +float (entity targ) visible = +{ + if (vlen(targ.origin - self.origin) > 5000) // long traces are slow + return FALSE; + + traceline ((self.origin + self.view_ofs), (targ.origin + targ.view_ofs), TRUE, self); // see through other monsters + + if (trace_inopen && trace_inwater) + return FALSE; // sight line crossed contents + + if (trace_fraction == 1) + return TRUE; + return FALSE; +} + + +/* +============= +infront + +returns 1 if the entity is in front (in sight) of self +============= +*/ +float(entity targ) infront = +{ + float dot; + + makevectors (self.angles); + dot = normalize (targ.origin - self.origin) * v_forward; + + return (dot > 0.3); +} +// returns 0 if not infront, or the dotproduct if infront +float(vector dir, entity targ) infront2 = +{ + float dot; + + dir = normalize(dir); + dot = normalize (targ.origin - self.origin) * dir; + + if (dot >= 0.3) return dot; // infront + return 0; +} + + +//============================================================================ + +/* +=========== +ChangeYaw + +Turns towards self.ideal_yaw at self.yaw_speed +Sets the global variable current_yaw +Called every 0.1 sec by monsters +============ +*/ +/* + +void() ChangeYaw = +{ + float ideal, move; + +//current_yaw = self.ideal_yaw; +// mod down the current angle + current_yaw = anglemod( self.angles_y ); + ideal = self.ideal_yaw; + + if (current_yaw == ideal) + return; + + move = ideal - current_yaw; + if (ideal > current_yaw) + { + if (move > 180) + move = move - 360; + } + else + { + if (move < -180) + move = move + 360; + } + + if (move > 0) + { + if (move > self.yaw_speed) + move = self.yaw_speed; + } + else + { + if (move < 0-self.yaw_speed ) + move = 0-self.yaw_speed; + } + + current_yaw = anglemod (current_yaw + move); + + self.angles_y = current_yaw; +} + +*/ + + +//============================================================================ + +void() HuntTarget = +{ + self.goalentity = self.enemy; + self.think = self.th_run; + self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin); + self.nextthink = time + 0.1; + SUB_AttackFinished (1); // wait a while before first attack +} + +.void() th_sightsound; + +void() SightSound = +{ + if (self.health < 1) + return; + // skill 5 does not play sight sounds, instead you only hear the appear sound as they are about to attack + if (skill >= 5) + if (self.classname != "monster_hellfish") + return; + + if (self.th_sightsound) + self.th_sightsound(); +} + +void() FoundTarget = +{ + if (self.health < 1 || !self.th_run) + return; + if (self.enemy.health < 1 || !self.enemy.takedamage) + return; + if (self.enemy.classname == "player") + { + // let other monsters see this monster for a while + sight_entity = self; + sight_entity_time = time + 0.1; + } + + self.show_hostile = time + 1; // wake up other monsters + + SightSound (); + HuntTarget (); +} + +/* +//float checkplayertime; +entity lastcheckplayer; +entity havocbot_list; + + +entity() checkplayer = +{ + entity check; + float worldcount; + // we can just fallback on checkclient if there are no bots + if (!havocbot_list) + return checkclient(); +*/ + /* + if (time < checkplayertime) + { + traceline(self.origin + self.view_ofs, lastcheckplayer.origin + lastcheckplayer.view_ofs, TRUE, self); + if (trace_fraction == 1) + return lastcheckplayer; + if (trace_ent == lastcheckplayer) + return lastcheckplayer; + } + checkplayertime = time + 0.1; + */ +/* + check = lastcheckplayer; + worldcount = 0; + c = 0; + do + { + c = c + 1; + check = findfloat(check, havocattack, TRUE); + if (check.classname == "player" || check.classname == "turretbase") + { + traceline(self.origin + self.view_ofs, check.origin + check.view_ofs, TRUE, self); + if (trace_fraction == 1) + return lastcheckplayer = check; + if (trace_ent == check) + return lastcheckplayer = check; + } + else if (check == world) + { + worldcount = worldcount + 1; + if (worldcount >= 2) + return lastcheckplayer = check; + } + } + while(check != lastcheckplayer && c < 100); + return world; +} +*/ + +/* +=========== +FindTarget + +Self is currently not attacking anything, so try to find a target + +Returns TRUE if an enemy was sighted + +When a player fires a missile, the point of impact becomes a fakeplayer so +that monsters that see the impact will respond as if they had seen the +player. + +To avoid spending too much time, only a single client (or fakeclient) is +checked each frame. This means multi player games will have slightly +slower noticing monsters. +============ +*/ +.float findtarget; +float() FindTarget = +{ + entity client; + float r; + + if (self.health < 1) + return FALSE; + + // if the first or second spawnflag bit is set, the monster will only + // wake up on really seeing the player, not another monster getting angry + + if (self.spawnflags & 3) + { + // don't wake up on seeing another monster getting angry + client = checkclient (); + if (!client) + return FALSE; // current check entity isn't in PVS + } + else + { + if (sight_entity_time >= time) + { + client = sight_entity; + if (client.enemy == self.enemy) + return TRUE; + } + else + { + client = checkclient (); + if (!client) + return FALSE; // current check entity isn't in PVS + } + } + + if (client == self.enemy) + return FALSE; + + if (client.flags & FL_NOTARGET) + return FALSE; + +#if 0 + if (client.items & IT_INVISIBILITY) + return FALSE; +#endif + + // on skill 5 the monsters usually ignore the player and remain ghostlike + if (skill >= 5) + if (self.classname != "monster_hellfish") + if (random() < 0.99) + return FALSE; + + r = range(client); + if (r == RANGE_FAR) + return FALSE; + + if (!visible (client)) + return FALSE; + + if (r == RANGE_NEAR) + { + if (client.show_hostile < time && !infront (client)) + return FALSE; + } + else if (r == RANGE_MID) + { + // LordHavoc: was if ( /* client.show_hostile < time || */ !infront (client)) + if (client.show_hostile < time && !infront (client)) + return FALSE; + } + + // + // got one + // + + if (client.model == "") + return FALSE; + self.enemy = client; + if (self.enemy.classname != "player" && self.enemy.classname != "turretbase") + { + self.enemy = self.enemy.enemy; + if (self.enemy.classname != "player" && self.enemy.classname != "turretbase") + { + self.enemy = world; + return FALSE; + } + } + + FoundTarget (); + + return TRUE; +} + + +//============================================================================= + +void(float dist) ai_forward = +{ + walkmove (self.angles_y, dist); +} + +void(float dist) ai_back = +{ + walkmove ( (self.angles_y+180), dist); +} + + +void(float a) monster_setalpha; + +/* +============= +ai_pain + +stagger back a bit +============= +*/ +void(float dist) ai_pain = +{ + if (self.health < 1) + return; + ai_back (dist); +} + +/* +============= +ai_painforward + +stagger back a bit +============= +*/ +void(float dist) ai_painforward = +{ + if (self.health < 1) + return; + walkmove (self.ideal_yaw, dist); +} + +/* +============= +ai_walk + +The monster is walking it's beat +============= +*/ +void(float dist) ai_walk = +{ + if (self.health < 1) + return; + + movedist = dist; + + // check for noticing a player + if (self.oldenemy.takedamage) + if (self.oldenemy.health >= 1) + { + self.enemy = self.oldenemy; + self.oldenemy = world; + FoundTarget(); + monster_setalpha(0); + return; + } + if (self.enemy) + { + if (self.enemy.takedamage) + { + if (self.enemy.health >= 1) + { + FoundTarget(); + monster_setalpha(0); + return; + } + else + self.enemy = world; + } + else + self.enemy = world; + } + + self.findtarget = TRUE; + + movetogoal (dist); + monster_setalpha(0); +} + + +/* +============= +ai_stand + +The monster is staying in one place for a while, with slight angle turns +============= +*/ +void() ai_stand = +{ + if (self.health < 1) + return; + if (self.enemy) + { + if (self.enemy.takedamage) + { + if (self.enemy.health >= 1) + { + FoundTarget(); + monster_setalpha(0); + return; + } + else + self.enemy = world; + } + else + self.enemy = world; + } + self.findtarget = TRUE; + + if (time > self.pausetime) + { + self.th_walk (); + monster_setalpha(0); + return; + } + +// change angle slightly + + monster_setalpha(0); +} + +/* +============= +ai_turn + +don't move, but turn towards ideal_yaw +============= +*/ +void() ai_turn = +{ + if (self.enemy) + { + if (self.enemy.takedamage) + { + if (self.enemy.health >= 1) + { + FoundTarget(); + monster_setalpha(0); + return; + } + else + self.enemy = world; + } + else + self.enemy = world; + } + self.findtarget = TRUE; + + ChangeYaw (); + monster_setalpha(0); +} + +//============================================================================= + +/* +============= +ChooseTurn +============= +*/ +void(vector pDestvec) ChooseTurn = +{ + vector dir, newdir; + + dir = self.origin - pDestvec; + + newdir_x = trace_plane_normal_y; + newdir_y = 0 - trace_plane_normal_x; + newdir_z = 0; + + if (dir * newdir > 0) + { + dir_x = 0 - trace_plane_normal_y; + dir_y = trace_plane_normal_x; + } + else + { + dir_x = trace_plane_normal_y; + dir_y = 0 - trace_plane_normal_x; + } + + dir_z = 0; + self.ideal_yaw = vectoyaw(dir); +} + +/* +============ +FacingIdeal + +============ +*/ +float() FacingIdeal = +{ + float delta; + + delta = anglemod(self.angles_y - self.ideal_yaw); + if (delta > 45 && delta < 315) + return FALSE; + return TRUE; +} + + +//============================================================================= + +.float() th_checkattack; + + + +/* +============= +ai_run + +The monster has an enemy it is trying to kill +============= +*/ +void(float dist) ai_run = +{ + float ofs; + if (self.health < 1) + return; + movedist = dist; + // see if the enemy is dead + if (self.enemy.health < 1 || self.enemy.takedamage == DAMAGE_NO) + { + self.enemy = world; + // FIXME: look all around for other targets + if (self.oldenemy.health >= 1 && self.oldenemy.takedamage) + { + self.enemy = self.oldenemy; + self.oldenemy = world; + HuntTarget (); + } + else + { + if (self.movetarget) + self.th_walk (); + else + self.th_stand (); + return; + } + } + + // wake up other monsters + self.show_hostile = time + 1; + + // check knowledge of enemy + enemy_range = range(self.enemy); + + self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin); + ChangeYaw (); + + if (self.attack_state == AS_MELEE) + { + //dprint ("ai_run_melee\n"); + //Turn and close until within an angle to launch a melee attack + if (FacingIdeal()) + { + self.th_melee (); + self.attack_state = AS_STRAIGHT; + } + return; + } + else if (self.attack_state == AS_MISSILE) + { + //dprint ("ai_run_missile\n"); + //Turn in place until within an angle to launch a missile attack + if (FacingIdeal()) + if (self.th_missile ()) + self.attack_state = AS_STRAIGHT; + return; + } + + if (self.th_checkattack()) + return; // beginning an attack + + if (visible(self.enemy)) + self.search_time = time + 5; + else if (coop) + { + // look for other coop players + if (self.search_time < time) + self.findtarget = TRUE; + } + + if (self.attack_state == AS_SLIDING) + { + //dprint ("ai_run_slide\n"); + //Strafe sideways, but stay at aproximately the same range + if (self.lefty) + ofs = 90; + else + ofs = -90; + + if (walkmove (self.ideal_yaw + ofs, movedist)) + return; + + self.lefty = !self.lefty; + + walkmove (self.ideal_yaw - ofs, movedist); + } + + // head straight in + movetogoal (dist); // done in C code... +} + diff --git a/qcsrc/server/attic/monsters/defs.qc b/qcsrc/server/attic/monsters/defs.qc new file mode 100644 index 0000000000..19821429c3 --- /dev/null +++ b/qcsrc/server/attic/monsters/defs.qc @@ -0,0 +1,55 @@ +.entity movetarget; +.float pausetime; + +.void() th_stand; +.void() th_walk; +.void() th_run; +.float() th_missile; // LordHavoc: changed from void() to float(), returns true if attacking +.void() th_melee; +//.void(entity attacker, float damage, float damgtype, string dethtype) th_pain; // TODO Xonotic uses event_damage +//.void() th_die; // TODO never called directly by Xonotic +.entity oldenemy; // mad at this player before taking damage +entity newmis; // launch_spike sets this after spawning it + +// range values +float RANGE_MELEE = 0; +float RANGE_NEAR = 1; +float RANGE_MID = 2; +float RANGE_FAR = 3; + +float DMG_KNIGHT_MELEE_BASE = 0; +float DMG_KNIGHT_MELEE_RANDOM1 = 3; +float DMG_KNIGHT_MELEE_RANDOM2 = 3; +float DMG_KNIGHT_MELEE_RANDOM3 = 3; + +.float show_hostile; + // set to time+0.2 whenever a client fires a + // weapon or takes damage. Used to alert + // monsters that otherwise would let the player go + +float movedist; +.float lefty; +.float search_time; +.float attack_state; + +float AS_STRAIGHT = 1; +float AS_SLIDING = 2; +float AS_MELEE = 3; +float AS_MISSILE = 4; + +float SKILL4_MINALPHA = 0.4; + +float monsterwander; +//#NO AUTOCVARS START +/* + monsterwander = cvar("monsterwander"); + // monsterwander is always on in skill 5 + if (skill >= 5) + monsterwander = TRUE; +*/ +//#NO AUTOCVARS END + +.float candrown; + +.void(vector org, float bodydamage, float armordamage, vector vel, float damgtype) bleedfunc; +void(vector org, float bodydamage, float armordamage, vector vel, float damgtype) genericbleedfunc; diff --git a/qcsrc/server/attic/monsters/fight.qc b/qcsrc/server/attic/monsters/fight.qc new file mode 100644 index 0000000000..a8fcd8e707 --- /dev/null +++ b/qcsrc/server/attic/monsters/fight.qc @@ -0,0 +1,252 @@ + +/* + +A monster is in fight mode if it thinks it can effectively attack its +enemy. + +When it decides it can't attack, it goes into hunt mode. + +*/ + +void SUB_AttackFinished (float normal) +{ + self.cnt = 0; // refire count for nightmare + if (skill < 3) + ATTACK_FINISHED(self) = time + normal; +} + +float CanDamage(entity targ, entity inflictor) +{ + if (targ.movetype == MOVETYPE_PUSH) + { + traceline(inflictor.origin, 0.5 * (targ.absmin + targ.absmax), TRUE, self); + if (trace_fraction == 1) + return TRUE; + if (trace_ent == targ) + return TRUE; + return FALSE; + } + + traceline(inflictor.origin, targ.origin, TRUE, self); + if (trace_fraction == 1) + return TRUE; + traceline(inflictor.origin, targ.origin + '15 15 0', TRUE, self); + if (trace_fraction == 1) + return TRUE; + traceline(inflictor.origin, targ.origin + '-15 -15 0', TRUE, self); + if (trace_fraction == 1) + return TRUE; + traceline(inflictor.origin, targ.origin + '-15 15 0', TRUE, self); + if (trace_fraction == 1) + return TRUE; + traceline(inflictor.origin, targ.origin + '15 -15 0', TRUE, self); + if (trace_fraction == 1) + return TRUE; + + return FALSE; +} + +float(float v) anglemod; + +void(vector dest) ChooseTurn; + +void() ai_face; + + +float enemy_range; + + +//============================================================================= + +/* +=========== +GenericCheckAttack + +The player is in view, so decide to move or launch an attack +Returns FALSE if movement should continue +============ +*/ +float() GenericCheckAttack = +{ + vector spot1, spot2; + entity targ; + float chance; + + if (self.health < 1) + return FALSE; + targ = self.enemy; + + if (vlen(targ.origin - self.origin) > 5000) // long traces are slow + return FALSE; + +// see if any entities are in the way of the shot + spot1 = self.origin + self.view_ofs; + spot2 = targ.origin + targ.view_ofs; + + traceline (spot1, spot2, FALSE, self); + + if (trace_ent != targ) + return FALSE; // don't have a clear shot + + if (trace_inopen && trace_inwater) + return FALSE; // sight line crossed contents + + if (enemy_range == RANGE_MELEE) + { // melee attack + if (self.th_melee) + { + self.th_melee (); + return TRUE; + } + } + +// missile attack + if (time < ATTACK_FINISHED(self)) + return FALSE; + + if (!self.th_missile) + return FALSE; + + if (enemy_range == RANGE_FAR) + return FALSE; + + if (enemy_range == RANGE_MELEE) + { + chance = 0.9; + ATTACK_FINISHED(self) = 0; + } + else if (enemy_range == RANGE_NEAR) + { + if (self.th_melee) + chance = 0.2; + else + chance = 0.4; + } + else if (enemy_range == RANGE_MID) + { + if (self.th_melee) + chance = 0.05; + else + chance = 0.1; + } + else + chance = 0; + + if (random () < chance) + if (self.th_missile ()) + { + SUB_AttackFinished (2*random()); + return TRUE; + } + + return FALSE; +} + + +/* +============= +ai_face + +Stay facing the enemy +============= +*/ +void() ai_face = +{ + self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin); + ChangeYaw (); +} + +/* +============= +ai_charge + +The monster is in a melee attack, so get as close as possible to .enemy +============= +*/ +float (entity targ) visible; +float(entity targ) infront; +float(entity targ) range; + +void(float d) ai_charge = +{ + if (self.health < 1) + return; + ai_face (); + movetogoal (d); // done in C code... +} + +void() ai_charge_side = +{ + if (self.health < 1) + return; + vector dtemp; + float heading; + +// aim to the left of the enemy for a flyby + + self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin); + ChangeYaw (); + + makevectors (self.angles); + dtemp = self.enemy.origin - 30*v_right; + heading = vectoyaw(dtemp - self.origin); + + walkmove(heading, 20); +} + + +/* +============= +ai_melee + +============= +*/ +void() ai_melee = +{ + vector delta; + float ldmg; + + if (self.health < 1) + return; + if (!self.enemy) + return; // removed before stroke + + delta = self.enemy.origin - self.origin; + + if (vlen(delta) > 60) + return; + + ldmg = DMG_KNIGHT_MELEE_BASE + DMG_KNIGHT_MELEE_RANDOM1 * random(); + ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM2 * random(); + ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM3 * random(); + traceline(self.origin, self.enemy.origin, FALSE, self); + + Damage (self.enemy, self, self, ldmg, self.projectiledeathtype, trace_endpos, '0 0 0'); // TODO add force to monster melee attacks? +} + + +void() ai_melee_side = +{ + vector delta; + float ldmg; + + if (self.health < 1) + return; + if (!self.enemy) + return; // removed before stroke + + ai_charge_side(); + + delta = self.enemy.origin - self.origin; + + if (vlen(delta) > 60) + return; + if (!CanDamage (self.enemy, self)) + return; + ldmg = DMG_KNIGHT_MELEE_BASE + DMG_KNIGHT_MELEE_RANDOM1 * random(); + ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM2 * random(); + ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM3 * random(); + traceline(self.origin, self.enemy.origin, FALSE, self); + Damage (self.enemy, self, self, ldmg, self.projectiledeathtype, trace_endpos, '0 0 0'); +} + diff --git a/qcsrc/server/attic/monsters/m_monsters.qc b/qcsrc/server/attic/monsters/m_monsters.qc new file mode 100644 index 0000000000..3e160d97b5 --- /dev/null +++ b/qcsrc/server/attic/monsters/m_monsters.qc @@ -0,0 +1,475 @@ +/* ALL MONSTERS SHOULD BE 1 0 0 IN COLOR */ + +// name =[framenum, nexttime, nextthink] {code} +// expands to: +// name () +// { +// self.frame=framenum; +// self.nextthink = time + nexttime; +// self.think = nextthink +// <code> +// } + +.float ismonster; + +.float modelindex2; + +/* +================ +monster_use + +Using a monster makes it angry at the current activator +LordHavoc: using a monster with the spawnflag 'Appear' makes it appear +================ +*/ +void() monster_use = +{ + if (self.enemy) + return; + if (self.health < 1) + return; + if (self.mdl) + if (self.spawnflags & MONSTER_APPEAR) + { + self.nextthink = time + 0.1; + self.spawnflags = self.spawnflags - MONSTER_APPEAR; + self.solid = SOLID_SLIDEBOX; + self.takedamage = DAMAGE_AIM; + //self.movetype = MOVETYPE_STEP; + self.model = self.mdl; + self.mdl = ""; + self.modelindex = self.modelindex2; + self.modelindex2 = 0; + //setorigin(self, self.origin + '0 0 1'); + spawn_tdeath(self.origin, self, self.origin); + return; + } + +#if 0 + if (activator.items & IT_INVISIBILITY) + return; +#endif + if (activator.flags & FL_NOTARGET) + return; + if (activator.classname != "player") + return; + + // delay reaction so if the monster is teleported, its sound is still heard + self.enemy = activator; + self.nextthink = time + 0.1; + self.think = FoundTarget; +} + +void() monster_appearsetup = +{ + if ((self.spawnflags & MONSTER_APPEAR) == 0) + return; + self.mdl = self.model; + self.modelindex2 = self.modelindex; + self.modelindex = 0; + self.solid = SOLID_NOT; + self.takedamage = DAMAGE_NO; + //self.movetype = MOVETYPE_NONE; + self.nextthink = -1; + self.model = ""; +} + +/* +================ +monster_setalpha + +Sets relative alpha of monster in skill 4 mode. +================ +*/ +void(float a) monster_setalpha = +{ + if (skill < 4 || self.classname == "monster_hellfish") + { + self.alpha = 1.0; + return; + } + + if (skill >= 5) + { + // randomly forget enemy, this makes monsters randomly return to their normal ghostlike state + if (a == 0) + if (self.enemy) + if (random() < 0.1) + self.enemy = world; + // randomly blink (playing the same alarming sound as if attacking) + if (self.enemy == world) + { + a = 0; + if (time >= 0.3) // don't blink during the init process because it might become permanent + if (random() < 0.005) + { + // blink for an instant, this causes the appear sound, alarming the player as if under attack + /* PLEASE FIX THE SOUND CHANNEL BEFORE ACTIVATING THIS + sound(self, CHAN_AUTO, "wizard/wsight.wav", 1, ATTN_NORM); + */ + a = 1; + } + } + // if ghosted, become non-solid and immune to damage + if (a <= 0 || self.enemy == world) + { + self.solid = SOLID_NOT; + self.takedamage = DAMAGE_NO; + } + else + { + // if unghosting, make sure we have an enemy, otherwise stay ghosted (even if blinking) so we can't be shot while blinking + /* PLEASE FIX THE SOUND CHANNEL BEFORE ACTIVATING THIS + if (self.solid != SOLID_SLIDEBOX) + sound(self, CHAN_AUTO, "wizard/wsight.wav", 1, ATTN_NORM); + */ + self.solid = SOLID_SLIDEBOX; + self.takedamage = DAMAGE_AIM; + } + } + self.alpha = SKILL4_MINALPHA + (1 - SKILL4_MINALPHA) * bound(0, a, 1); +} + +/* +================ +monster_death_use + +When a mosnter dies, it fires all of its targets with the current +enemy as activator. +================ +*/ +void() monster_death_use = +{ +// fall to ground + if (self.flags & FL_FLY) + self.flags = self.flags - FL_FLY; + if (self.flags & FL_SWIM) + self.flags = self.flags - FL_SWIM; + + if (!self.target) + return; + + activator = self.enemy; + SUB_UseTargets (); +} + + +void() monsterinwall = +{ + entity e; + if (!autocvar_developer) + return; + // this is handy for level designers, + // puts a spikey ball where the error is... + e = spawn(); + setorigin(e, self.origin); + setmodel (e, "models/ebomb.mdl"); + e.movetype = MOVETYPE_NONE; + e.solid = SOLID_NOT; + e.think = SUB_Null; + e.nextthink = -1; + e.scale = 16; +} + +//============================================================================ + +void() walkmonster_start_go = +{ + self.origin_z = self.origin_z + 1; // raise off floor a bit + + tracebox(self.origin, self.mins, self.maxs, self.origin, TRUE, self); + if (trace_startsolid) + { + dprint("walkmonster in wall at: "); + dprint(vtos(self.origin)); + dprint("\n"); + monsterinwall(); + droptofloor(); + } + else + { + droptofloor(); + if (!walkmove(0,0)) + { + dprint("walkmonster in wall at: "); + dprint(vtos(self.origin)); + dprint("\n"); + monsterinwall(); + } + } + + //self.cantrigger = TRUE; + + self.takedamage = DAMAGE_AIM; + + self.ideal_yaw = self.angles * '0 1 0'; + if (!self.yaw_speed) + self.yaw_speed = 20; + self.view_ofs = '0 0 25'; + self.use = monster_use; + + self.flags = self.flags | FL_MONSTER; + + if (monsterwander) + self.spawnflags = self.spawnflags | MONSTER_WANDER; + + if (self.target) + { + self.goalentity = self.movetarget = find(world, targetname, self.target); + self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin); + if (!self.movetarget) + { + dprint("Monster can't find target at "); + dprint(vtos(self.origin)); + dprint("\n"); + } + // this used to be an objerror + if (self.movetarget.classname == "path_corner") + self.th_walk (); + else + { + if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp")) + { + monster_spawnwanderpath(); + self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin); + self.th_walk (); + } + else + { + self.pausetime = 99999999; + self.th_stand (); + } + } + } + else + { + if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp")) + { + monster_spawnwanderpath(); + self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin); + self.th_walk (); + } + else + { + self.pausetime = 99999999; + self.th_stand (); + } + } + +// spread think times so they don't all happen at same time + self.nextthink = self.nextthink + random()*0.5 + 0.1; + self.iscreature = TRUE; + self.damagedbycontents = TRUE; + + force_retouch = 2; // mainly to detect teleports + + monster_appearsetup(); +} + + +void() walkmonster_start = +{ + self.candrown = 1; // this is turned off by some monsters like zombies + // delay drop to floor to make sure all doors have been spawned + // spread think times so they don't all happen at same time + self.nextthink = time + random()*0.5 + 0.3; + self.think = walkmonster_start_go; + total_monsters = total_monsters + 1; + self.bot_attack = TRUE; + self.frags = 2; // actually just used to get havocbots to attack it... + self.bleedfunc = genericbleedfunc; + self.ismonster = TRUE; + + monster_setalpha (0); +} + + + +void() flymonster_start_go = +{ + self.takedamage = DAMAGE_AIM; + + self.ideal_yaw = self.angles * '0 1 0'; + if (!self.yaw_speed) + self.yaw_speed = 10; + self.view_ofs = '0 0 25'; + self.use = monster_use; + + self.flags = self.flags | FL_FLY; + self.flags = self.flags | FL_MONSTER; + + if (!walkmove(0,0)) + { + dprint("flymonster in wall at: "); + dprint(vtos(self.origin)); + dprint("\n"); + monsterinwall(); + } + + //self.cantrigger = TRUE; + + if (monsterwander) + self.spawnflags = self.spawnflags | MONSTER_WANDER; + + if (self.target) + { + self.goalentity = self.movetarget = find(world, targetname, self.target); + if (!self.movetarget) + { + dprint("Monster can't find target at "); + dprint(vtos(self.origin)); + dprint("\n"); + } + // this used to be an objerror + if (self.movetarget.classname == "path_corner") + self.th_walk (); + else + { + if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp")) + { + monster_spawnwanderpath(); + self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin); + self.th_walk (); + } + else + { + self.pausetime = 99999999; + self.th_stand (); + } + } + } + else + { + if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp")) + { + monster_spawnwanderpath(); + self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin); + self.th_walk (); + } + else + { + self.pausetime = 99999999; + self.th_stand (); + } + } + self.iscreature = TRUE; + self.damagedbycontents = TRUE; + + force_retouch = 2; // mainly to detect teleports + + monster_appearsetup(); +} + +void() flymonster_start = +{ + self.candrown = 1; + // spread think times so they don't all happen at same time + self.nextthink = time + random()*0.5 + 0.1; + self.think = flymonster_start_go; + total_monsters = total_monsters + 1; + self.bot_attack = TRUE; + self.frags = 2; // actually just used to get havocbots to attack it... + self.bleedfunc = genericbleedfunc; + self.ismonster = TRUE; + + monster_setalpha (0); +} + + +void() swimmonster_start_go = +{ + if (deathmatch) + { + remove(self); + return; + } + + //self.cantrigger = TRUE; + + self.takedamage = DAMAGE_AIM; + + self.ideal_yaw = self.angles * '0 1 0'; + if (!self.yaw_speed) + self.yaw_speed = 10; + self.view_ofs = '0 0 10'; + self.use = monster_use; + + self.flags = self.flags | FL_SWIM; + self.flags = self.flags | FL_MONSTER; + + if (monsterwander) + self.spawnflags = self.spawnflags | MONSTER_WANDER; + + if (self.target) + { + self.goalentity = self.movetarget = find(world, targetname, self.target); + if (!self.movetarget) + { + dprint("Monster can't find target at "); + dprint(vtos(self.origin)); + dprint("\n"); + } + // this used to be an objerror + if (self.movetarget.classname == "path_corner") + self.th_walk (); + else + { + if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp")) + { + monster_spawnwanderpath(); + self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin); + self.th_walk (); + } + else + { + self.pausetime = 99999999; + self.th_stand (); + } + } + } + else + { + if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp")) + { + monster_spawnwanderpath(); + self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin); + self.th_walk (); + } + else + { + self.pausetime = 99999999; + self.th_stand (); + } + } + self.iscreature = TRUE; + self.damagedbycontents = TRUE; + + force_retouch = 2; // mainly to detect teleports + + monster_appearsetup(); +} + +void() swimmonster_start = +{ + // spread think times so they don't all happen at same time + self.candrown = 0; + self.nextthink = time + random()*0.5 + 0.1; + self.think = swimmonster_start_go; + total_monsters = total_monsters + 1; + self.bot_attack = TRUE; + self.frags = 2; // actually just used to get havocbots to attack it... + self.bleedfunc = genericbleedfunc; + self.ismonster = TRUE; + + monster_setalpha(0); +} + +void(vector org, float bodydamage, float armordamage, vector force, float damgtype) genericbleedfunc = +{ + vector v; + v = '0 0 0' - force * 0.05; + if (armordamage > 0) + te_spark(org, v, armordamage * 3); + if (bodydamage > 0) + te_blood(org, v, bodydamage); +} diff --git a/qcsrc/server/attic/monsters/monster_zombie.qc b/qcsrc/server/attic/monsters/monster_zombie.qc new file mode 100644 index 0000000000..c95c2eaf2f --- /dev/null +++ b/qcsrc/server/attic/monsters/monster_zombie.qc @@ -0,0 +1,575 @@ +//#define MONSTES_ENABLED +#ifdef MONSTES_ENABLED + +float autocvar_g_monster_zombie_attack_run_damage; +float autocvar_g_monster_zombie_attack_run_delay; +float autocvar_g_monster_zombie_attack_run_force; +float autocvar_g_monster_zombie_attack_run_hitrange; +float autocvar_g_monster_zombie_attack_run_range; +float autocvar_g_monster_zombie_attack_stand_damage; +float autocvar_g_monster_zombie_attack_stand_delay; +float autocvar_g_monster_zombie_attack_stand_force; +float autocvar_g_monster_zombie_attack_stand_range; +float autocvar_g_monster_zombie_health; +float autocvar_g_monster_zombie_idle_timer_max; +float autocvar_g_monster_zombie_idle_timer_min; +float autocvar_g_monster_zombie_movespeed; +float autocvar_g_monster_zombie_respawntime; +float autocvar_g_monster_zombie_stopspeed; +float autocvar_g_monster_zombie_targetrange; +float autocvar_g_monster_zombie_turnspeed; +float autocvar_g_monsters; + + +#define zombie_anim_attackleap 0 +#define zombie_anim_attackrun1 1 +#define zombie_anim_attackrun2 2 +#define zombie_anim_attackrun3 3 +#define zombie_anim_attackstanding1 4 +#define zombie_anim_attackstanding2 5 +#define zombie_anim_attackstanding3 6 +#define zombie_anim_blockend 7 +#define zombie_anim_blockstart 8 +#define zombie_anim_deathback1 9 +#define zombie_anim_deathback2 10 +#define zombie_anim_deathback3 11 +#define zombie_anim_deathfront1 12 +#define zombie_anim_deathfront2 13 +#define zombie_anim_deathfront3 14 +#define zombie_anim_deathleft1 15 +#define zombie_anim_deathleft2 16 +#define zombie_anim_deathright1 17 +#define zombie_anim_deathright2 18 +#define zombie_anim_idle 19 +#define zombie_anim_painback1 20 +#define zombie_anim_painback2 21 +#define zombie_anim_painfront1 22 +#define zombie_anim_painfront2 23 +#define zombie_anim_runbackwards 24 +#define zombie_anim_runbackwardsleft 25 +#define zombie_anim_runbackwardsright 26 +#define zombie_anim_runforward 27 +#define zombie_anim_runforwardleft 28 +#define zombie_anim_runforwardright 29 +#define zombie_anim_spawn 30 + +#define ZOMBIE_MIN '-18 -18 -25' +#define ZOMBIE_MAX '18 18 47' + +#define ZV_IDLE 10 + +#define ZV_PATH 100 +#define ZV_HUNT 200 + +#define ZV_ATTACK_FIND 10 +#define ZV_ATTACK_RUN 20 +#define ZV_ATTACK_STAND 30 + +#define ZV_PATH2 10000 + +//.entity verbs_idle; +//.entity verbs_attack; +//.entity verbs_move; + +//.float state_timeout; +//.void() monster_state; +#define MONSTERFLAG_NORESPAWN 2 + +void zombie_spawn(); + +float zombie_scoretarget(entity trg) +{ + float tmp; + vector ang1; + + if (trg.takedamage == DAMAGE_AIM) + if not (trg.flags & FL_NOTARGET) + if (trg.deadflag == DEAD_NO) + if (trg.team != self.team) + { + if((self.origin_z - trg.origin_z) < 128) + { + ang1 = normalize(self.origin - trg.origin); + tmp = vlen(ang1 - v_forward); + if(tmp > 1.5) + { + traceline(self.origin + '0 0 47',trg.origin + '0 0 32',MOVE_NORMAL,self); + if(trace_ent != trg) + return 0; + + return (autocvar_g_monster_zombie_targetrange - vlen(self.origin - trg.origin)) * tmp; + } + else if(self.enemy == trg) + return (autocvar_g_monster_zombie_targetrange - vlen(self.origin - trg.origin)) * tmp; + } + } + + return 0; +} + +void zombie_corpse_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) +{ + //dprint("zombie_corpse_damage\n"); + Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker); + + self.health -= damage; + + if(self.health < 0) + { + Violence_GibSplash(self, 1, 1, attacker); + remove(self); + } +} + +void zombie_die(vector dir) +{ + vector v; + float f; + + entity dummy; + + dummy = spawn(); + setmodel(dummy,"models/monsters/zombie.dpm"); + setorigin(dummy, self.origin); + dummy.velocity = self.velocity; + dummy.movetype = MOVETYPE_BOUNCE; + dummy.think = SUB_Remove; + dummy.nextthink = time + 3; + dummy.health = 50; + dummy.takedamage = DAMAGE_YES; + dummy.event_damage = zombie_corpse_damage; + dummy.solid = SOLID_CORPSE; + setsize(dummy,self.mins,self.maxs); + + SUB_SetFade(dummy,time + 5,2); + + + v = normalize(self.origin - dir); + f = vlen(v_forward - v) - 1; + if(f > 0.5) + dummy.frame = zombie_anim_deathfront1 + rint(random() * 2); + else if(f < 0.5) + dummy.frame = zombie_anim_deathback1 + rint(random() * 2); + else + { + f = vlen(v_right - v) - 1; + if(f > 0.5) + dummy.frame = zombie_anim_deathright1 + rint(random() * 2); + else if(f < 0.5) + dummy.frame = zombie_anim_deathleft1 + rint(random() * 2); + } + + + if(self.spawnflags & MONSTERFLAG_NORESPAWN) + { + self.think = SUB_Remove; + self.nextthink = time; + return; + } + + setmodel(self,""); + self.solid = SOLID_NOT; + self.takedamage = DAMAGE_NO; + self.event_damage = SUB_Null; + self.enemy = world; + self.think = zombie_spawn; + self.nextthink = time + autocvar_g_monster_zombie_respawntime; + self.pain_finished = self.nextthink; +} + +void zombie_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) +{ + + vector v; + float f; + + v = normalize(self.origin - hitloc); + f = vlen(v_forward - v) - 1; + + + self.health -= damage; + self.velocity = self.velocity + force; + if(self.health <= 0) + { + zombie_die(hitloc); + return; + } + + Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker); + + if (damage > 50) + Violence_GibSplash_At(hitloc, force * -0.1, 3, 1, self, attacker); + if (damage > 100) + Violence_GibSplash_At(hitloc, force * -0.2, 3, 1, self, attacker); + + if (time > self.pain_finished) + { + if(f < 0.5) + { + if(random() < 0.5) + self.frame = zombie_anim_painback1; + else + self.frame = zombie_anim_painback2; + } + else + { + if(random() < 0.5) + self.frame = zombie_anim_painfront1; + else + self.frame = zombie_anim_painfront2; + } + + self.pain_finished = time + 0.36; + } +} + +.vector bvec; +.float bvec_time; + +void zombie_move() +{ + vector real_angle; + float vz, tdiff, tspeed; + + tdiff = time - self.zoomstate; + tspeed = tdiff * autocvar_g_monster_zombie_turnspeed; + vz = self.velocity_z; + self.zoomstate = time; + + if(self.bvec_time < time) + { + self.bvec_time = time + 0.2; + self.bvec = steerlib_beamsteer(steerlib_attract2(self.moveto,0.5,500,0.95),512,32,34,64); + } + + if(self.enemy) + self.moveto = self.enemy.origin; + else + self.moveto = self.origin + v_forward; + + self.steerto = normalize(steerlib_attract2(self.moveto,0.5,500,0.95) + self.bvec); + + self.angles_y = safeangle(self.angles_y); + real_angle = vectoangles(self.steerto) - self.angles; + self.angles_y += bound(-10, real_angle_y, 10); + + if(vlen(self.origin - self.moveto) > 64) + { + movelib_move_simple(v_forward ,autocvar_g_monster_zombie_movespeed,0.6); + if(time > self.pain_finished) + if(self.attack_finished_single < time) + self.frame = zombie_anim_runforward; + } + else + { + movelib_beak_simple(autocvar_g_monster_zombie_stopspeed); + if(time > self.pain_finished) + if(self.attack_finished_single < time) + self.frame = zombie_anim_idle; + } + + self.velocity_z = vz; + self.steerto = self.origin; +} + +float zombie_verb_idle_roam(float eval) +{ + switch (eval) + { + case VCM_EVAL: + + if(self.enemy) + return VS_CALL_NO; + + return verb.verb_static_value; + + case VCM_DO: + + self.moveto = v_forward * 128; + self.steerto = v_forward; //steerlib_beamsteer(v_forward,512,32,34,64); + + return VS_CALL_YES_DOING; + } + + return VS_CALL_YES_DONE; +} + +float zombie_verb_idle_stand(float eval) +{ + switch (eval) + { + case VCM_EVAL: + + if(self.enemy) + return VS_CALL_NO; + + return verb.verb_static_value; + + case VCM_DO: + + self.moveto = self.origin; + self.frame = zombie_anim_idle; + self.velocity = '0 0 0'; + + return VS_CALL_YES_DOING; + } + + return VS_CALL_YES_DONE; +} + +float zombie_verb_idle(float eval) +{ + switch (eval) + { + case VCM_EVAL: + + if(self.enemy) + return VS_CALL_NO; + + return verb.verb_static_value; + + case VCM_DO: + float t; + + t = autocvar_g_monster_zombie_idle_timer_max - autocvar_g_monster_zombie_idle_timer_min; + t = autocvar_g_monster_zombie_idle_timer_min + (random() * t); + + if(random() < 0.5) + verbstack_push(self.verbs_idle, zombie_verb_idle_roam, ZV_IDLE + 1, t, self); + else + verbstack_push(self.verbs_idle, zombie_verb_idle_stand, ZV_IDLE + 1, 0.1, self); + + return VS_CALL_YES_DOING; + } + + return VS_CALL_YES_DONE; +} + +float zombie_verb_attack_findtarget(float eval) +{ + switch (eval) + { + case VCM_EVAL: + if(self.enemy) + return VS_CALL_NO; + + return verb.verb_static_value; + + case VCM_DO: + + entity trg, best_trg; + float trg_score, best_trg_score; + + trg = findradius(self.origin,autocvar_g_monster_zombie_targetrange); + while(trg) + { + trg_score = zombie_scoretarget(trg); + if(trg_score > best_trg_score) + { + best_trg = trg; + best_trg_score = trg_score; + } + + trg = trg.chain; + } + + if(best_trg) + { + self.enemy = best_trg; + dprint("Selected: ",best_trg.netname, " as target.\n"); + } + + return VS_CALL_YES_DOING; + } + + return VS_CALL_YES_DONE; +} + +void zombie_runattack_damage() +{ + entity oldself; + oldself = self; + self = self.owner; + + if(vlen(self.origin - self.enemy.origin) > autocvar_g_monster_zombie_attack_run_hitrange) + return; + + if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6) + return; + + Damage(self.enemy, self, self, autocvar_g_monster_zombie_attack_run_damage, DEATH_TURRET, self.enemy.origin, normalize(self.enemy.origin - self.origin) * autocvar_g_monster_zombie_attack_run_force); + + self = oldself; + self.think = SUB_Remove; + self.nextthink = time; +} + +float zombie_verb_attack_run(float eval) +{ + switch (eval) + { + case VCM_EVAL: + if not (self.enemy) + return VS_CALL_NO; + + if(self.attack_finished_single > time) + return VS_CALL_NO; + + if(vlen(self.origin - self.enemy.origin) > autocvar_g_monster_zombie_attack_run_range) + return VS_CALL_NO; + + if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6) + return VS_CALL_NO; + + return verb.verb_static_value; + + case VCM_DO: + entity pain; + pain = spawn(); + pain.owner = self; + pain.think = zombie_runattack_damage; + pain.nextthink = time + autocvar_g_monster_zombie_attack_run_delay; + + self.attack_finished_single = time + 0.7; + self.frame = zombie_anim_attackrun1 + rint(random() * 2); + + return VS_CALL_YES_DOING; + } + + return VS_CALL_YES_DONE; +} + +void zombie_standattack_damage() +{ + //entity oldself; + //oldself = self; + //self = self.owner; + + setorigin(self,self.owner.origin + v_forward * 32); + RadiusDamage(self, self.owner, autocvar_g_monster_zombie_attack_stand_damage,autocvar_g_monster_zombie_attack_stand_damage,16,self, autocvar_g_monster_zombie_attack_stand_force,DEATH_TURRET,world); + //float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity ignore, float forceintensity, float deathtype, entity directhitentity) + + + //self = oldself; + self.think = SUB_Remove; + self.nextthink = time; +} + +float zombie_verb_attack_stand(float eval) +{ + switch (eval) + { + case VCM_EVAL: + if not (self.enemy) + return VS_CALL_NO; + + if(self.attack_finished_single > time) + return VS_CALL_NO; + + if(vlen(self.origin - self.enemy.origin) > autocvar_g_monster_zombie_attack_stand_range) + return VS_CALL_NO; + + if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.8) + return VS_CALL_NO; + + return verb.verb_static_value; + + case VCM_DO: + entity pain; + pain = spawn(); + pain.owner = self; + pain.think = zombie_runattack_damage; + pain.nextthink = time + autocvar_g_monster_zombie_attack_stand_delay; + + self.attack_finished_single = time + 0.7; + self.frame = zombie_anim_attackstanding1 + rint(random() * 1); + dprint("frame:",ftos(self.frame),"\n"); + + return VS_CALL_YES_DOING; + } + + return VS_CALL_YES_DONE; +} + +void zombie_think() +{ + self.angles_x *= -1; + makevectors(self.angles); + self.angles_x *= -1; + + if (zombie_scoretarget(self.enemy) == 0) + self.enemy = world; + + verbstack_pop(self.verbs_attack); + //verbstack_pop(self.verbs_move); + + if not (self.enemy) + verbstack_pop(self.verbs_idle); + + zombie_move(); + + if(self.enemy) + self.nextthink = time; + else + self.nextthink = time + 0.2; +} + +void zombie_spawn() +{ + setmodel(self,"models/monsters/zombie.dpm"); + + self.solid = SOLID_BBOX; + self.takedamage = DAMAGE_AIM; + self.event_damage = zombie_damage; + self.enemy = world; + self.frame = zombie_anim_spawn; + self.think = zombie_think; + self.nextthink = time + 2.1; + self.pain_finished = self.nextthink; + self.movetype = MOVETYPE_WALK; + self.health = autocvar_g_monster_zombie_health; + self.velocity = '0 0 0'; + self.angles = self.pos2; + self.moveto = self.origin; + self.flags = FL_MONSTER; + + setorigin(self,self.pos1); + setsize(self,ZOMBIE_MIN,ZOMBIE_MAX); +} + + +void spawnfunc_monster_zombie() +{ + if not(autocvar_g_monsters) + { + remove(self); + return; + } + + precache_model("models/monsters/zombie.dpm"); + + + self.verbs_idle = spawn(); + self.verbs_attack = spawn(); + + self.verbs_idle.owner = self; + self.verbs_attack.owner = self; + + self.think = zombie_spawn; + self.nextthink = time + 2; + + traceline(self.origin + '0 0 10', self.origin - '0 0 32', MOVE_WORLDONLY, self); + + self.pos1 = trace_endpos; + self.pos2 = self.angles; + self.team = MAX_SHOT_DISTANCE -1; + + verbstack_push(self.verbs_idle, zombie_verb_idle, ZV_IDLE,0 , self); + + verbstack_push(self.verbs_attack, zombie_verb_attack_findtarget, ZV_ATTACK_FIND,0 , self); + verbstack_push(self.verbs_attack, zombie_verb_attack_run, ZV_ATTACK_RUN,0 , self); + verbstack_push(self.verbs_attack, zombie_verb_attack_stand, ZV_ATTACK_STAND,0 , self); + +} + +#endif // MONSTES_ENABLED diff --git a/qcsrc/server/attic/vehicles/bumblebee.qc b/qcsrc/server/attic/vehicles/bumblebee.qc new file mode 100644 index 0000000000..f784563712 --- /dev/null +++ b/qcsrc/server/attic/vehicles/bumblebee.qc @@ -0,0 +1,371 @@ +#ifdef SVQC +// Auto cvars +float autocvar_g_vehicle_bumblebee_speed_forward; +float autocvar_g_vehicle_bumblebee_speed_strafe; +float autocvar_g_vehicle_bumblebee_speed_up; +float autocvar_g_vehicle_bumblebee_speed_down; +float autocvar_g_vehicle_bumblebee_turnspeed; +float autocvar_g_vehicle_bumblebee_pitchspeed; +float autocvar_g_vehicle_bumblebee_pitchlimit; +float autocvar_g_vehicle_bumblebee_friction; + +float autocvar_g_vehicle_bumblebee_energy; +float autocvar_g_vehicle_bumblebee_energy_regen; +float autocvar_g_vehicle_bumblebee_energy_regen_pause; + +float autocvar_g_vehicle_bumblebee_health; +float autocvar_g_vehicle_bumblebee_health_regen; +float autocvar_g_vehicle_bumblebee_health_regen_pause; + +float autocvar_g_vehicle_bumblebee_shield; +float autocvar_g_vehicle_bumblebee_shield_regen; +float autocvar_g_vehicle_bumblebee_shield_regen_pause; + +float autocvar_g_vehicle_bumblebee_cannon_cost; +float autocvar_g_vehicle_bumblebee_cannon_damage; +float autocvar_g_vehicle_bumblebee_cannon_radius; +float autocvar_g_vehicle_bumblebee_cannon_refire; +float autocvar_g_vehicle_bumblebee_cannon_speed; +float autocvar_g_vehicle_bumblebee_cannon_spread; +float autocvar_g_vehicle_bumblebee_cannon_force; + +float autocvar_g_vehicle_bumblebee_cannon_turnspeed; +float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down; +float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up; +float autocvar_g_vehicle_bumblebee_cannon_turnlimit_in; +float autocvar_g_vehicle_bumblebee_cannon_turnlimit_out; + +float autocvar_g_vehicle_bumblebee_respawntime; + +float autocvar_g_vehicle_bumblebee_blowup_radius; +float autocvar_g_vehicle_bumblebee_blowup_coredamage; +float autocvar_g_vehicle_bumblebee_blowup_edgedamage; +float autocvar_g_vehicle_bumblebee_blowup_forceintensity; + +#define BUMB_MIN '-120 -120 -40' +#define BUMB_MAX '120 120 40' + +.entity gunner1; +//.entity gunner2; +.vector lastaim; +float bumb_gunner_frame() +{ + entity vehic, gun, gunner; + float ftmp, ftmp2; + vector vtmp; + + vehic = self.vehicle; + gun = self.vehicle.gun1; + gunner = self; + + self = vehic; + vehic.solid = SOLID_NOT; + crosshair_trace(gunner); + + //vtmp = gettaginfo(vehic, gettagindexvehic, "tag_hardpoint01")); + vtmp = gettaginfo(gun, gettagindex(gun, "muzzle")); + vtmp = vectoangles(normalize(trace_endpos - vtmp)); // Find the direction & angle + vtmp = shortangle_vxy(vtmp - (vehic.angles + gun.angles), vehic.angles + gun.angles); // Find aim offset + + // Bind to aimspeed + ftmp2 = autocvar_g_vehicle_bumblebee_cannon_turnspeed * frametime; ftmp = -ftmp2; + vtmp_x = bound(ftmp, vtmp_x, ftmp2); + vtmp_y = bound(ftmp, vtmp_y, ftmp2); + // Bind to limts + gun.angles_x = bound(-autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down, vtmp_x + gun.angles_x, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up); + gun.angles_y = bound(-autocvar_g_vehicle_bumblebee_cannon_turnlimit_in, vtmp_y + gun.angles_y, autocvar_g_vehicle_bumblebee_cannon_turnlimit_out); + + if(gunner.BUTTON_ATCK && gun.cnt <= time) + { + vtmp = gettaginfo(gun, gettagindex(gun, "muzzle")); + v_forward = normalize(v_forward); + vtmp += v_forward * 50; + + fireBullet (vtmp, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_damage, + autocvar_g_vehicle_spiderbot_minigun_spread, DEATH_SBMINIGUN, 0); + + gun.cnt = time + 0.1; + } + + setorigin(gunner, vehic.origin); + gunner.velocity = vehic.velocity; + + vehic.solid = SOLID_BBOX; + gunner.BUTTON_ATCK = gunner.BUTTON_ATCK2 = gunner.BUTTON_CROUCH = 0; + self = gunner; + return 1; +} + +void bumb_gunner_enter() +{ + if(self.gunner1 != world) + return; + + self.gunner1 = other; + self.gunner1.vehicle = self; + + msg_entity = other; + WriteByte (MSG_ONE, SVC_SETVIEWPORT); + WriteEntity(MSG_ONE, self.gun1); + WriteByte (MSG_ONE, SVC_SETVIEWANGLES); + if(self.tur_head) + { + WriteAngle(MSG_ONE, self.gun1.angles_x + self.angles_x); // tilt + WriteAngle(MSG_ONE, self.gun1.angles_y + self.angles_y); // yaw + WriteAngle(MSG_ONE, 0); // roll + } + other.PlayerPhysplug = bumb_gunner_frame; +} + +float bumb_pilot_frame() +{ + entity pilot, gunner, vehic; + vector newvel; + + pilot = self; + vehic = self.vehicle; + self = vehic; + + if(pilot.BUTTON_USE && vehic.deadflag == DEAD_NO) + { + self = vehic; + vehicles_exit(VHEF_NORMAL); + self = pilot; + return 0; + } + + if(vehic.deadflag != DEAD_NO) + { + self = pilot; + pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = 0; + return 1; + } + + crosshair_trace(pilot); + + vector vang; + float ftmp; + + vang = vehic.angles; + newvel = vectoangles(normalize(trace_endpos - self.origin + '0 0 32')); + vang_x *= -1; + newvel_x *= -1; + if(newvel_x > 180) newvel_x -= 360; + if(newvel_x < -180) newvel_x += 360; + if(newvel_y > 180) newvel_y -= 360; + if(newvel_y < -180) newvel_y += 360; + + ftmp = shortangle_f(pilot.v_angle_y - vang_y, vang_y); + if(ftmp > 180) ftmp -= 360; if(ftmp < -180) ftmp += 360; + vehic.avelocity_y = bound(-autocvar_g_vehicle_bumblebee_turnspeed, ftmp + vehic.avelocity_y * 0.9, autocvar_g_vehicle_bumblebee_turnspeed); + + // Pitch + ftmp = 0; + if(pilot.movement_x > 0 && vang_x < autocvar_g_vehicle_bumblebee_pitchlimit) ftmp = 5; + else if(pilot.movement_x < 0 && vang_x > -autocvar_g_vehicle_bumblebee_pitchlimit) ftmp = -20; + + newvel_x = bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel_x , autocvar_g_vehicle_bumblebee_pitchlimit); + ftmp = vang_x - bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel_x + ftmp, autocvar_g_vehicle_bumblebee_pitchlimit); + vehic.avelocity_x = bound(-autocvar_g_vehicle_bumblebee_pitchspeed, ftmp + vehic.avelocity_x * 0.9, autocvar_g_vehicle_bumblebee_pitchspeed); + + vehic.angles_x = anglemods(vehic.angles_x); + vehic.angles_y = anglemods(vehic.angles_y); + vehic.angles_z = anglemods(vehic.angles_z); + + makevectors('0 1 0' * vehic.angles_y); + newvel = vehic.velocity * -autocvar_g_vehicle_bumblebee_friction; + + if(pilot.movement_x != 0) + { + if(pilot.movement_x > 0) + newvel += v_forward * autocvar_g_vehicle_bumblebee_speed_forward; + else if(pilot.movement_x < 0) + newvel -= v_forward * autocvar_g_vehicle_bumblebee_speed_forward; + } + + if(pilot.movement_y != 0) + { + if(pilot.movement_y < 0) + newvel -= v_right * autocvar_g_vehicle_bumblebee_speed_strafe; + else if(pilot.movement_y > 0) + newvel += v_right * autocvar_g_vehicle_bumblebee_speed_strafe; + ftmp = newvel * v_right; + ftmp *= frametime * 0.1; + vehic.angles_z = bound(-15, vehic.angles_z + ftmp, 15); + } + else + { + vehic.angles_z *= 0.95; + if(vehic.angles_z >= -1 && vehic.angles_z <= -1) + vehic.angles_z = 0; + } + + if(pilot.BUTTON_CROUCH) + newvel -= v_up * autocvar_g_vehicle_bumblebee_speed_down; + else if (pilot.BUTTON_JUMP) + newvel += v_up * autocvar_g_vehicle_bumblebee_speed_up; + + vehic.velocity += newvel * frametime; + pilot.velocity = pilot.movement = vehic.velocity; + setorigin(pilot,vehic.origin + '0 0 32'); + + + if(vehic.vehicle_flags & VHF_SHIELDREGEN) + vehicles_regen(dmg_time, vehicle_shield, autocvar_g_vehicle_bumblebee_shield, autocvar_g_vehicle_bumblebee_shield_regen_pause, autocvar_g_vehicle_bumblebee_shield_regen, frametime); + + if(vehic.vehicle_flags & VHF_HEALTHREGEN) + vehicles_regen(dmg_time, vehicle_health, autocvar_g_vehicle_bumblebee_health, autocvar_g_vehicle_bumblebee_health_regen_pause, autocvar_g_vehicle_bumblebee_health_regen, frametime); + + if(vehic.vehicle_flags & VHF_ENERGYREGEN) + vehicles_regen(cnt, vehicle_energy, autocvar_g_vehicle_bumblebee_energy, autocvar_g_vehicle_bumblebee_energy_regen_pause, autocvar_g_vehicle_bumblebee_energy_regen, frametime); + + VEHICLE_UPDATE_PLAYER(health, bumblebee); + VEHICLE_UPDATE_PLAYER(energy, bumblebee); + if(vehic.vehicle_flags & VHF_HASSHIELD) + VEHICLE_UPDATE_PLAYER(shield, bumblebee); + + pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = pilot.BUTTON_CROUCH = 0; + self = pilot; + + return 1; +} + +void bumb_think() +{ + self.velocity = self.velocity * 0.99; + self.nextthink = time + 0.1; +} + +void bumb_enter() +{ + self.touch = bumb_gunner_enter; +} + +void bumb_exit(float eject) +{ + self.owner = world; + self.touch = vehicles_touch; +} + +void bumb_spawn() +{ + self.vehicle_health = autocvar_g_vehicle_bumblebee_health; + self.vehicle_shield = autocvar_g_vehicle_bumblebee_shield; + self.movetype = MOVETYPE_TOSS; + self.solid = SOLID_BBOX; + //self.vehicle_energy = 1; + self.movetype = MOVETYPE_FLY; + setorigin(self, self.origin + '0 0 25'); +} + +void bumb_die() +{ + self.health = 0; + self.event_damage = SUB_Null; + self.solid = SOLID_CORPSE; + self.takedamage = DAMAGE_NO; + self.deadflag = DEAD_DYING; + self.movetype = MOVETYPE_BOUNCE; + + pointparticles(particleeffectnum("rocket_explode"), findbetterlocation (self.origin, 16), '0 0 0', 1); +} + +void bumb_dinit() +{ + if not (vehicle_initialize( + "Bumblebee", + "models/vehicles/bumblebee_body.dpm", + "", + "models/vehicles/spiderbot_cockpit.dpm", + "", "", "tag_viewport", + HUD_BUMBLEBEE, + BUMB_MIN, BUMB_MAX, + FALSE, + bumb_spawn, autocvar_g_vehicle_bumblebee_respawntime, + bumb_pilot_frame, + bumb_enter, bumb_exit, + bumb_die, bumb_think, + FALSE)) + { + remove(self); + return; + } + self.gun1 = spawn(); + setmodel(self.gun1, "models/vehicles/bumblebee_ray.dpm"); + setattachment(self.gun1, self, "tag_hardpoint03"); + + self.gun1 = spawn(); + self.gun2 = spawn(); + + self.gun1.owner = self; + self.gun2.owner = self; + + setmodel(self.gun1, "models/vehicles/bumblebee_plasma_right.dpm"); + setmodel(self.gun2, "models/vehicles/bumblebee_plasma_left.dpm"); + + setattachment(self.gun1, self, "tag_hardpoint01"); + setattachment(self.gun2, self, "tag_hardpoint02"); + + vector ofs; + ofs = gettaginfo(self, gettagindex(self, "tag_hardpoint01")); + ofs -= self.origin; + setattachment(self.gun1, self, ""); + setorigin(self.gun1, ofs); + + ofs = gettaginfo(self, gettagindex(self, "tag_hardpoint02")); + ofs -= self.origin; + setattachment(self.gun2, self, ""); + setorigin(self.gun2, ofs); + + +} + +void spawnfunc_vehicle_bumblebee() +{ + + precache_model ("models/vehicles/bumblebee_body.dpm"); + precache_model ("models/vehicles/bumblebee_plasma_left.dpm"); + precache_model ("models/vehicles/bumblebee_plasma_right.dpm"); + precache_model ("models/vehicles/bumblebee_ray.dpm"); + + //vehicles_configcheck("vehicle_bumblebee.cfg", autocvar_g_vehicle_bumblebee_health); + + if(autocvar_g_vehicle_bumblebee_energy) + if(autocvar_g_vehicle_bumblebee_energy_regen) + self.vehicle_flags |= VHF_ENERGYREGEN; + + if(autocvar_g_vehicle_bumblebee_shield) + self.vehicle_flags |= VHF_HASSHIELD; + + if(autocvar_g_vehicle_bumblebee_shield_regen) + self.vehicle_flags |= VHF_SHIELDREGEN; + + if(autocvar_g_vehicle_bumblebee_health_regen) + self.vehicle_flags |= VHF_HEALTHREGEN; + + self.think = bumb_dinit; + self.nextthink = time + 1; +} +#endif // SVQC + +#ifdef CSQC +void bumblebee_draw() +{ + +} + +void bumblebee_draw2d() +{ + +} + +void bumblebee_read_extra() +{ + +} + +void vehicle_bumblebee_assemble() +{ + +} +#endif //CSQC diff --git a/qcsrc/server/attic/vehicles/collision.qc b/qcsrc/server/attic/vehicles/collision.qc new file mode 100644 index 0000000000..11488a0d5a --- /dev/null +++ b/qcsrc/server/attic/vehicles/collision.qc @@ -0,0 +1,55 @@ +vector collision_force; +vector collision_angle; + +vector bb1[9]; +vector bb2[9]; + +float collision_run() +{ + vector vtmp, vmin, vmax, vrot, vforce, vtmp2, vtmp3; + float i, fvel, bcol; + + + // Extract the 8 bbox corners from mins/maxs for self + vmax = self.maxs; + vmin = self.mins; + bb1[0] = vmax; + vtmp = vmax; vtmp_x = vmin_x; bb1[1] = vtmp; + vtmp = vmax; vtmp_y = vmin_y; bb1[2] = vtmp; + vtmp = vmin; vtmp_z = vmax_z; bb1[3] = vtmp; + bb1[4] = vmin; + vtmp = vmin; vtmp_x = vmax_x; bb1[5] = vtmp; + vtmp = vmin; vtmp_y = vmax_y; bb1[6] = vtmp; + vtmp = vmax; vtmp_z = vmin_z; bb1[7] = vtmp; + + makevectors(self.angles + '-2 0 0' * self.angles_x); + bcol = 0; + + // Pass1: Transform by rotation, ajust points by impact/s + for(i = 8; i >= 0; --i) + { + vtmp = bb1[i]; + vtmp = self.origin + vtmp_x * v_forward - vtmp_y * v_right + vtmp_z * v_up; + traceline(self.origin, vtmp, MOVE_WORLDONLY, self); + te_lightning1(world,self.origin,vtmp); + if(trace_fraction != 1.0) + { + vforce += (trace_endpos - vtmp); + vtmp3 = self.origin + self.velocity * frametime; + vtmp2 = vectoangles(normalize(vtmp - vtmp3)); + vrot += (vectoangles(normalize(trace_endpos - vtmp3)) - vtmp2); + bcol += 1; + } + } + + if(bcol) + { + + vtmp = self.origin + self.velocity * frametime; + self.angles += vrot * frametime; + self.velocity += vforce * frametime; + + } + +} + diff --git a/qcsrc/server/attic/vehicles/network.qc b/qcsrc/server/attic/vehicles/network.qc new file mode 100644 index 0000000000..688aa7ca21 --- /dev/null +++ b/qcsrc/server/attic/vehicles/network.qc @@ -0,0 +1,237 @@ +#ifdef VEHICLES_CSQC +// SendFlags +float VSF_SETUP = 1; /// Send vehicle type etc +float VSF_ORIGIN = 2; /// Send location +float VSF_MOVEMENT = 4; /// Send movement update (and angles) +float VSF_AVEL = 8; /// Send Angular velocity +float VSF_STATS = 16; /// Send ammo, health etc +float VSF_EXTRA = 32; /// Send additional data (turret rotations etc). Handeld per vehicle type. +float VSF_ANIMINFO = 64; /// Animation info +float VSF_FULL_UPDATE = 16777215; /// Send everything + +float VSX_FAR = 1; +float VSX_OWNER = 2; +float VSX_GUN1 = 4; +float VSX_GUN2 = 8; + +#ifdef SVQC +#define VSX_FARDISTANCE 2000 +float send_vehile(entity to, float sf) +{ + float dist, xf; + + var void WriteFunc(float, float); + + dist = vlen(self.origin - to.origin); + if(to == self.owner) + xf |= VSX_OWNER; + else if(dist > VSX_FARDISTANCE) + xf |= VSX_FAR; + + // Always send a movement and origin to owner + if(to == self.owner) + sf |= VSF_ORIGIN | VSF_MOVEMENT; + + WriteByte(MSG_ENTITY, ENT_CLIENT_VEHICLE); + + // We need to know client-side what was sent + WriteByte(MSG_ENTITY, sf); + WriteByte(MSG_ENTITY, xf); + + if(sf & VSF_SETUP) + { + WriteByte(MSG_ENTITY, self.hud); //vehicle type = hud + WriteByte(MSG_ENTITY, self.team); + WriteShort(MSG_ENTITY, self.colormap); + WriteShort(MSG_ENTITY, self.vehicle_flags); + } + + if(sf & VSF_ORIGIN) + { + WriteFunc = ((xf & VSX_FAR) ? WriteShort : WriteCoord); + WriteFunc(MSG_ENTITY, self.origin_x); + WriteFunc(MSG_ENTITY, self.origin_y); + WriteFunc(MSG_ENTITY, self.origin_z); + } + + if(sf & VSF_MOVEMENT) + { + WriteFunc = ((xf & VSX_FAR) ? WriteShort : WriteCoord); + WriteFunc(MSG_ENTITY, self.velocity_x); + WriteFunc(MSG_ENTITY, self.velocity_y); + WriteFunc(MSG_ENTITY, self.velocity_z); + + WriteFunc = ((xf & VSX_FAR) ? WriteShort : WriteAngle); + WriteFunc(MSG_ENTITY, self.angles_x); + WriteFunc(MSG_ENTITY, self.angles_y); + WriteFunc(MSG_ENTITY, self.angles_z); + } + + if(sf & VSF_AVEL) + { + WriteFunc = ((xf & VSX_FAR) ? WriteShort : WriteCoord); + WriteFunc(MSG_ENTITY, self.avelocity_x); + WriteFunc(MSG_ENTITY, self.avelocity_y); + WriteFunc(MSG_ENTITY, self.avelocity_z); + } + + if(sf & VSF_STATS) + { + WriteByte(MSG_ENTITY, self.vehicle_health); + if(xf & VSX_OWNER) + { + WriteByte(MSG_ENTITY, self.vehicle_shield); + WriteByte(MSG_ENTITY, self.vehicle_energy); + + WriteByte(MSG_ENTITY, self.vehicle_ammo1); + WriteByte(MSG_ENTITY, self.vehicle_reload1); + + WriteByte(MSG_ENTITY, self.vehicle_ammo2); + WriteByte(MSG_ENTITY, self.vehicle_reload2); + + } + } + + if(sf & VSF_EXTRA) + self.vehile_send_exta(to, sf); + + return TRUE; +} + +void net_link_vehile() +{ + self.SendFlags = 0xFFFFFF; + Net_LinkEntity(self, FALSE, 0, send_vehile); +} +#endif // SVQC + +#ifdef CSQC +void vehicle_spiderbot_assemble() +{ + +} + +void vehicle_raptor_assemble() +{ + +} + +void vehicle_bumblebee_assemble() +{ + +} + +.float lastupdate; +void read_vehicle(float bIsNew) +{ + float sf, xf; + var float ReadFunc(); + + sf = ReadByte(); + xf = ReadByte(); + + if(xf & VSX_OWNER) + vehicle = self; + + if(sf & VSF_SETUP) + { + self.vehicle_hud = ReadByte(); + self.team = ReadByte(); + self.colormap = ReadShort(); + self.vehicle_flags = ReadShort(); + + switch(self.vehicle_hud) + { + case HUD_WAKIZASHI: + vehicle_racer_assemble(); + break; + case HUD_SPIDERBOT: + vehicle_spiderbot_assemble(); + break; + case HUD_RAPTOR: + vehicle_raptor_assemble(); + break; + case HUD_BUMBLEBEE: + vehicle_bumblebee_assemble(); + break; + default: + break; + } + } + + if(self.vehicle_hud == HUD_WAKIZASHI && xf & VSX_OWNER) + { + + vehicle_hudmodel.owner = self; + } + + //if(xf & VSX_FAR) + // dprint("Client vehicle faaar set\n"); + + if(sf & VSF_ORIGIN) + { + ReadFunc = ((xf & VSX_FAR) ? ReadShort : ReadCoord); + self.origin_x = ReadFunc(); + self.origin_y = ReadFunc(); + self.origin_z = ReadFunc(); + + setorigin(self, self.origin); + //self.lastupdate = time; + } + + if(sf & VSF_MOVEMENT) + { + ReadFunc = ((xf & VSX_FAR) ? ReadShort : ReadCoord); + self.velocity_x = ReadFunc(); + self.velocity_y = ReadFunc(); + self.velocity_z = ReadFunc(); + + ReadFunc = ((sf & VSX_FAR) ? ReadShort : ReadAngle); + self.angles_x = ReadFunc(); + self.angles_y = ReadFunc(); + self.angles_z = ReadFunc(); + + //self.lastupdate = time; + // self.move_velocity = self.velocity; + // self.move_angles = self.angles; + } + + if(sf & VSF_AVEL) + { + ReadFunc = ((xf & VSX_FAR) ? ReadShort : ReadCoord); + self.avelocity_x = ReadFunc(); + self.avelocity_y = ReadFunc(); + self.avelocity_z = ReadFunc(); + + // self.move_avelocity = self.avelocity; + } + + if(sf & VSF_STATS) + { + self.vehicle_health = ReadByte(); + if(xf & VSX_OWNER) + { + self.vehicle_shield = ReadByte(); + self.vehicle_energy = ReadByte(); + self.vehicle_ammo1 = ReadByte(); + self.vehicle_reload1 = ReadByte(); + self.vehicle_ammo2 = ReadByte(); + self.vehicle_reload2 = ReadByte(); + } + } + + if(sf & VSF_EXTRA) + self.vehile_read_exta(sf); + +} + +#endif // CSQC +#else +#ifdef CSQC +.float lastupdate; +void read_vehicle(float bIsNew) +{ + +} +#endif +#endif // VEHICLES_CSQC diff --git a/qcsrc/server/attic/verbstack.qc b/qcsrc/server/attic/verbstack.qc new file mode 100644 index 0000000000..b0601afe64 --- /dev/null +++ b/qcsrc/server/attic/verbstack.qc @@ -0,0 +1,274 @@ +/// Some default stacks. +.entity verbs_idle; +.entity verbs_attack; +.entity verbs_move; +//.entity vchain; + +/// This global gets set to the verb in question each time the stack manager calls verb_call +entity verb; +//.entity current_verb; +//.float verb_done; + +/// Execure this verb +#define VCM_DO 0 +/// Return the value of this verb. Return VS_CALL_REMOVE to delete it. +#define VCM_EVAL 1 +/// This verb is beeing removed NOW (not sent when verb_call returns VS_CALL_REMOVE) +#define VCM_REMOVE 2 + +/// Verb callback +.float(float message) verb_call; + +/// Points to this verb's stack. +.entity verbstack; + +/// Static value of this verb +.float verb_static_value; + +/// verb_call returns this when a verb in not doable +#define VS_CALL_NO 0 +/// verb_call(VCM_DO) returns this when a verb is executing +#define VS_CALL_YES_DOING -1 +/// verb_call(VCM_DO) returns this when a verb did execure and is done +#define VS_CALL_YES_DONE -2 +/// verb_call(VCM_DO) returns this when a verb should be deleted by the stack manager +#define VS_CALL_REMOVE -3 + +/* +void verbstack_updatechain(entity stack) +{ + entity vrb, v; + if not (stack) + return; + + dprint("verbstack_updatechain\n"); + + vrb = findchainentity(verbstack, stack); + if not (vrb) + { + stack.vchain = world; + return; + } + + stack.vchain = vrb; + v = vrb; + + while(vrb) + { + vrb = vrb.chain; + + + } +} + +void verbstack_remove(entity vverb) +{ + entity vstack; + dprint("verbstack_remove\n"); + + vstack = verb.verbstack; + remove(vverb); + vverb.verbstack = world; + verbstack_updatechain(vstack); + + //vverb.think = SUB_Remove; + //vverb.nextthink = time; +} + +void verbstack_thinkremove() +{ + dprint("verbstack_thinkremove\n"); + verbstack_remove(self); +} +*/ + +/** + Push a new verb onto the specified stack. Set vrb_life to make it time-limited. +**/ +entity verbstack_push(entity stack, float(float eval) vrb_call, float val_static, float vrb_life,entity verb_owner) +{ + entity vrb; + + if not(stack) + return world; + + if not(vrb_call) + return world; + + vrb = spawn(); + vrb.owner = verb_owner; + vrb.verbstack = stack; + vrb.verb_call = vrb_call; + vrb.verb_static_value = val_static; + + vrb.classname = "verb"; + stack.classname = "verbstack"; + + if(vrb_life) + { + //vrb.think = verbstack_thinkremove; + vrb.think = SUB_Remove; + vrb.nextthink = time + vrb_life; + } + + //verbstack_updatechain(stack); + + return vrb; +} + +/** + Find the best verb in this stack and execurte it. + ALso remove any verbs returning VS_CALL_REMOVE on VCM_EVAL or VCM_DO +**/ +float verbstack_pop(entity stack) +{ + entity vrb, bestverb, oldself; + float value, bestvalue; + + oldself = self; + + vrb = findchainentity(verbstack,stack); + //vrb = stack.vchain; + //dprint("owner:", stack.owner.classname, " vsn:", stack.classname,"\n"); + while(vrb) + { + //dprint("vn:", vrb.classname,"\n"); + verb = vrb; + vrb = vrb.chain; + self = verb.owner; + value = verb.verb_call(VCM_EVAL); + + if(value < 0) + { + if(value == VS_CALL_REMOVE) + remove(verb); + } + else + { + if(value > bestvalue) + { + bestverb = verb; + bestvalue = value; + } + } + } + + if(bestverb) + { + verb = bestverb; + self = verb.owner; + value = verb.verb_call(VCM_DO); + + if(value == VS_CALL_REMOVE) + remove(bestverb); + } + + self = oldself; + + return value; +} + +float verbstack_popfifo(entity stack) +{ + entity oldself; + float ret; + + oldself = self; + verb = findentity(stack,verbstack,stack); + if not (verb) + ret = 0; + else + { + self = verb.owner; + ret = verb.verb_call(VCM_DO); + + if(ret == VS_CALL_REMOVE) + remove(verb); + } + + self = oldself; + return ret; +} + +/** + Find the best verb in this stack and return it. + ALso remove any verbs returning VS_CALL_REMOVE on VCM_EVAL. +**/ +entity verbstack_pull(entity stack) +{ + entity vrb; + entity bestverb, oldself; + float value, bestvalue; + + oldself = self; + + vrb = findchainentity(verbstack,stack); + while(vrb) + { + self = vrb.owner; + + verb = vrb; + vrb = vrb.chain; + value = verb.verb_call(VCM_EVAL); + + if(value < 0) + { + if(value == VS_CALL_REMOVE) + remove(verb); + } + else + { + if(value > bestvalue) + { + bestverb = verb; + bestvalue = value; + } + } + } + + self = oldself; + + return bestverb; +} + +entity verbstack_pullfifo(entity stack) +{ + return findentity(stack,verbstack,stack); +} + +/** + Delete every verb on this stack, signaling them with VCM_REMOVE first. +**/ +void verbstack_flush(entity stack) +{ + entity vrb, oldself; + + oldself = self; + + vrb = findchainentity(verbstack,stack); + while(vrb) + { + self = vrb.owner; + + verb = vrb; + vrb = vrb.chain; + verb.verb_call(VCM_REMOVE); + remove(verb); + } + + self = oldself; + + //stack.vchain = world; +} + +void verbstack_doverb(entity vrb) +{ + float value; + + verb = vrb; + self = verb.owner; + value = verb.verb_call(VCM_DO); + + if(value == VS_CALL_REMOVE) + remove(vrb); +} diff --git a/qcsrc/server/autocvars.qh b/qcsrc/server/autocvars.qh index c5beab2699..538d65307f 100644 --- a/qcsrc/server/autocvars.qh +++ b/qcsrc/server/autocvars.qh @@ -1,3 +1,5 @@ +float autocvar__notarget; +float autocvar__independent_players; float autocvar__campaign_index; string autocvar__campaign_name; float autocvar__sv_init; @@ -35,7 +37,7 @@ float autocvar_bot_ai_enemydetectionradius; float autocvar_bot_ai_friends_aware_pickup_radius; float autocvar_bot_ai_ignoregoal_timeout; float autocvar_bot_ai_keyboard_distance; -float autocvar_bot_ai_keyboard_treshold; +float autocvar_bot_ai_keyboard_threshold; float autocvar_bot_ai_navigation_jetpack; float autocvar_bot_ai_navigation_jetpack_mindistance; float autocvar_bot_ai_strategyinterval; @@ -54,9 +56,11 @@ float autocvar_bot_sound_monopoly; #define autocvar_bot_suffix cvar_string("bot_suffix") float autocvar_bot_usemodelnames; float autocvar_bot_vs_human; +float autocvar_bot_debug_tracewalk; +float autocvar_bot_debug_goalstack; +float autocvar_bot_wander_enable; float autocvar_captureleadlimit_override; #define autocvar_capturelimit_override cvar("capturelimit_override") -float autocvar_deathmatch_force_teamplay; #define autocvar_developer cvar("developer") float autocvar_developer_fteqccbugs; float autocvar_ekg; @@ -69,7 +73,6 @@ float autocvar_g_antilag_nudge; float autocvar_g_arena_maxspawned; float autocvar_g_arena_point_leadlimit; float autocvar_g_arena_point_limit; -float autocvar_g_arena_powerups; float autocvar_g_arena_roundbased; float autocvar_g_arena_warmup; float autocvar_g_assault; @@ -82,38 +85,46 @@ float autocvar_g_balance_armor_rot; float autocvar_g_balance_armor_rotlinear; float autocvar_g_balance_armor_rotstable; float autocvar_g_balance_armor_start; -float autocvar_g_balance_campingrifle_auto_reload_on_switch; -float autocvar_g_balance_campingrifle_bursttime; -float autocvar_g_balance_campingrifle_magazinecapacity; -float autocvar_g_balance_campingrifle_primary_ammo; -float autocvar_g_balance_campingrifle_primary_animtime; -float autocvar_g_balance_campingrifle_primary_bulletconstant; -float autocvar_g_balance_campingrifle_primary_bullethail; -float autocvar_g_balance_campingrifle_primary_burstcost; -float autocvar_g_balance_campingrifle_primary_damage; -float autocvar_g_balance_campingrifle_primary_force; -float autocvar_g_balance_campingrifle_primary_headshotaddeddamage; -float autocvar_g_balance_campingrifle_primary_lifetime; -float autocvar_g_balance_campingrifle_primary_refire; -float autocvar_g_balance_campingrifle_primary_speed; -float autocvar_g_balance_campingrifle_primary_spread; -float autocvar_g_balance_campingrifle_primary_tracer; -float autocvar_g_balance_campingrifle_reloadtime; -float autocvar_g_balance_campingrifle_secondary; -float autocvar_g_balance_campingrifle_secondary_ammo; -float autocvar_g_balance_campingrifle_secondary_animtime; -float autocvar_g_balance_campingrifle_secondary_bulletconstant; -float autocvar_g_balance_campingrifle_secondary_bullethail; -float autocvar_g_balance_campingrifle_secondary_burstcost; -float autocvar_g_balance_campingrifle_secondary_damage; -float autocvar_g_balance_campingrifle_secondary_force; -float autocvar_g_balance_campingrifle_secondary_headshotaddeddamage; -float autocvar_g_balance_campingrifle_secondary_lifetime; -float autocvar_g_balance_campingrifle_secondary_refire; -float autocvar_g_balance_campingrifle_secondary_speed; -float autocvar_g_balance_campingrifle_secondary_spread; -float autocvar_g_balance_campingrifle_secondary_tracer; +float autocvar_g_balance_rifle_bursttime; +float autocvar_g_balance_rifle_primary_ammo; +float autocvar_g_balance_rifle_primary_animtime; +float autocvar_g_balance_rifle_primary_bulletconstant; +float autocvar_g_balance_rifle_primary_bullethail; +float autocvar_g_balance_rifle_primary_burstcost; +float autocvar_g_balance_rifle_primary_damage; +float autocvar_g_balance_rifle_primary_force; +float autocvar_g_balance_rifle_primary_headshotaddeddamage; +float autocvar_g_balance_rifle_primary_lifetime; +float autocvar_g_balance_rifle_primary_refire; +float autocvar_g_balance_rifle_primary_shots; +float autocvar_g_balance_rifle_primary_speed; +float autocvar_g_balance_rifle_primary_spread; +float autocvar_g_balance_rifle_primary_tracer; +float autocvar_g_balance_rifle_secondary; +float autocvar_g_balance_rifle_secondary_ammo; +float autocvar_g_balance_rifle_secondary_animtime; +float autocvar_g_balance_rifle_secondary_bulletconstant; +float autocvar_g_balance_rifle_secondary_bullethail; +float autocvar_g_balance_rifle_secondary_burstcost; +float autocvar_g_balance_rifle_secondary_damage; +float autocvar_g_balance_rifle_secondary_force; +float autocvar_g_balance_rifle_secondary_headshotaddeddamage; +float autocvar_g_balance_rifle_secondary_lifetime; +float autocvar_g_balance_rifle_secondary_reload; +float autocvar_g_balance_rifle_secondary_refire; +float autocvar_g_balance_rifle_secondary_shots; +float autocvar_g_balance_rifle_secondary_speed; +float autocvar_g_balance_rifle_secondary_spread; +float autocvar_g_balance_rifle_secondary_tracer; +float autocvar_g_balance_rifle_reload_ammo; +float autocvar_g_balance_rifle_reload_time; float autocvar_g_balance_cloaked_alpha; +float autocvar_g_balance_contents_damagerate; +float autocvar_g_balance_contents_drowndelay; +float autocvar_g_balance_contents_playerdamage_drowning; +float autocvar_g_balance_contents_playerdamage_lava; +float autocvar_g_balance_contents_playerdamage_slime; +float autocvar_g_balance_contents_projectiledamage; float autocvar_g_balance_crylink_primary_ammo; float autocvar_g_balance_crylink_primary_animtime; float autocvar_g_balance_crylink_primary_bouncedamagefactor; @@ -121,6 +132,7 @@ float autocvar_g_balance_crylink_primary_bounces; float autocvar_g_balance_crylink_primary_damage; float autocvar_g_balance_crylink_primary_edgedamage; float autocvar_g_balance_crylink_primary_force; +float autocvar_g_balance_crylink_primary_joindelay; float autocvar_g_balance_crylink_primary_joinexplode; float autocvar_g_balance_crylink_primary_joinexplode_damage; float autocvar_g_balance_crylink_primary_joinexplode_edgedamage; @@ -146,6 +158,7 @@ float autocvar_g_balance_crylink_secondary_bounces; float autocvar_g_balance_crylink_secondary_damage; float autocvar_g_balance_crylink_secondary_edgedamage; float autocvar_g_balance_crylink_secondary_force; +float autocvar_g_balance_crylink_secondary_joindelay; float autocvar_g_balance_crylink_secondary_joinexplode; float autocvar_g_balance_crylink_secondary_joinexplode_damage; float autocvar_g_balance_crylink_secondary_joinexplode_edgedamage; @@ -163,6 +176,8 @@ float autocvar_g_balance_crylink_secondary_refire; float autocvar_g_balance_crylink_secondary_shots; float autocvar_g_balance_crylink_secondary_speed; float autocvar_g_balance_crylink_secondary_spread; +float autocvar_g_balance_crylink_reload_ammo; +float autocvar_g_balance_crylink_reload_time; float autocvar_g_balance_ctf_damageforcescale; float autocvar_g_balance_ctf_delay_collect; float autocvar_g_balance_curse_empathy_minhealth; @@ -175,12 +190,14 @@ float autocvar_g_balance_curse_venom_rotrate; float autocvar_g_balance_curse_vulner_takedamage; float autocvar_g_balance_curse_weak_damage; float autocvar_g_balance_curse_weak_force; +float autocvar_g_balance_damagepush_speedfactor; float autocvar_g_balance_electro_combo_comboradius; float autocvar_g_balance_electro_combo_damage; float autocvar_g_balance_electro_combo_edgedamage; float autocvar_g_balance_electro_combo_force; float autocvar_g_balance_electro_combo_radius; float autocvar_g_balance_electro_combo_speed; +float autocvar_g_balance_electro_combo_safeammocheck; float autocvar_g_balance_electro_lightning; float autocvar_g_balance_electro_primary_ammo; float autocvar_g_balance_electro_primary_animtime; @@ -204,6 +221,7 @@ float autocvar_g_balance_electro_secondary_bouncestop; float autocvar_g_balance_electro_secondary_count; float autocvar_g_balance_electro_secondary_damage; float autocvar_g_balance_electro_secondary_damageforcescale; +float autocvar_g_balance_electro_secondary_damagedbycontents; float autocvar_g_balance_electro_secondary_edgedamage; float autocvar_g_balance_electro_secondary_force; float autocvar_g_balance_electro_secondary_health; @@ -212,6 +230,8 @@ float autocvar_g_balance_electro_secondary_radius; float autocvar_g_balance_electro_secondary_refire; float autocvar_g_balance_electro_secondary_refire2; float autocvar_g_balance_electro_secondary_speed; +float autocvar_g_balance_electro_reload_ammo; +float autocvar_g_balance_electro_reload_time; float autocvar_g_balance_falldamage_deadminspeed; float autocvar_g_balance_falldamage_factor; float autocvar_g_balance_falldamage_maxdamage; @@ -248,6 +268,8 @@ float autocvar_g_balance_fireball_secondary_lifetime; float autocvar_g_balance_fireball_secondary_refire; float autocvar_g_balance_fireball_secondary_speed; float autocvar_g_balance_fireball_secondary_speed_up; +float autocvar_g_balance_fireball_reload_ammo; +float autocvar_g_balance_fireball_reload_time; float autocvar_g_balance_firetransfer_damage; float autocvar_g_balance_firetransfer_time; float autocvar_g_balance_fuel_limit; @@ -265,6 +287,7 @@ float autocvar_g_balance_grapplehook_length_min; float autocvar_g_balance_grapplehook_speed_fly; float autocvar_g_balance_grapplehook_speed_pull; float autocvar_g_balance_grapplehook_stretch; +float autocvar_g_balance_grapplehook_damagedbycontents; float autocvar_g_balance_grenadelauncher_bouncefactor; float autocvar_g_balance_grenadelauncher_bouncestop; float autocvar_g_balance_grenadelauncher_primary_ammo; @@ -275,7 +298,7 @@ float autocvar_g_balance_grenadelauncher_primary_edgedamage; float autocvar_g_balance_grenadelauncher_primary_force; float autocvar_g_balance_grenadelauncher_primary_health; float autocvar_g_balance_grenadelauncher_primary_lifetime; -float autocvar_g_balance_grenadelauncher_primary_lifetime2; +float autocvar_g_balance_grenadelauncher_primary_lifetime_stick; float autocvar_g_balance_grenadelauncher_primary_radius; float autocvar_g_balance_grenadelauncher_primary_refire; float autocvar_g_balance_grenadelauncher_primary_remote_minbouncecnt; @@ -290,29 +313,50 @@ float autocvar_g_balance_grenadelauncher_secondary_edgedamage; float autocvar_g_balance_grenadelauncher_secondary_force; float autocvar_g_balance_grenadelauncher_secondary_health; float autocvar_g_balance_grenadelauncher_secondary_lifetime; -float autocvar_g_balance_grenadelauncher_secondary_lifetime2; +float autocvar_g_balance_grenadelauncher_secondary_lifetime_bounce; +float autocvar_g_balance_grenadelauncher_secondary_lifetime_stick; float autocvar_g_balance_grenadelauncher_secondary_radius; float autocvar_g_balance_grenadelauncher_secondary_refire; float autocvar_g_balance_grenadelauncher_secondary_speed; float autocvar_g_balance_grenadelauncher_secondary_speed_up; float autocvar_g_balance_grenadelauncher_secondary_type; +float autocvar_g_balance_grenadelauncher_reload_ammo; +float autocvar_g_balance_grenadelauncher_reload_time; float autocvar_g_balance_hagar_primary_ammo; float autocvar_g_balance_hagar_primary_damage; float autocvar_g_balance_hagar_primary_edgedamage; float autocvar_g_balance_hagar_primary_force; +float autocvar_g_balance_hagar_primary_health; +float autocvar_g_balance_hagar_primary_damageforcescale; float autocvar_g_balance_hagar_primary_lifetime; float autocvar_g_balance_hagar_primary_radius; float autocvar_g_balance_hagar_primary_refire; float autocvar_g_balance_hagar_primary_speed; float autocvar_g_balance_hagar_secondary; +float autocvar_g_balance_hagar_secondary_load; +float autocvar_g_balance_hagar_secondary_load_speed; +float autocvar_g_balance_hagar_secondary_load_spread; +float autocvar_g_balance_hagar_secondary_load_spread_bias; +float autocvar_g_balance_hagar_secondary_load_max; +float autocvar_g_balance_hagar_secondary_load_hold; +float autocvar_g_balance_hagar_secondary_load_releasedeath; +float autocvar_g_balance_hagar_secondary_load_abort; +float autocvar_g_balance_hagar_secondary_load_linkexplode; +float autocvar_g_balance_hagar_secondary_load_animtime; float autocvar_g_balance_hagar_secondary_ammo; float autocvar_g_balance_hagar_secondary_damage; float autocvar_g_balance_hagar_secondary_edgedamage; float autocvar_g_balance_hagar_secondary_force; +float autocvar_g_balance_hagar_secondary_health; +float autocvar_g_balance_hagar_secondary_damageforcescale; float autocvar_g_balance_hagar_secondary_lifetime_min; float autocvar_g_balance_hagar_secondary_lifetime_rand; float autocvar_g_balance_hagar_secondary_radius; float autocvar_g_balance_hagar_secondary_refire; +float autocvar_g_balance_hagar_secondary_speed; +float autocvar_g_balance_hagar_secondary_spread; +float autocvar_g_balance_hagar_reload_ammo; +float autocvar_g_balance_hagar_reload_time; float autocvar_g_balance_health_limit; float autocvar_g_balance_health_regen; float autocvar_g_balance_health_regenlinear; @@ -347,6 +391,8 @@ float autocvar_g_balance_hlac_secondary_shots; float autocvar_g_balance_hlac_secondary_speed; float autocvar_g_balance_hlac_secondary_spread; float autocvar_g_balance_hlac_secondary_spread_crouchmod; +float autocvar_g_balance_hlac_reload_ammo; +float autocvar_g_balance_hlac_reload_time; float autocvar_g_balance_hook_primary_animtime; float autocvar_g_balance_hook_primary_fuel; float autocvar_g_balance_hook_primary_hooked_fuel; @@ -365,9 +411,10 @@ float autocvar_g_balance_hook_secondary_power; float autocvar_g_balance_hook_secondary_radius; float autocvar_g_balance_hook_secondary_refire; float autocvar_g_balance_hook_secondary_speed; +float autocvar_g_balance_hook_secondary_health; +float autocvar_g_balance_hook_secondary_damageforcescale; float autocvar_g_balance_keyhunt_damageforcescale; float autocvar_g_balance_keyhunt_delay_collect; -float autocvar_g_balance_keyhunt_delay_drop; float autocvar_g_balance_keyhunt_delay_return; float autocvar_g_balance_keyhunt_delay_round; float autocvar_g_balance_keyhunt_delay_tracking; @@ -388,6 +435,7 @@ float autocvar_g_balance_laser_primary_damage; float autocvar_g_balance_laser_primary_delay; float autocvar_g_balance_laser_primary_edgedamage; float autocvar_g_balance_laser_primary_force; +float autocvar_g_balance_laser_primary_force_other_scale; float autocvar_g_balance_laser_primary_force_velocitybias; float autocvar_g_balance_laser_primary_force_zscale; float autocvar_g_balance_laser_primary_lifetime; @@ -400,11 +448,14 @@ float autocvar_g_balance_laser_secondary_animtime; float autocvar_g_balance_laser_secondary_damage; float autocvar_g_balance_laser_secondary_edgedamage; float autocvar_g_balance_laser_secondary_force; +float autocvar_g_balance_laser_secondary_force_other_scale; float autocvar_g_balance_laser_secondary_force_velocitybias; float autocvar_g_balance_laser_secondary_force_zscale; float autocvar_g_balance_laser_secondary_lifetime; float autocvar_g_balance_laser_secondary_radius; float autocvar_g_balance_laser_secondary_speed; +float autocvar_g_balance_laser_reload_ammo; +float autocvar_g_balance_laser_reload_time; float autocvar_g_balance_minelayer_ammo; float autocvar_g_balance_minelayer_animtime; float autocvar_g_balance_minelayer_damage; @@ -414,6 +465,7 @@ float autocvar_g_balance_minelayer_edgedamage; float autocvar_g_balance_minelayer_force; float autocvar_g_balance_minelayer_health; float autocvar_g_balance_minelayer_lifetime; +float autocvar_g_balance_minelayer_lifetime_countdown; float autocvar_g_balance_minelayer_limit; float autocvar_g_balance_minelayer_protection; float autocvar_g_balance_minelayer_proximityradius; @@ -425,10 +477,18 @@ float autocvar_g_balance_minelayer_remote_force; float autocvar_g_balance_minelayer_remote_radius; float autocvar_g_balance_minelayer_speed; float autocvar_g_balance_minelayer_time; +float autocvar_g_balance_minelayer_reload_ammo; +float autocvar_g_balance_minelayer_reload_time; float autocvar_g_balance_minstanex_ammo; +float autocvar_g_balance_minstanex_laser_ammo; +float autocvar_g_balance_minstanex_laser_animtime; +float autocvar_g_balance_minstanex_laser_refire; float autocvar_g_balance_minstanex_animtime; float autocvar_g_balance_minstanex_refire; +float autocvar_g_balance_minstanex_reload_ammo; +float autocvar_g_balance_minstanex_reload_time; float autocvar_g_balance_nex_charge; +float autocvar_g_balance_nex_charge_animlimit; float autocvar_g_balance_nex_charge_limit; float autocvar_g_balance_nex_charge_maxspeed; float autocvar_g_balance_nex_charge_mindmg; @@ -464,6 +524,8 @@ float autocvar_g_balance_nex_secondary_damagefalloff_maxdist; float autocvar_g_balance_nex_secondary_damagefalloff_mindist; float autocvar_g_balance_nex_secondary_force; float autocvar_g_balance_nex_secondary_refire; +float autocvar_g_balance_nex_reload_ammo; +float autocvar_g_balance_nex_reload_time; float autocvar_g_balance_nexball_primary_animtime; float autocvar_g_balance_nexball_primary_refire; float autocvar_g_balance_nexball_primary_speed; @@ -506,7 +568,6 @@ float autocvar_g_balance_powerup_strength_force; float autocvar_g_balance_powerup_strength_selfdamage; float autocvar_g_balance_powerup_strength_selfforce; float autocvar_g_balance_powerup_strength_time; -float autocvar_g_balance_powerup_timer; float autocvar_g_balance_rocketlauncher_ammo; float autocvar_g_balance_rocketlauncher_animtime; float autocvar_g_balance_rocketlauncher_damage; @@ -530,6 +591,8 @@ float autocvar_g_balance_rocketlauncher_remote_radius; float autocvar_g_balance_rocketlauncher_speed; float autocvar_g_balance_rocketlauncher_speedaccel; float autocvar_g_balance_rocketlauncher_speedstart; +float autocvar_g_balance_rocketlauncher_reload_ammo; +float autocvar_g_balance_rocketlauncher_reload_time; float autocvar_g_balance_rune_defense_combo_takedamage; float autocvar_g_balance_rune_defense_takedamage; float autocvar_g_balance_rune_regen_combo_hpmod; @@ -550,6 +613,7 @@ float autocvar_g_balance_rune_strength_force; float autocvar_g_balance_rune_vampire_absorb; float autocvar_g_balance_rune_vampire_combo_absorb; float autocvar_g_balance_rune_vampire_maxhealth; +float autocvar_g_balance_seeker_type; float autocvar_g_balance_seeker_flac_ammo; float autocvar_g_balance_seeker_flac_animtime; float autocvar_g_balance_seeker_flac_damage; @@ -561,6 +625,7 @@ float autocvar_g_balance_seeker_flac_radius; float autocvar_g_balance_seeker_flac_refire; float autocvar_g_balance_seeker_missile_accel; float autocvar_g_balance_seeker_missile_ammo; +float autocvar_g_balance_seeker_missile_animtime; float autocvar_g_balance_seeker_missile_count; float autocvar_g_balance_seeker_missile_damage; float autocvar_g_balance_seeker_missile_damageforcescale; @@ -574,6 +639,7 @@ float autocvar_g_balance_seeker_missile_proxy; float autocvar_g_balance_seeker_missile_proxy_delay; float autocvar_g_balance_seeker_missile_proxy_maxrange; float autocvar_g_balance_seeker_missile_radius; +float autocvar_g_balance_seeker_missile_refire; float autocvar_g_balance_seeker_missile_smart; float autocvar_g_balance_seeker_missile_smart_mindist; float autocvar_g_balance_seeker_missile_smart_trace_max; @@ -587,6 +653,9 @@ float autocvar_g_balance_seeker_tag_health; float autocvar_g_balance_seeker_tag_lifetime; float autocvar_g_balance_seeker_tag_refire; float autocvar_g_balance_seeker_tag_speed; +float autocvar_g_balance_seeker_tag_tracker_lifetime; +float autocvar_g_balance_seeker_reload_ammo; +float autocvar_g_balance_seeker_reload_time; float autocvar_g_balance_selfdamagepercent; float autocvar_g_balance_shotgun_primary_ammo; float autocvar_g_balance_shotgun_primary_animtime; @@ -603,9 +672,16 @@ float autocvar_g_balance_shotgun_secondary_damage; float autocvar_g_balance_shotgun_secondary_force; float autocvar_g_balance_shotgun_secondary_melee_delay; float autocvar_g_balance_shotgun_secondary_melee_range; -float autocvar_g_balance_shotgun_secondary_melee_swing; +float autocvar_g_balance_shotgun_secondary_melee_swing_side; +float autocvar_g_balance_shotgun_secondary_melee_swing_up; float autocvar_g_balance_shotgun_secondary_melee_time; +float autocvar_g_balance_shotgun_secondary_melee_traces; +float autocvar_g_balance_shotgun_secondary_melee_no_doubleslap; +float autocvar_g_balance_shotgun_secondary_melee_nonplayerdamage; +float autocvar_g_balance_shotgun_secondary_melee_multihit; float autocvar_g_balance_shotgun_secondary_refire; +float autocvar_g_balance_shotgun_reload_ammo; +float autocvar_g_balance_shotgun_reload_time; float autocvar_g_balance_teams; float autocvar_g_balance_teams_force; float autocvar_g_balance_teams_prevent_imbalance; @@ -619,12 +695,14 @@ float autocvar_g_balance_tuba_refire; float autocvar_g_balance_uzi_bulletconstant; float autocvar_g_balance_uzi_burst; float autocvar_g_balance_uzi_burst_ammo; +float autocvar_g_balance_uzi_burst_animtime; float autocvar_g_balance_uzi_burst_refire; float autocvar_g_balance_uzi_burst_refire2; float autocvar_g_balance_uzi_burst_spread; float autocvar_g_balance_uzi_first; float autocvar_g_balance_uzi_first_ammo; float autocvar_g_balance_uzi_first_damage; +float autocvar_g_balance_uzi_first_headshotaddeddamage; float autocvar_g_balance_uzi_first_force; float autocvar_g_balance_uzi_first_refire; float autocvar_g_balance_uzi_first_spread; @@ -635,9 +713,12 @@ float autocvar_g_balance_uzi_spread_max; float autocvar_g_balance_uzi_spread_min; float autocvar_g_balance_uzi_sustained_ammo; float autocvar_g_balance_uzi_sustained_damage; +float autocvar_g_balance_uzi_sustained_headshotaddeddamage; float autocvar_g_balance_uzi_sustained_force; float autocvar_g_balance_uzi_sustained_refire; float autocvar_g_balance_uzi_sustained_spread; +float autocvar_g_balance_uzi_reload_ammo; +float autocvar_g_balance_uzi_reload_time; float autocvar_g_balance_weaponswitchdelay; float autocvar_g_ballistics_density_corpse; float autocvar_g_ballistics_density_player; @@ -659,9 +740,10 @@ float autocvar_g_ca_damage2score_multiplier; float autocvar_g_ca_point_leadlimit; float autocvar_g_ca_point_limit; float autocvar_g_ca_round_timelimit; +float autocvar_g_ca_spectate_enemies; float autocvar_g_ca_warmup; float autocvar_g_campaign; -float autocvar_g_campaign_forceteam; +#define autocvar_g_campaign_forceteam cvar("g_campaign_forceteam") float autocvar_g_campaign_skill; float autocvar_g_casings; float autocvar_g_changeteam_banned; @@ -677,10 +759,7 @@ float autocvar_g_chat_flood_spl_team; float autocvar_g_chat_flood_spl_tell; float autocvar_g_chat_nospectators; float autocvar_g_chat_teamcolors; -float autocvar_g_ctf_allow_drop; float autocvar_g_ctf_captimerecord_always; -float autocvar_g_ctf_capture_leadlimit; -float autocvar_g_ctf_capture_limit; float autocvar_g_ctf_dynamiclights; string autocvar_g_ctf_flag_blue_model; float autocvar_g_ctf_flag_blue_skin; @@ -699,7 +778,6 @@ float autocvar_g_ctf_shield_max_ratio; float autocvar_g_ctf_shield_min_negscore; float autocvar_g_cts_finish_kill_delay; float autocvar_g_cts_selfdamage; -float autocvar_g_deathglow; float autocvar_g_debug_bot_commands; float autocvar_g_domination_default_teams; float autocvar_g_domination_disable_frags; @@ -719,9 +797,12 @@ float autocvar_g_freezetag_frozen_force; float autocvar_g_freezetag_point_leadlimit; float autocvar_g_freezetag_point_limit; float autocvar_g_freezetag_revive_extra_size; -float autocvar_g_freezetag_revive_time; +float autocvar_g_freezetag_revive_speed; +float autocvar_g_freezetag_revive_clearspeed; float autocvar_g_freezetag_warmup; #define autocvar_g_friendlyfire cvar("g_friendlyfire") +#define autocvar_g_friendlyfire_virtual cvar("g_friendlyfire_virtual") +#define autocvar_g_friendlyfire_virtual_force cvar("g_friendlyfire_virtual_force") float autocvar_g_full_getstatus_responses; float autocvar_g_fullbrightitems; float autocvar_g_fullbrightplayers; @@ -737,19 +818,23 @@ float autocvar_g_jetpack_attenuation; float autocvar_g_jetpack_fuel; float autocvar_g_jetpack_maxspeed_side; float autocvar_g_jetpack_maxspeed_up; -float autocvar_g_keepaway_ballcarrier_alpha; +float autocvar_g_keepaway_ballcarrier_effects; float autocvar_g_keepaway_ballcarrier_damage; float autocvar_g_keepaway_ballcarrier_force; float autocvar_g_keepaway_ballcarrier_highspeed; float autocvar_g_keepaway_ballcarrier_selfdamage; float autocvar_g_keepaway_ballcarrier_selfforce; -float autocvar_g_keepaway_bckillscore; float autocvar_g_keepaway_noncarrier_damage; float autocvar_g_keepaway_noncarrier_force; float autocvar_g_keepaway_noncarrier_selfdamage; float autocvar_g_keepaway_noncarrier_selfforce; float autocvar_g_keepaway_noncarrier_warn; +float autocvar_g_keepaway_score_bckill; +float autocvar_g_keepaway_score_killac; +float autocvar_g_keepaway_score_timepoints; +float autocvar_g_keepaway_score_timeinterval; float autocvar_g_keepawayball_damageforcescale; +float autocvar_g_keepawayball_effects; float autocvar_g_keepawayball_respawntime; float autocvar_g_keepawayball_trail_color; float autocvar_g_keyhunt_point_leadlimit; @@ -790,24 +875,8 @@ float autocvar_g_minstagib_ammo_drop; float autocvar_g_minstagib_extralives; float autocvar_g_minstagib_speed_highspeed; #define autocvar_g_mirrordamage cvar("g_mirrordamage") -float autocvar_g_monster_zombie_attack_run_damage; -float autocvar_g_monster_zombie_attack_run_delay; -float autocvar_g_monster_zombie_attack_run_force; -float autocvar_g_monster_zombie_attack_run_hitrange; -float autocvar_g_monster_zombie_attack_run_range; -float autocvar_g_monster_zombie_attack_stand_damage; -float autocvar_g_monster_zombie_attack_stand_delay; -float autocvar_g_monster_zombie_attack_stand_force; -float autocvar_g_monster_zombie_attack_stand_range; -float autocvar_g_monster_zombie_health; -float autocvar_g_monster_zombie_idle_timer_max; -float autocvar_g_monster_zombie_idle_timer_min; -float autocvar_g_monster_zombie_movespeed; -float autocvar_g_monster_zombie_respawntime; -float autocvar_g_monster_zombie_stopspeed; -float autocvar_g_monster_zombie_targetrange; -float autocvar_g_monster_zombie_turnspeed; -float autocvar_g_monsters; +#define autocvar_g_mirrordamage_virtual cvar("g_mirrordamage_virtual") + var float autocvar_g_movement_highspeed = 1; float autocvar_g_multijump; float autocvar_g_multijump_add; @@ -854,9 +923,8 @@ float autocvar_g_player_alpha; float autocvar_g_player_brightness; float autocvar_g_playerclip_collisions; string autocvar_g_playerstats_uri; -float autocvar_g_powerup_shield; -float autocvar_g_powerup_strength; -float autocvar_g_powerup_superhealth; +float autocvar_g_powerups; +float autocvar_g_projectiles_damage; float autocvar_g_projectiles_newton_style; float autocvar_g_projectiles_newton_style_2_maxfactor; float autocvar_g_projectiles_newton_style_2_minfactor; @@ -892,6 +960,7 @@ float autocvar_g_shootfromeye; string autocvar_g_shootfromfixedorigin; float autocvar_g_showweaponspawns; float autocvar_g_spawn_furthest; +float autocvar_g_spawn_useallspawns; float autocvar_g_spawnpoints_auto_move_out_of_solid; #define autocvar_g_spawnshieldtime cvar("g_spawnshieldtime") float autocvar_g_spawnsound; @@ -948,74 +1017,15 @@ float autocvar_g_turrets_unit_walker_std_rocket_speed; float autocvar_g_turrets_unit_walker_std_rocket_turnrate; float autocvar_g_turrets_unit_walker_std_rockets_range; float autocvar_g_turrets_unit_walker_std_rockets_range_min; +float autocvar_g_turrets_unit_walker_turn; +float autocvar_g_turrets_unit_walker_turn_walk; +float autocvar_g_turrets_unit_walker_turn_run; +float autocvar_g_turrets_unit_walker_turn_strafe; +float autocvar_g_turrets_unit_walker_turn_swim; float autocvar_g_use_ammunition; -float autocvar_g_vehicle_racer_afterburn_cost; -float autocvar_g_vehicle_racer_anglestabilizer; -float autocvar_g_vehicle_racer_downforce; -float autocvar_g_vehicle_racer_energy; -float autocvar_g_vehicle_racer_energy_usepause; -float autocvar_g_vehicle_racer_health; -float autocvar_g_vehicle_racer_laser_cost; -float autocvar_g_vehicle_racer_laser_damage; -float autocvar_g_vehicle_racer_laser_radius; -float autocvar_g_vehicle_racer_laser_refire; -float autocvar_g_vehicle_racer_laser_speed; -float autocvar_g_vehicle_racer_pitchspeed; -float autocvar_g_vehicle_racer_power_air; -float autocvar_g_vehicle_racer_power_min; -float autocvar_g_vehicle_racer_power_solid; -float autocvar_g_vehicle_racer_reload; -float autocvar_g_vehicle_racer_respawntime; -float autocvar_g_vehicle_racer_rocket_accel; -float autocvar_g_vehicle_racer_rocket_damage; -float autocvar_g_vehicle_racer_rocket_radius; -float autocvar_g_vehicle_racer_rocket_refire; -float autocvar_g_vehicle_racer_rocket_speed; -float autocvar_g_vehicle_racer_rocket_turnrate; -float autocvar_g_vehicle_racer_shield; -float autocvar_g_vehicle_racer_speed_afterburn; -float autocvar_g_vehicle_racer_speed_forward; -float autocvar_g_vehicle_racer_speed_strafe; -float autocvar_g_vehicle_racer_springlength; -float autocvar_g_vehicle_racer_turnroll; -float autocvar_g_vehicle_racer_turnspeed; -float autocvar_g_vehicle_raptor_reload; -float autocvar_g_vehicle_spiderbot_crush_dmg; -float autocvar_g_vehicle_spiderbot_crush_force; -float autocvar_g_vehicle_spiderbot_head_pitchlimit_down; -float autocvar_g_vehicle_spiderbot_head_pitchlimit_up; -float autocvar_g_vehicle_spiderbot_head_pitchspeed; -float autocvar_g_vehicle_spiderbot_head_turnlimit; -float autocvar_g_vehicle_spiderbot_head_turnspeed; -float autocvar_g_vehicle_spiderbot_health; -float autocvar_g_vehicle_spiderbot_minigun_cooldown; -float autocvar_g_vehicle_spiderbot_minigun_damage; -float autocvar_g_vehicle_spiderbot_minigun_heat; -float autocvar_g_vehicle_spiderbot_minigun_refire; -float autocvar_g_vehicle_spiderbot_minigun_spread; -float autocvar_g_vehicle_spiderbot_movement_inertia; -float autocvar_g_vehicle_spiderbot_respawntime; -float autocvar_g_vehicle_spiderbot_rocket_damage; -float autocvar_g_vehicle_spiderbot_rocket_edgedamage; -float autocvar_g_vehicle_spiderbot_rocket_force; -float autocvar_g_vehicle_spiderbot_rocket_health; -float autocvar_g_vehicle_spiderbot_rocket_lifetime; -float autocvar_g_vehicle_spiderbot_rocket_noise; -float autocvar_g_vehicle_spiderbot_rocket_radius; -float autocvar_g_vehicle_spiderbot_rocket_refire; -float autocvar_g_vehicle_spiderbot_rocket_reload; -float autocvar_g_vehicle_spiderbot_rocket_speed; -float autocvar_g_vehicle_spiderbot_rocket_turnrate; -float autocvar_g_vehicle_spiderbot_shield; -float autocvar_g_vehicle_spiderbot_speed_stop; -float autocvar_g_vehicle_spiderbot_speed_strafe; -float autocvar_g_vehicle_spiderbot_speed_walk; -float autocvar_g_vehicle_spiderbot_turnspeed; float autocvar_g_waypointeditor; +float autocvar_g_waypointeditor_auto; float autocvar_g_waypoints_for_items; -float autocvar_g_waypointsprite_deadlifetime; -float autocvar_g_waypointsprite_deployed_lifetime; -float autocvar_g_waypointsprite_limitedrange; float autocvar_g_weapon_charge_colormod_blue_full; float autocvar_g_weapon_charge_colormod_blue_half; float autocvar_g_weapon_charge_colormod_green_full; @@ -1027,7 +1037,6 @@ float autocvar_g_weapon_charge_colormod_red_half; float autocvar_g_weapon_throwable; #define autocvar_g_weaponarena cvar_string("g_weaponarena") string autocvar_g_xonoticversion; -float autocvar_gamecfg; float autocvar_gameversion; float autocvar_gameversion_min; float autocvar_gameversion_max; @@ -1045,17 +1054,18 @@ float autocvar_quit_when_empty; float autocvar_r_showbboxes; float autocvar_rescan_pending; float autocvar_samelevel; +string autocvar_sessionid; #define autocvar_skill cvar("skill") float autocvar_skill_auto; #define autocvar_slowmo cvar("slowmo") float autocvar_snd_soundradius; float autocvar_spawn_debug; -float autocvar_spawn_debugview; float autocvar_speedmeter; float autocvar_sv_accelerate; var float autocvar_sv_accuracy_data_share = 1; string autocvar_sv_adminnick; float autocvar_sv_airaccel_qw; +float autocvar_sv_airaccel_qw_stretchfactor; float autocvar_sv_airaccel_sideways_friction; float autocvar_sv_airaccelerate; float autocvar_sv_aircontrol; @@ -1065,9 +1075,10 @@ float autocvar_sv_airspeedlimit_nonqw; float autocvar_sv_airstopaccelerate; float autocvar_sv_airstrafeaccel_qw; float autocvar_sv_airstrafeaccelerate; -float autocvar_sv_allow_shownames; float autocvar_sv_autoscreenshot; float autocvar_sv_cheats; +float autocvar_sv_clientcommand_antispam_time; +float autocvar_sv_clientcommand_antispam_count; float autocvar_sv_curl_serverpackages_auto; float autocvar_sv_db_saveasdump; float autocvar_sv_defaultcharacter; @@ -1094,15 +1105,14 @@ float autocvar_sv_eventlog_files_counter; string autocvar_sv_eventlog_files_nameprefix; string autocvar_sv_eventlog_files_namesuffix; float autocvar_sv_eventlog_files_timestamps; -float autocvar_sv_fragmessage_information_handicap; -float autocvar_sv_fragmessage_information_ping; -float autocvar_sv_fragmessage_information_stats; -float autocvar_sv_fragmessage_information_typefrag; +float autocvar_sv_fraginfo; +float autocvar_sv_fraginfo_handicap; +float autocvar_sv_fraginfo_ping; +float autocvar_sv_fraginfo_stats; float autocvar_sv_friction; float autocvar_sv_friction_on_land; float autocvar_sv_gameplayfix_q2airaccelerate; #define autocvar_sv_gravity cvar("sv_gravity") -float autocvar_sv_hitsound_antispam_time; string autocvar_sv_intermission_cdtrack; string autocvar_sv_jumpspeedcap_max; float autocvar_sv_jumpspeedcap_max_disable_on_ramps; @@ -1117,23 +1127,17 @@ float autocvar_sv_maxairspeed; float autocvar_sv_maxairstrafespeed; float autocvar_sv_maxspeed; string autocvar_sv_motd; -string autocvar_sv_player_crouch_maxs; -string autocvar_sv_player_crouch_mins; -string autocvar_sv_player_crouch_viewoffset; -string autocvar_sv_player_headsize; -string autocvar_sv_player_maxs; -string autocvar_sv_player_mins; -string autocvar_sv_player_viewoffset; +float autocvar_sv_player_jumpanim_minfall; float autocvar_sv_precacheplayermodels; float autocvar_sv_precacheweapons; float autocvar_sv_q3acompat_machineshotgunswap; -float autocvar_sv_qcweaponanimation; float autocvar_sv_ready_restart; float autocvar_sv_ready_restart_after_countdown; float autocvar_sv_ready_restart_repeatable; float autocvar_sv_servermodelsonly; float autocvar_sv_spectate; float autocvar_sv_spectator_speed_multiplier; +float autocvar_sv_status_privacy; float autocvar_sv_stepheight; float autocvar_sv_stopspeed; float autocvar_sv_strengthsound_antispam_refire_threshold; @@ -1148,13 +1152,16 @@ float autocvar_sv_vote_call; float autocvar_sv_vote_change; string autocvar_sv_vote_commands; float autocvar_sv_vote_majority_factor; +float autocvar_sv_vote_majority_factor_of_voted; float autocvar_sv_vote_master; +float autocvar_sv_vote_master_callable; string autocvar_sv_vote_master_commands; string autocvar_sv_vote_master_password; +float autocvar_sv_vote_master_playerlimit; +float autocvar_sv_vote_no_stops_vote; float autocvar_sv_vote_nospectators; string autocvar_sv_vote_only_commands; float autocvar_sv_vote_override_mostrecent; -float autocvar_sv_vote_simple_majority_factor; float autocvar_sv_vote_singlecount; float autocvar_sv_vote_stop; float autocvar_sv_vote_timeout; @@ -1164,16 +1171,42 @@ float autocvar_sv_warsowbunny_airforwardaccel; float autocvar_sv_warsowbunny_backtosideratio; float autocvar_sv_warsowbunny_topspeed; float autocvar_sv_warsowbunny_turnaccel; -string autocvar_sv_weaponstats_damagefile; -string autocvar_sv_weaponstats_killfile; +float autocvar_sv_waypointsprite_deadlifetime; +float autocvar_sv_waypointsprite_deployed_lifetime; +float autocvar_sv_waypointsprite_limitedrange; +string autocvar_sv_weaponstats_file; +float autocvar_sv_gibhealth; float autocvar_sys_ticrate; float autocvar_teamplay_lockonrestart; float autocvar_teamplay_mode; #define autocvar_timelimit cvar("timelimit") #define autocvar_timelimit_override cvar("timelimit_override") +float autocvar_timelimit_increment; +float autocvar_timelimit_decrement; +float autocvar_timelimit_min; +float autocvar_timelimit_max; float autocvar_timelimit_overtime; float autocvar_timelimit_overtimes; float autocvar_timelimit_suddendeath; #define autocvar_utf8_enable cvar("utf8_enable") float autocvar_waypoint_benchmark; float autocvar_welcome_message_time; +float autocvar_sv_gameplayfix_gravityunaffectedbyticrate; +float autocvar_g_trueaim_minrange; +float autocvar_g_debug_defaultsounds; +float autocvar_g_loituma; +float autocvar_g_grab_range; +float autocvar_g_sandbox_info; +float autocvar_g_sandbox_readonly; +string autocvar_g_sandbox_storage_name; +float autocvar_g_sandbox_storage_autosave; +float autocvar_g_sandbox_storage_autoload; +float autocvar_g_sandbox_editor_flood; +float autocvar_g_sandbox_editor_maxobjects; +float autocvar_g_sandbox_editor_free; +float autocvar_g_sandbox_editor_distance_spawn; +float autocvar_g_sandbox_editor_distance_edit; +float autocvar_g_sandbox_object_scale_min; +float autocvar_g_sandbox_object_scale_max; +float autocvar_g_sandbox_object_material_velocity_min; +float autocvar_g_sandbox_object_material_velocity_factor; diff --git a/qcsrc/server/bot/aim.qc b/qcsrc/server/bot/aim.qc index 1911daf9e6..3bff21ecf0 100644 --- a/qcsrc/server/bot/aim.qc +++ b/qcsrc/server/bot/aim.qc @@ -1,12 +1,13 @@ +entity ka_ball; // traces multiple trajectories to find one that will impact the target // 'end' vector is the place it aims for, // returns TRUE only if it hit targ (don't target non-solid entities) float findtrajectorywithleading(vector org, vector m1, vector m2, entity targ, float shotspeed, float shotspeedupward, float maxtime, float shotdelay, entity ignore) { - local float c, savesolid, shottime; - local vector dir, end, v; + float c, savesolid, shottime; + vector dir, end, v, o; if (shotspeed < 1) return FALSE; // could cause division by zero if calculated if (targ.solid < SOLID_BBOX) // SOLID_NOT and SOLID_TRIGGER @@ -17,9 +18,10 @@ float findtrajectorywithleading(vector org, vector m1, vector m2, entity targ, f setsize(tracetossent, m1, m2); savesolid = targ.solid; targ.solid = SOLID_NOT; - shottime = ((vlen(targ.origin - org) / shotspeed) + shotdelay); - v = targ.velocity * shottime + targ.origin; - tracebox(targ.origin, targ.mins, targ.maxs, v, FALSE, targ); + o = (targ.absmin + targ.absmax) * 0.5; + shottime = ((vlen(o - org) / shotspeed) + shotdelay); + v = targ.velocity * shottime + o; + tracebox(o, targ.mins, targ.maxs, v, FALSE, targ); v = trace_endpos; end = v + (targ.mins + targ.maxs) * 0.5; if ((vlen(end - org) / shotspeed + 0.2) > maxtime) @@ -76,7 +78,7 @@ float findtrajectorywithleading(vector org, vector m1, vector m2, entity targ, f // leave a valid one even if it won't reach findtrajectory_velocity = normalize(end - org) * shotspeed + shotspeedupward * '0 0 1'; return FALSE; -}; +} void lag_update() { @@ -85,7 +87,7 @@ void lag_update() if (self.lag3_time) if (time > self.lag3_time) {self.lag_func(self.lag3_time, self.lag3_float1, self.lag3_float2, self.lag3_entity1, self.lag3_vec1, self.lag3_vec2, self.lag3_vec3, self.lag3_vec4);self.lag3_time = 0;} if (self.lag4_time) if (time > self.lag4_time) {self.lag_func(self.lag4_time, self.lag4_float1, self.lag4_float2, self.lag4_entity1, self.lag4_vec1, self.lag4_vec2, self.lag4_vec3, self.lag4_vec4);self.lag4_time = 0;} if (self.lag5_time) if (time > self.lag5_time) {self.lag_func(self.lag5_time, self.lag5_float1, self.lag5_float2, self.lag5_entity1, self.lag5_vec1, self.lag5_vec2, self.lag5_vec3, self.lag5_vec4);self.lag5_time = 0;} -}; +} float lag_additem(float t, float f1, float f2, entity e1, vector v1, vector v2, vector v3, vector v4) { @@ -96,7 +98,7 @@ float lag_additem(float t, float f1, float f2, entity e1, vector v1, vector v2, if (self.lag5_time == 0) {self.lag5_time = t;self.lag5_float1 = f1;self.lag5_float2 = f2;self.lag5_entity1 = e1;self.lag5_vec1 = v1;self.lag5_vec2 = v2;self.lag5_vec3 = v3;self.lag5_vec4 = v4;return TRUE;} // no room for it (what is the best thing to do here??) return FALSE; -}; +} float bot_shouldattack(entity e) { @@ -104,7 +106,7 @@ float bot_shouldattack(entity e) { if (e == self) return FALSE; - if (teams_matter) + if (teamplay) if (e.team != 0) return FALSE; } @@ -113,7 +115,13 @@ float bot_shouldattack(entity e) if(e.freezetag_frozen) return FALSE; - if(teams_matter) + // If neither player has ball then don't attack unless the ball is on the + // ground. + if (g_keepaway) + if (!e.ballcarried && !self.ballcarried && ka_ball.owner) + return FALSE; + + if(teamplay) { if(e.team==0) return FALSE; @@ -134,7 +142,7 @@ float bot_shouldattack(entity e) if(e.flags & FL_NOTARGET) return FALSE; return TRUE; -}; +} void bot_lagfunc(float t, float f1, float f2, entity e1, vector v1, vector v2, vector v3, vector v4) { @@ -157,12 +165,12 @@ void bot_lagfunc(float t, float f1, float f2, entity e1, vector v1, vector v2, v self.bot_canfire = (random() < 0.95); else self.bot_canfire = 1; -}; +} float bot_aimdir(vector v, float maxfiredeviation) { - local float dist, delta_t, blend; - local vector desiredang, diffang; + float dist, delta_t, blend; + vector desiredang, diffang; //dprint("aim ", self.netname, ": old:", vtos(self.v_angle)); // make sure v_angle is sane first @@ -263,7 +271,7 @@ float bot_aimdir(vector v, float maxfiredeviation) //diffang = diffang + randomvec() * (dist * 0.05 * (3.5 - bound(0, skill, 3))); // turn - local float r, fixedrate, blendrate; + float r, fixedrate, blendrate; fixedrate = autocvar_bot_ai_aimskill_fixedrate / bound(1,dist,1000); blendrate = autocvar_bot_ai_aimskill_blendrate; r = max(fixedrate, blendrate); @@ -302,18 +310,18 @@ float bot_aimdir(vector v, float maxfiredeviation) //dprint(" diff:", vtos(diffang), "\n"); return self.bot_canfire && (time < self.bot_firetimer); -}; +} vector bot_shotlead(vector targorigin, vector targvelocity, float shotspeed, float shotdelay) { // Try to add code here that predicts gravity effect here, no clue HOW to though ... well not yet atleast... return targorigin + targvelocity * (shotdelay + vlen(targorigin - shotorg) / shotspeed); -}; +} float bot_aim(float shotspeed, float shotspeedupward, float maxshottime, float applygravity) { - local float f, r; - local vector v; + float f, r, hf, distanceratio; + vector v; /* eprint(self); dprint("bot_aim(", ftos(shotspeed)); @@ -322,6 +330,10 @@ float bot_aim(float shotspeed, float shotspeedupward, float maxshottime, float a dprint(", ", ftos(applygravity)); dprint(");\n"); */ + + hf = self.dphitcontentsmask; + self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE; + shotspeed *= g_weaponspeedfactor; shotspeedupward *= g_weaponspeedfactor; if (!shotspeed) @@ -338,33 +350,41 @@ float bot_aim(float shotspeed, float shotspeedupward, float maxshottime, float a shotorg = self.origin + self.view_ofs; shotdir = v_forward; v = bot_shotlead(self.bot_aimtargorigin, self.bot_aimtargvelocity, shotspeed, self.bot_aimlatency); - local float distanceratio; - distanceratio =sqrt(bound(0,skill,10000))*0.3*(vlen(v-shotorg)-100)/autocvar_bot_ai_aimskill_firetolerance_distdegrees; + distanceratio = sqrt(bound(0,skill,10000))*0.3*(vlen(v-shotorg)-100)/autocvar_bot_ai_aimskill_firetolerance_distdegrees; distanceratio = bound(0,distanceratio,1); r = (autocvar_bot_ai_aimskill_firetolerance_maxdegrees-autocvar_bot_ai_aimskill_firetolerance_mindegrees) * (1-distanceratio) + autocvar_bot_ai_aimskill_firetolerance_mindegrees; if (applygravity && self.bot_aimtarg) { if (!findtrajectorywithleading(shotorg, '0 0 0', '0 0 0', self.bot_aimtarg, shotspeed, shotspeedupward, maxshottime, 0, self)) + { + self.dphitcontentsmask = hf; return FALSE; + } + f = bot_aimdir(findtrajectory_velocity - shotspeedupward * '0 0 1', r); } else { f = bot_aimdir(v - shotorg, r); //dprint("AIM: ");dprint(vtos(self.bot_aimtargorigin));dprint(" + ");dprint(vtos(self.bot_aimtargvelocity));dprint(" * ");dprint(ftos(self.bot_aimlatency + vlen(self.bot_aimtargorigin - shotorg) / shotspeed));dprint(" = ");dprint(vtos(v));dprint(" : aimdir = ");dprint(vtos(normalize(v - shotorg)));dprint(" : ");dprint(vtos(shotdir));dprint("\n"); - traceline(shotorg, shotorg + shotdir * 10000, FALSE, self); - if (trace_ent.takedamage) - if (trace_fraction < 1) - if (!bot_shouldattack(trace_ent)) - return FALSE; + //traceline(shotorg, shotorg + shotdir * 10000, FALSE, self); + //if (trace_ent.takedamage) + //if (trace_fraction < 1) + //if (!bot_shouldattack(trace_ent)) + // return FALSE; traceline(shotorg, self.bot_aimtargorigin, FALSE, self); if (trace_fraction < 1) if (trace_ent != self.enemy) if (!bot_shouldattack(trace_ent)) + { + self.dphitcontentsmask = hf; return FALSE; + } } - if (r > maxshottime * shotspeed) - return FALSE; - return f; -}; + + //if (r > maxshottime * shotspeed) + // return FALSE; + self.dphitcontentsmask = hf; + return TRUE; +} diff --git a/qcsrc/server/bot/bot.qc b/qcsrc/server/bot/bot.qc index 581e3f0c75..039e21daed 100644 --- a/qcsrc/server/bot/bot.qc +++ b/qcsrc/server/bot/bot.qc @@ -12,7 +12,7 @@ entity bot_spawn() { - local entity oldself, bot; + entity oldself, bot; bot = spawnclient(); if (bot) { @@ -25,7 +25,7 @@ entity bot_spawn() self = oldself; } return bot; -}; +} void bot_think() { @@ -98,10 +98,12 @@ void bot_think() self.bot_strategytime = 0; } } + else if(self.aistatus & AI_STATUS_STUCK) + navigation_unstuck(); // now call the current bot AI (havocbot for example) self.bot_ai(); -}; +} void bot_setnameandstuff() { @@ -233,11 +235,11 @@ void bot_setnameandstuff() self.cvar_cl_accuracy_data_share = 1; // share the bots weapon accuracy data with the world self.cvar_cl_accuracy_data_receive = 0; // don't receive any weapon accuracy data -}; +} void bot_custom_weapon_priority_setup() { - local float tokens, i, c, w; + float tokens, i, c, w; bot_custom_weapon = FALSE; @@ -310,11 +312,11 @@ void bot_custom_weapon_priority_setup() bot_weapons_close[c] = -1; bot_custom_weapon = TRUE; -}; +} void bot_endgame() { - local entity e; + entity e; //dprint("bot_endgame\n"); e = bot_list; while (e) @@ -323,12 +325,12 @@ void bot_endgame() e = e.nextbot; } // if dynamic waypoints are ever implemented, save them here -}; +} void bot_relinkplayerlist() { - local entity e; - local entity prevbot; + entity e; + entity prevbot; player_count = 0; currentbots = 0; player_list = e = findchainflags(flags, FL_CLIENT); @@ -355,7 +357,7 @@ void bot_relinkplayerlist() dprint(strcat("relink: ", ftos(currentbots), " bots seen.\n")); bot_strategytoken = bot_list; bot_strategytoken_taken = TRUE; -}; +} void bot_clientdisconnect() { @@ -373,7 +375,10 @@ void bot_clientdisconnect() self.netname_freeme = string_null; self.playermodel_freeme = string_null; self.playerskin_freeme = string_null; - remove(self.bot_cmd_current); + if(self.bot_cmd_current) + remove(self.bot_cmd_current); + if(bot_waypoint_queue_owner==self) + bot_waypoint_queue_owner = world; } void bot_clientconnect() @@ -401,12 +406,12 @@ void bot_clientconnect() JoinBestTeam(self, FALSE, TRUE); havocbot_setupbot(); -}; +} void bot_removefromlargestteam() { - local float besttime, bestcount, thiscount; - local entity best, head; + float besttime, bestcount, thiscount; + entity best, head; CheckAllowedTeams(world); GetTeamCounts(world); head = findchainfloat(isbot, TRUE); @@ -442,14 +447,14 @@ void bot_removefromlargestteam() } currentbots = currentbots - 1; dropclient(best); -}; +} void bot_removenewest() { - local float besttime; - local entity best, head; + float besttime; + entity best, head; - if(teams_matter) + if(teamplay) { bot_removefromlargestteam(); return; @@ -471,7 +476,7 @@ void bot_removenewest() } currentbots = currentbots - 1; dropclient(best); -}; +} void autoskill(float factor) { @@ -525,28 +530,18 @@ void autoskill(float factor) head.totalfrags_lastcheck = head.totalfrags; } -void bot_serverframe() +void bot_calculate_stepheightvec(void) { - float realplayers, bots, activerealplayers; - entity head; - - if (intermission_running) - return; - - if (time < 2) - return; - stepheightvec = autocvar_sv_stepheight * '0 0 1'; - bot_navigation_movemode = ((autocvar_bot_navigation_ignoreplayers) ? MOVE_NOMONSTERS : MOVE_NORMAL); + jumpstepheightvec = stepheightvec + + ((autocvar_sv_jumpvelocity * autocvar_sv_jumpvelocity) / (2 * autocvar_sv_gravity)) * '0 0 0.85'; + // 0.75 factor is for safety to make the jumps easy +} - if(time > autoskill_nextthink) - { - float a; - a = autocvar_skill_auto; - if(a) - autoskill(a); - autoskill_nextthink = time + 5; - } +float bot_fixcount() +{ + entity head; + float realplayers, bots, activerealplayers; activerealplayers = 0; realplayers = 0; @@ -563,7 +558,7 @@ void bot_serverframe() // But don't remove bots immediately on level change, as the real players // usually haven't rejoined yet bots_would_leave = FALSE; - if (teams_matter && autocvar_bot_vs_human && (c3==-1 && c4==-1)) + if (teamplay && autocvar_bot_vs_human && (c3==-1 && c4==-1)) bots = min(ceil(fabs(autocvar_bot_vs_human) * activerealplayers), maxclients - realplayers); else if ((realplayers || autocvar_bot_join_empty || (currentbots > 0 && time < 5))) { @@ -585,8 +580,6 @@ void bot_serverframe() bots = 0; } - bot_ignore_bots = autocvar_bot_ignore_bots; - // only add one bot per frame to avoid utter chaos if(time > botframe_nextthink) { @@ -596,21 +589,51 @@ void bot_serverframe() if (bot_spawn() == world) { bprint("Can not add bot, server full.\n"); - botframe_nextthink = time + 10; - break; + return FALSE; } } while (currentbots > bots) bot_removenewest(); } + return TRUE; +} + +void bot_serverframe() +{ + if (intermission_running) + return; + + if (time < 2) + return; + + bot_calculate_stepheightvec(); + bot_navigation_movemode = ((autocvar_bot_navigation_ignoreplayers) ? MOVE_NOMONSTERS : MOVE_NORMAL); + + if(time > autoskill_nextthink) + { + float a; + a = autocvar_skill_auto; + if(a) + autoskill(a); + autoskill_nextthink = time + 5; + } + + if(time > botframe_nextthink) + { + if(!bot_fixcount()) + botframe_nextthink = time + 10; + } + + bot_ignore_bots = autocvar_bot_ignore_bots; + if(botframe_spawnedwaypoints) { if(autocvar_waypoint_benchmark) localcmd("quit\n"); } - if (currentbots > 0 || autocvar_g_waypointeditor) + if (currentbots > 0 || autocvar_g_waypointeditor || autocvar_g_waypointeditor_auto) if (botframe_spawnedwaypoints) { if(botframe_cachedwaypointlinks) @@ -621,7 +644,7 @@ void bot_serverframe() else { // TODO: Make this check cleaner - local entity wp = findchain(classname, "waypoint"); + entity wp = findchain(classname, "waypoint"); if(time - wp.nextthink > 10) waypoint_save_links(); } @@ -650,7 +673,7 @@ void bot_serverframe() if (botframe_nextdangertime < time) { - local float interval; + float interval; interval = autocvar_bot_ai_dangerdetectioninterval; if (botframe_nextdangertime < time - interval * 1.5) botframe_nextdangertime = time; @@ -662,10 +685,13 @@ void bot_serverframe() if (autocvar_g_waypointeditor) botframe_showwaypointlinks(); + 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; } -}; +} diff --git a/qcsrc/server/bot/bot.qh b/qcsrc/server/bot/bot.qh index 9e6d447e6a..6823841d9b 100644 --- a/qcsrc/server/bot/bot.qh +++ b/qcsrc/server/bot/bot.qh @@ -2,17 +2,18 @@ * Globals and Fields */ -float AI_STATUS_ROAMING = 1; // Bot is just crawling the map. No enemies at sight -float AI_STATUS_ATTACKING = 2; // There are enemies at sight -float AI_STATUS_RUNNING = 4; // Bot is bunny hopping -float AI_STATUS_DANGER_AHEAD = 8; // There is lava/slime/trigger_hurt ahead -float AI_STATUS_OUT_JUMPPAD = 16; // Trying to get out of a "vertical" jump pad -float AI_STATUS_OUT_WATER = 32; // Trying to get out of water +float AI_STATUS_ROAMING = 1; // Bot is just crawling the map. No enemies at sight +float AI_STATUS_ATTACKING = 2; // There are enemies at sight +float AI_STATUS_RUNNING = 4; // Bot is bunny hopping +float AI_STATUS_DANGER_AHEAD = 8; // There is lava/slime/trigger_hurt ahead +float AI_STATUS_OUT_JUMPPAD = 16; // Trying to get out of a "vertical" jump pad +float AI_STATUS_OUT_WATER = 32; // Trying to get out of water float AI_STATUS_WAYPOINT_PERSONAL_LINKING = 64; // Waiting for the personal waypoint to be linked float AI_STATUS_WAYPOINT_PERSONAL_GOING = 128; // Going to a personal waypoint float AI_STATUS_WAYPOINT_PERSONAL_REACHED = 256; // Personal waypoint reached -float AI_STATUS_JETPACK_FLYING = 512; -float AI_STATUS_JETPACK_LANDING = 1024; +float AI_STATUS_JETPACK_FLYING = 512; +float AI_STATUS_JETPACK_LANDING = 1024; +float AI_STATUS_STUCK = 2048; // Cannot reach any goal .float isbot; // true if this client is actually a bot .float aistatus; @@ -113,3 +114,5 @@ void() havocbot_setupbot; float c1, c2, c3, c4; void CheckAllowedTeams(entity for_whom); void GetTeamCounts(entity other); float JoinBestTeam(entity pl, float only_return_best, float forcebestteam); + +void bot_calculate_stepheightvec(void); diff --git a/qcsrc/server/bot/havocbot/havocbot.qc b/qcsrc/server/bot/havocbot/havocbot.qc index c1785a8d27..3aefc45a75 100644 --- a/qcsrc/server/bot/havocbot/havocbot.qc +++ b/qcsrc/server/bot/havocbot/havocbot.qc @@ -2,6 +2,9 @@ #include "role_ctf.qc" #include "role_onslaught.qc" #include "role_keyhunt.qc" +#include "role_freezetag.qc" +#include "role_keepaway.qc" +#include "role_assault.qc" #include "roles.qc" void havocbot_ai() @@ -21,7 +24,8 @@ void havocbot_ai() } else { - self.havocbot_role(); + if not(self.jumppadcount) + self.havocbot_role(); } // TODO: tracewalk() should take care of this job (better path finding under water) @@ -31,8 +35,8 @@ void havocbot_ai() if(self.waterlevel==WATERLEVEL_SWIMMING || self.aistatus & AI_STATUS_OUT_WATER) { // Look for the closest waypoint out of water - local entity newgoal, head; - local float bestdistance, distance; + entity newgoal, head; + float bestdistance, distance; newgoal = world; bestdistance = 10000; @@ -115,9 +119,9 @@ void havocbot_ai() self.aistatus |= AI_STATUS_ROAMING; self.aistatus &~= AI_STATUS_ATTACKING; - local vector now,v,next;//,heading; - local float aimdistance,skillblend,distanceblend,blend; - next = now = self.goalcurrent.origin - (self.origin + self.view_ofs); + vector now,v,next;//,heading; + float aimdistance,skillblend,distanceblend,blend; + next = now = ( (self.goalcurrent.absmin + self.goalcurrent.absmax) * 0.5) - (self.origin + self.view_ofs); aimdistance = vlen(now); //heading = self.velocity; //dprint(self.goalstack01.classname,etos(self.goalstack01),"\n"); @@ -125,7 +129,7 @@ void havocbot_ai() self.goalstack01 != self && self.goalstack01 != world && self.aistatus & AI_STATUS_RUNNING == 0 && !(self.goalcurrent.wpflags & WAYPOINTFLAG_TELEPORT) ) - next = self.goalstack01.origin - (self.origin + self.view_ofs); + next = ((self.goalstack01.absmin + self.goalstack01.absmax) * 0.5) - (self.origin + self.view_ofs); skillblend=bound(0,(skill+self.bot_moveskill-2.5)*0.5,1); //lower skill player can't preturn distanceblend=bound(0,aimdistance/autocvar_bot_ai_keyboard_distance,1); @@ -144,12 +148,37 @@ void havocbot_ai() bot_aimdir(v, -1); } havocbot_movetogoal(); -}; + + // if the bot is not attacking, consider reloading weapons + if not(self.aistatus & AI_STATUS_ATTACKING) + { + float i; + entity e; + + // we are currently holding a weapon that's not fully loaded, reload it + if(skill >= 2) // bots can only reload the held weapon on purpose past this skill + if(self.clip_load < self.clip_size) + self.impulse = 20; // "press" the reload button, not sure if this is done right + + // if we're not reloading a weapon, switch to any weapon in our invnetory that's not fully loaded to reload it next + // the code above executes next frame, starting the reloading then + if(skill >= 5) // bots can only look for unloaded weapons past this skill + if(self.clip_load >= 0) // only if we're not reloading a weapon already + { + for(i = WEP_FIRST; i <= WEP_LAST; ++i) + { + e = get_weaponinfo(i); + if ((self.weapons & W_WeaponBit(i)) && (e.spawnflags & WEP_FLAG_RELOADABLE) && (self.weapon_load[i] < cvar(strcat("g_balance_", e.netname, "_reload_ammo")))) + self.switchweapon = i; + } + } + } +} void havocbot_keyboard_movement(vector destorg) { - local vector keyboard; - local float blend, maxspeed; + vector keyboard; + float blend, maxspeed; float sk; sk = skill + self.bot_moveskill; @@ -167,9 +196,9 @@ void havocbot_keyboard_movement(vector destorg) , time); keyboard = self.movement * (1.0 / maxspeed); - local float trigger, trigger1; + float trigger, trigger1; blend = bound(0,sk*0.1,1); - trigger = autocvar_bot_ai_keyboard_treshold; + trigger = autocvar_bot_ai_keyboard_threshold; trigger1 = 0 - trigger; // categorize forward movement @@ -219,20 +248,20 @@ void havocbot_keyboard_movement(vector destorg) blend = bound(0,vlen(destorg-self.origin)/autocvar_bot_ai_keyboard_distance,1); // When getting close move with 360 degree //dprint("movement ", vtos(self.movement), " keyboard ", vtos(keyboard), " blend ", ftos(blend), "\n"); self.movement = self.movement + (keyboard - self.movement) * blend; -}; +} void havocbot_bunnyhop(vector dir) { - local float bunnyhopdistance; - local vector deviation; - local float maxspeed; + float bunnyhopdistance; + vector deviation; + float maxspeed; + vector gco, gno; if(autocvar_g_midair) return; - // Don't jump when using some weapons + // Don't jump when attacking if(self.aistatus & AI_STATUS_ATTACKING) - if(self.weapon & WEP_CAMPINGRIFLE) return; if(self.goalcurrent.classname == "player") @@ -261,7 +290,8 @@ void havocbot_bunnyhop(vector dir) self.bot_timelastseengoal = 0; } - bunnyhopdistance = vlen(self.origin - self.goalcurrent.origin); + gco = (self.goalcurrent.absmin + self.goalcurrent.absmax) * 0.5; + bunnyhopdistance = vlen(self.origin - gco); // Run only to visible goals if(self.flags & FL_ONGROUND) @@ -276,7 +306,7 @@ void havocbot_bunnyhop(vector dir) // for a period of time if(time - self.bot_timelastseengoal > autocvar_bot_ai_bunnyhop_firstjumpdelay) { - local float checkdistance; + float checkdistance; checkdistance = TRUE; // don't run if it is too close @@ -294,18 +324,19 @@ void havocbot_bunnyhop(vector dir) if(self.aistatus & AI_STATUS_ROAMING) if(self.goalcurrent.classname=="waypoint") if not(self.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL) - if(fabs(self.goalcurrent.origin_z - self.origin_z) < self.maxs_z - self.mins_z) + if(fabs(gco_z - self.origin_z) < self.maxs_z - self.mins_z) if(self.goalstack01!=world) { - deviation = vectoangles(self.goalstack01.origin - self.origin) - vectoangles(self.goalcurrent.origin - self.origin); + gno = (self.goalstack01.absmin + self.goalstack01.absmax) * 0.5; + deviation = vectoangles(gno - self.origin) - vectoangles(gco - self.origin); while (deviation_y < -180) deviation_y = deviation_y + 360; while (deviation_y > 180) deviation_y = deviation_y - 360; if(fabs(deviation_y) < 20) - if(bunnyhopdistance < vlen(self.origin - self.goalstack01.origin)) - if(fabs(self.goalstack01.origin_z - self.goalcurrent.origin_z) < self.maxs_z - self.mins_z) + if(bunnyhopdistance < vlen(self.origin - gno)) + if(fabs(gno_z - gco_z) < self.maxs_z - self.mins_z) { - if(vlen(self.goalcurrent.origin - self.goalstack01.origin) > autocvar_bot_ai_bunnyhop_startdistance) + if(vlen(gco - gno) > autocvar_bot_ai_bunnyhop_startdistance) if(checkpvs(self.origin + self.view_ofs, self.goalstack01)) { checkdistance = FALSE; @@ -336,7 +367,9 @@ void havocbot_bunnyhop(vector dir) self.bot_timelastseengoal = 0; } +#if 0 // Release jump button + if(!cvar("sv_pogostick")) if(self.flags & FL_ONGROUND == 0) { if(self.velocity_z < 0 || vlen(self.velocity)<maxspeed) @@ -360,22 +393,24 @@ void havocbot_bunnyhop(vector dir) } } -}; +#endif +} void havocbot_movetogoal() { - local vector destorg; - local vector diff; - local vector dir; - local vector flatdir; - local vector m1; - local vector m2; - local vector evadeobstacle; - local vector evadelava; - local float s; - local float maxspeed; - //local float dist; - local vector dodge; + vector destorg; + vector diff; + vector dir; + vector flatdir; + vector m1; + vector m2; + vector evadeobstacle; + vector evadelava; + float s; + float maxspeed; + vector gco; + //float dist; + vector dodge; //if (self.goalentity) // te_lightning2(self, self.origin, (self.goalentity.absmin + self.goalentity.absmax) * 0.5); self.movement = '0 0 0'; @@ -387,10 +422,11 @@ void havocbot_movetogoal() if(self.goalcurrent==self.navigation_jetpack_goal) if(self.ammo_fuel) { - #ifdef DEBUG_BOT_GOALSTACK + if(autocvar_bot_debug_goalstack) + { debuggoalstack(); te_wizspike(self.navigation_jetpack_point); - #endif + } // Take off if not(self.aistatus & AI_STATUS_JETPACK_FLYING) @@ -411,7 +447,7 @@ void havocbot_movetogoal() float db, v, d; vector dxy; - dxy = self.origin - self.goalcurrent.origin; dxy_z = 0; + dxy = self.origin - ( ( self.goalcurrent.absmin + self.goalcurrent.absmax ) * 0.5 ); dxy_z = 0; d = vlen(dxy); v = vlen(self.velocity - self.velocity_z * '0 0 1'); db = (pow(v,2) / (autocvar_g_jetpack_acceleration_side * 2)) + 100; @@ -452,31 +488,22 @@ void havocbot_movetogoal() // Handling of jump pads if(self.jumppadcount) { - if(self.flags & FL_ONGROUND) - { - self.jumppadcount = FALSE; - if(self.aistatus & AI_STATUS_OUT_JUMPPAD) - self.aistatus &~= AI_STATUS_OUT_JUMPPAD; - } - - // If got stuck on the jump pad try to reach the farther visible item + // If got stuck on the jump pad try to reach the farthest visible waypoint if(self.aistatus & AI_STATUS_OUT_JUMPPAD) { if(fabs(self.velocity_z)<50) { - local entity head, newgoal; - local float distance, bestdistance; + entity head, newgoal; + float distance, bestdistance; - for (head = findchainfloat(bot_pickup, TRUE); head; head = head.chain) + for (head = findchain(classname, "waypoint"); head; head = head.chain) { - if(head.classname=="worldspawn") - continue; distance = vlen(head.origin - self.origin); if(distance>1000) continue; - traceline(self.origin + self.view_ofs , head.origin, TRUE, world); + traceline(self.origin + self.view_ofs , ( ( head.absmin + head.absmax ) * 0.5 ), TRUE, world); if(trace_fraction<1) continue; @@ -504,14 +531,25 @@ void havocbot_movetogoal() { if(self.velocity_z>0) { - local float threshold; + float threshold, sxy; + vector velxy = self.velocity; velxy_z = 0; + sxy = vlen(velxy); threshold = maxspeed * 0.2; - if(fabs(self.velocity_x) < threshold && fabs(self.velocity_y) < threshold) + if(sxy < threshold) + { + dprint("Warning: ", self.netname, " got stuck on a jumppad (velocity in xy is ", ftos(sxy), "), trying to get out of it now\n"); self.aistatus |= AI_STATUS_OUT_JUMPPAD; + } return; } + + // Don't chase players while using a jump pad + if(self.goalcurrent.classname=="player" || self.goalstack01.classname=="player") + return; } } + else if(self.aistatus & AI_STATUS_OUT_JUMPPAD) + self.aistatus &~= AI_STATUS_OUT_JUMPPAD; // If there is a trigger_hurt right below try to use the jetpack or make a rocketjump if(skill>6) @@ -537,10 +575,10 @@ void havocbot_movetogoal() if(self.goalcurrent==world) dir = v_forward; else - dir = normalize(self.goalcurrent.origin - self.origin); + dir = normalize(( ( self.goalcurrent.absmin + self.goalcurrent.absmax ) * 0.5 ) - self.origin); - local vector xyvelocity = self.velocity; xyvelocity_z = 0; - local float xyspeed = xyvelocity * dir; + vector xyvelocity = self.velocity; xyvelocity_z = 0; + float xyspeed = xyvelocity * dir; if(xyspeed < (maxspeed / 2)) { @@ -622,9 +660,9 @@ void havocbot_movetogoal() return; } -#ifdef DEBUG_BOT_GOALSTACK - debuggoalstack(); -#endif + + if(autocvar_bot_debug_goalstack) + debuggoalstack(); m1 = self.goalcurrent.origin + self.goalcurrent.mins; m2 = self.goalcurrent.origin + self.goalcurrent.maxs; @@ -637,6 +675,7 @@ void havocbot_movetogoal() dir = normalize(diff); flatdir = diff;flatdir_z = 0; flatdir = normalize(flatdir); + gco = (self.goalcurrent.absmin + self.goalcurrent.absmax) * 0.5; //if (self.bot_dodgevector_time < time) { @@ -654,7 +693,7 @@ void havocbot_movetogoal() } else { - if(self.velocity_z >= 0 && !(self.watertype == CONTENT_WATER && self.goalcurrent.origin_z < self.origin_z) && + if(self.velocity_z >= 0 && !(self.watertype == CONTENT_WATER && gco_z < self.origin_z) && ( !(self.waterlevel == WATERLEVEL_WETFEET && self.watertype == CONTENT_WATER) || self.aistatus & AI_STATUS_OUT_WATER)) self.BUTTON_JUMP = TRUE; else @@ -675,19 +714,19 @@ void havocbot_movetogoal() if (trace_plane_normal_z < 0.7) { s = trace_fraction; - tracebox(self.origin + '0 0 16', self.mins, self.maxs, self.origin + self.velocity * 0.2 + '0 0 16', FALSE, self); + tracebox(self.origin + stepheightvec, self.mins, self.maxs, self.origin + self.velocity * 0.2 + stepheightvec, FALSE, self); if (trace_fraction < s + 0.01) if (trace_plane_normal_z < 0.7) { s = trace_fraction; - tracebox(self.origin + '0 0 48', self.mins, self.maxs, self.origin + self.velocity * 0.2 + '0 0 48', FALSE, self); + tracebox(self.origin + jumpstepheightvec, self.mins, self.maxs, self.origin + self.velocity * 0.2 + jumpstepheightvec, FALSE, self); if (trace_fraction > s) self.BUTTON_JUMP = 1; } } // avoiding dangers and obstacles - local vector dst_ahead, dst_down; + vector dst_ahead, dst_down; makevectors(self.v_angle_y * '0 1 0'); dst_ahead = self.origin + self.view_ofs + (self.velocity * 0.4) + (v_forward * 32 * 3); dst_down = dst_ahead + '0 0 -1500'; @@ -726,7 +765,7 @@ void havocbot_movetogoal() // (only when the bot is on the ground or jumping intentionally) self.aistatus &~= AI_STATUS_DANGER_AHEAD; - if(trace_fraction == 1) + if(trace_fraction == 1 && self.jumppadcount == 0 && !self.goalcurrent.wphardwired ) if(self.flags & FL_ONGROUND || self.aistatus & AI_STATUS_RUNNING || self.BUTTON_JUMP == TRUE) { // Look downwards @@ -749,11 +788,9 @@ void havocbot_movetogoal() if(tracebox_hits_trigger_hurt(dst_ahead, self.mins, self.maxs, trace_endpos)) { // Remove dangerous dynamic goals from stack - if (self.goalcurrent.classname == "player" || self.goalcurrent.classname == "droppedweapon") - navigation_poproute(); - // try to stop - flatdir = '0 0 0'; - evadeobstacle = normalize(self.velocity) * -1; + dprint("bot ", self.netname, " avoided the goal ", self.goalcurrent.classname, " ", etos(self.goalcurrent), " because it led to a dangerous path; goal stack cleared\n"); + navigation_clearroute(); + return; } } } @@ -771,7 +808,7 @@ void havocbot_movetogoal() dodge = havocbot_dodge(); dodge = dodge * bound(0,0.5+(skill+self.bot_dodgeskill)*0.1,1); evadelava = evadelava * bound(1,3-(skill+self.bot_dodgeskill),3); //Noobs fear lava a lot and take more distance from it - traceline(self.origin, self.enemy.origin, TRUE, world); + traceline(self.origin, ( ( self.enemy.absmin + self.enemy.absmax ) * 0.5 ), TRUE, world); if(trace_ent.classname == "player") dir = dir * bound(0,(skill+self.bot_dodgeskill)/7,1); @@ -814,13 +851,13 @@ void havocbot_movetogoal() if ((dir * v_up) >= autocvar_sv_jumpvelocity*0.5 && (self.flags & FL_ONGROUND)) self.BUTTON_JUMP=1; if (((dodge * v_up) > 0) && random()*frametime >= 0.2*bound(0,(10-skill-self.bot_dodgeskill)*0.1,1)) self.BUTTON_JUMP=TRUE; if (((dodge * v_up) < 0) && random()*frametime >= 0.5*bound(0,(10-skill-self.bot_dodgeskill)*0.1,1)) self.havocbot_ducktime=time+0.3/bound(0.1,skill+self.bot_dodgeskill,10); -}; +} void havocbot_chooseenemy() { - local entity head, best, head2; - local float rating, bestrating, i, f; - local vector eye, v; + entity head, best, head2; + float rating, bestrating, i, hf; + vector eye, v; if (autocvar_bot_nofire || IS_INDEPENDENT_PLAYER(self)) { self.enemy = world; @@ -841,13 +878,13 @@ void havocbot_chooseenemy() // and not really really far away // and we're not severely injured // then keep tracking for a half second into the future - traceline(self.origin+self.view_ofs, self.enemy.origin+self.enemy.view_ofs*0.5,FALSE,world); + traceline(self.origin+self.view_ofs, ( self.enemy.absmin + self.enemy.absmax ) * 0.5,FALSE,world); if (trace_ent == self.enemy || trace_fraction == 1) - if (vlen(self.enemy.origin - self.origin) < 1000) + if (vlen((( self.enemy.absmin + self.enemy.absmax ) * 0.5) - self.origin) < 1000) if (self.health > 30) { // remain tracking him for a shot while (case he went after a small corner or pilar - self.havocbot_chooseenemy_finished = time + autocvar_bot_ai_enemydetectioninterval; + self.havocbot_chooseenemy_finished = time + 0.5; return; } // enemy isn't visible, or is far away, or we're injured severely @@ -864,7 +901,13 @@ void havocbot_chooseenemy() bestrating = 100000000; head = head2 = findchainfloat(bot_attack, TRUE); + // Backup hit flags + hf = self.dphitcontentsmask; + // Search for enemies, if no enemy can be seen directly try to look through transparent objects + + self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE; + for(;;) { while (head) @@ -887,30 +930,53 @@ void havocbot_chooseenemy() // I want to do a second scan if no enemy was found or I don't have weapons // TODO: Perform the scan when using the rifle (requires changes on the rifle code) - if(best || self.weapons) // || self.weapon == WEP_CAMPINGRIFLE + if(best || self.weapons) // || self.weapon == WEP_RIFLE break; if(i) break; // Set flags to see through transparent objects - f = self.dphitcontentsmask; - self.dphitcontentsmask = DPCONTENTS_OPAQUE; + self.dphitcontentsmask |= DPCONTENTS_OPAQUE; head = head2; ++i; } - // Restore hit flags if needed - if(i) - self.dphitcontentsmask = f; + // Restore hit flags + self.dphitcontentsmask = hf; self.enemy = best; self.havocbot_stickenemy = TRUE; -}; +} + +float havocbot_chooseweapon_checkreload(float new_weapon) +{ + // bots under this skill cannot find unloaded weapons to reload idly when not in combat, + // so skip this for them, or they'll never get to reload their weapons at all. + // this also allows bots under this skill to be more stupid, and reload more often during combat :) + if(skill < 5) + return FALSE; + + // if this weapon is scheduled for reloading, don't switch to it during combat + if (self.weapon_load[new_weapon] < 0) + { + float i, other_weapon_available; + for(i = WEP_FIRST; i <= WEP_LAST; ++i) + { + // if we are out of ammo for all other weapons, it's an emergency to switch to anything else + if (weapon_action(i, WR_CHECKAMMO1) + weapon_action(i, WR_CHECKAMMO2)) + other_weapon_available = TRUE; + } + if(other_weapon_available) + return TRUE; + } + + return FALSE; +} void havocbot_chooseweapon() { - local float i; + float i; // ;) if(g_weaponarena == WEPBIT_TUBA) @@ -940,32 +1006,11 @@ void havocbot_chooseweapon() if(i < 1) return; - // Workaround for rifle reloading (..) - if(self.weapon == WEP_CAMPINGRIFLE) - if(i < autocvar_g_balance_campingrifle_reloadtime + 1) - return; - - local float w; - local float rocket ; rocket =-1000; - local float nex ; nex =-1000; - local float hagar ; hagar =-1000; - local float grenade ; grenade =-1000; - local float mine ; mine =-1000; - local float electro ; electro =-1000; - local float crylink ; crylink =-1000; - local float uzi ; uzi =-1000; - local float shotgun ; shotgun =-1000; - local float campingrifle ; campingrifle =-1000; - local float laser ; laser =-1000; - local float minstanex ; minstanex =-1000; - local float bestscore; bestscore = 0; - local float bestweapon; bestweapon=self.switchweapon; - local float distance; distance=bound(10,vlen(self.origin-self.enemy.origin)-200,10000); - local float maxdelaytime=0.5; - local float spreadpenalty=10; + float w; + float distance; distance=bound(10,vlen(self.origin-self.enemy.origin)-200,10000); // Should it do a weapon combo? - local float af, ct, combo_time, combo; + float af, ct, combo_time, combo; af = ATTACK_FINISHED(self); ct = autocvar_bot_ai_weapon_combo_threshold; @@ -993,8 +1038,9 @@ void havocbot_chooseweapon() if ( distance > bot_distance_far ) { for(i=0; i < WEP_COUNT && bot_weapons_far[i] != -1 ; ++i){ w = bot_weapons_far[i]; - if ( client_hasweapon(self, w, TRUE, FALSE) ){ - if ( self.weapon == w && combo) + if ( client_hasweapon(self, w, TRUE, FALSE) ) + { + if ((self.weapon == w && combo) || havocbot_chooseweapon_checkreload(w)) continue; self.switchweapon = w; return; @@ -1006,8 +1052,9 @@ void havocbot_chooseweapon() if ( distance > bot_distance_close) { for(i=0; i < WEP_COUNT && bot_weapons_mid[i] != -1 ; ++i){ w = bot_weapons_mid[i]; - if ( client_hasweapon(self, w, TRUE, FALSE) ){ - if ( self.weapon == w && combo) + if ( client_hasweapon(self, w, TRUE, FALSE) ) + { + if ((self.weapon == w && combo) || havocbot_chooseweapon_checkreload(w)) continue; self.switchweapon = w; return; @@ -1018,19 +1065,20 @@ void havocbot_chooseweapon() // Choose weapons for close distance for(i=0; i < WEP_COUNT && bot_weapons_close[i] != -1 ; ++i){ w = bot_weapons_close[i]; - if ( client_hasweapon(self, w, TRUE, FALSE) ){ - if ( self.weapon == w && combo) + if ( client_hasweapon(self, w, TRUE, FALSE) ) + { + if ((self.weapon == w && combo) || havocbot_chooseweapon_checkreload(w)) continue; self.switchweapon = w; return; } } } -}; +} void havocbot_aim() { - local vector selfvel, enemyvel; + vector selfvel, enemyvel; // if(self.flags & FL_INWATER) // return; if (time < self.nextaim) @@ -1044,11 +1092,11 @@ void havocbot_aim() enemyvel = self.enemy.velocity; if (!self.enemy.waterlevel) enemyvel_z = 0; - lag_additem(time + self.ping, 0, 0, self.enemy, self.origin, selfvel, self.enemy.origin, enemyvel); + lag_additem(time + self.ping, 0, 0, self.enemy, self.origin, selfvel, (self.enemy.absmin + self.enemy.absmax) * 0.5, enemyvel); } else - lag_additem(time + self.ping, 0, 0, world, self.origin, selfvel, self.goalcurrent.origin, '0 0 0'); -}; + lag_additem(time + self.ping, 0, 0, world, self.origin, selfvel, ( self.goalcurrent.absmin + self.goalcurrent.absmax ) * 0.5, '0 0 0'); +} float havocbot_moveto_refresh_route() { @@ -1063,7 +1111,7 @@ float havocbot_moveto_refresh_route() float havocbot_moveto(vector pos) { - local entity wp; + entity wp; if(self.aistatus & AI_STATUS_WAYPOINT_PERSONAL_GOING) { @@ -1101,12 +1149,11 @@ float havocbot_moveto(vector pos) } } - #ifdef DEBUG_BOT_GOALSTACK + if(autocvar_bot_debug_goalstack) debuggoalstack(); - #endif // Heading - local vector dir = self.goalcurrent.origin - (self.origin + self.view_ofs); + vector dir = ( ( self.goalcurrent.absmin + self.goalcurrent.absmax ) * 0.5 ) - (self.origin + self.view_ofs); dir_z = 0; bot_aimdir(dir, -1); @@ -1197,10 +1244,10 @@ vector havocbot_dodge() { // LordHavoc: disabled because this is too expensive return '0 0 0'; - /* - local entity head; - local vector dodge, v, n; - local float danger, bestdanger, vl, d; +#if 0 + entity head; + vector dodge, v, n; + float danger, bestdanger, vl, d; dodge = '0 0 0'; bestdanger = -20; // check for dangerous objects near bot or approaching bot @@ -1242,5 +1289,5 @@ vector havocbot_dodge() head = head.chain; } return dodge; - */ -}; +#endif +} diff --git a/qcsrc/server/bot/havocbot/role_assault.qc b/qcsrc/server/bot/havocbot/role_assault.qc new file mode 100644 index 0000000000..4456802d5c --- /dev/null +++ b/qcsrc/server/bot/havocbot/role_assault.qc @@ -0,0 +1,205 @@ +#define HAVOCBOT_AST_ROLE_NONE 0 +#define HAVOCBOT_AST_ROLE_DEFENSE 2 +#define HAVOCBOT_AST_ROLE_OFFENSE 4 + +.float havocbot_role_flags; +.float havocbot_attack_time; + +.void() havocbot_role; +.void() havocbot_previous_role; + +void() havocbot_role_ast_defense; +void() havocbot_role_ast_offense; +.entity havocbot_ast_target; + +void(entity bot) havocbot_ast_reset_role; + +void(float ratingscale, vector org, float sradius) havocbot_goalrating_items; +void(float ratingscale, vector org, float sradius) havocbot_goalrating_enemyplayers; + +void havocbot_goalrating_ast_targets(float ratingscale) +{ + entity ad, best, wp, tod; + float radius, found, bestvalue; + vector p; + + ad = findchain(classname, "func_assault_destructible"); + + for (; ad; ad = ad.chain) + { + if (ad.target == "") + continue; + + if not(ad.bot_attack) + continue; + + found = FALSE; + for(tod = world; (tod = find(tod, targetname, ad.target)); ) + { + if(tod.classname == "target_objective_decrease") + { + if(tod.enemy.health > 0 && tod.enemy.health < ASSAULT_VALUE_INACTIVE) + { + // dprint(etos(ad),"\n"); + found = TRUE; + break; + } + } + } + + if(!found) + { + /// dprint("target not found\n"); + continue; + } + /// dprint("target #", etos(ad), " found\n"); + + + p = 0.5 * (ad.absmin + ad.absmax); + // dprint(vtos(ad.origin), " ", vtos(ad.absmin), " ", vtos(ad.absmax),"\n"); + // te_knightspike(p); + // te_lightning2(world, '0 0 0', p); + + // Find and rate waypoints around it + found = FALSE; + best = world; + bestvalue = 99999999999; + for(radius=0; radius<1500 && !found; radius+=500) + { + for(wp=findradius(p, radius); wp; wp=wp.chain) + { + if(!(wp.wpflags & WAYPOINTFLAG_GENERATED)) + if(wp.classname=="waypoint") + if(checkpvs(wp.origin, ad)) + { + found = TRUE; + if(wp.cnt<bestvalue) + { + best = wp; + bestvalue = wp.cnt; + } + } + } + } + + if(best) + { + /// dprint("waypoints around target were found\n"); + // te_lightning2(world, '0 0 0', best.origin); + // te_knightspike(best.origin); + + navigation_routerating(best, ratingscale, 4000); + best.cnt += 1; + + self.havocbot_attack_time = 0; + + if(checkpvs(self.view_ofs,ad)) + if(checkpvs(self.view_ofs,best)) + { + // dprint("increasing attack time for this target\n"); + self.havocbot_attack_time = time + 2; + } + } + } +} + +void havocbot_role_ast_offense() +{ + if(self.deadflag != DEAD_NO) + { + self.havocbot_attack_time = 0; + havocbot_ast_reset_role(self); + return; + } + + // Set the role timeout if necessary + if (!self.havocbot_role_timeout) + self.havocbot_role_timeout = time + 120; + + if (time > self.havocbot_role_timeout) + { + havocbot_ast_reset_role(self); + return; + } + + if(self.havocbot_attack_time>time) + return; + + if (self.bot_strategytime < time) + { + navigation_goalrating_start(); + havocbot_goalrating_enemyplayers(20000, self.origin, 650); + havocbot_goalrating_ast_targets(20000); + havocbot_goalrating_items(15000, self.origin, 10000); + navigation_goalrating_end(); + + self.bot_strategytime = time + autocvar_bot_ai_strategyinterval; + } +} + +void havocbot_role_ast_defense() +{ + if(self.deadflag != DEAD_NO) + { + self.havocbot_attack_time = 0; + havocbot_ast_reset_role(self); + return; + } + + // Set the role timeout if necessary + if (!self.havocbot_role_timeout) + self.havocbot_role_timeout = time + 120; + + if (time > self.havocbot_role_timeout) + { + havocbot_ast_reset_role(self); + return; + } + + if(self.havocbot_attack_time>time) + return; + + if (self.bot_strategytime < time) + { + navigation_goalrating_start(); + havocbot_goalrating_enemyplayers(20000, self.origin, 3000); + havocbot_goalrating_ast_targets(20000); + havocbot_goalrating_items(15000, self.origin, 10000); + navigation_goalrating_end(); + + self.bot_strategytime = time + autocvar_bot_ai_strategyinterval; + } +} + +void havocbot_role_ast_setrole(entity bot, float role) +{ + switch(role) + { + case HAVOCBOT_AST_ROLE_DEFENSE: + bot.havocbot_role = havocbot_role_ast_defense; + bot.havocbot_role_flags = HAVOCBOT_AST_ROLE_DEFENSE; + bot.havocbot_role_timeout = 0; + break; + case HAVOCBOT_AST_ROLE_OFFENSE: + bot.havocbot_role = havocbot_role_ast_offense; + bot.havocbot_role_flags = HAVOCBOT_AST_ROLE_OFFENSE; + bot.havocbot_role_timeout = 0; + break; + } +} + +void havocbot_ast_reset_role(entity bot) +{ + if(self.deadflag != DEAD_NO) + return; + + if(bot.team==assault_attacker_team) + havocbot_role_ast_setrole(bot, HAVOCBOT_AST_ROLE_OFFENSE); + else + havocbot_role_ast_setrole(bot, HAVOCBOT_AST_ROLE_DEFENSE); +} + +void havocbot_chooserole_ast() +{ + havocbot_ast_reset_role(self); +} diff --git a/qcsrc/server/bot/havocbot/role_ctf.qc b/qcsrc/server/bot/havocbot/role_ctf.qc index 0ec0abb3ce..74c611ea18 100644 --- a/qcsrc/server/bot/havocbot/role_ctf.qc +++ b/qcsrc/server/bot/havocbot/role_ctf.qc @@ -40,7 +40,7 @@ entity havocbot_ctf_find_flag(entity bot) f = f.ctf_worldflagnext; } return world; -}; +} entity havocbot_ctf_find_enemy_flag(entity bot) { @@ -53,11 +53,11 @@ entity havocbot_ctf_find_enemy_flag(entity bot) f = f.ctf_worldflagnext; } return world; -}; +} float havocbot_ctf_teamcount(entity bot, vector org, float radius) { - if not(teams_matter) + if not(teamplay) return 0; float c; @@ -73,11 +73,11 @@ float havocbot_ctf_teamcount(entity bot, vector org, float radius) } return c; -}; +} void havocbot_goalrating_ctf_ourflag(float ratingscale) { - local entity head; + entity head; head = ctf_worldflaglist; while (head) { @@ -87,11 +87,11 @@ void havocbot_goalrating_ctf_ourflag(float ratingscale) } if (head) navigation_routerating(head, ratingscale, 10000); -}; +} void havocbot_goalrating_ctf_ourbase(float ratingscale) { - local entity head; + entity head; head = ctf_worldflaglist; while (head) { @@ -103,11 +103,11 @@ void havocbot_goalrating_ctf_ourbase(float ratingscale) return; navigation_routerating(head.basewaypoint, ratingscale, 10000); -}; +} void havocbot_goalrating_ctf_enemyflag(float ratingscale) { - local entity head; + entity head; head = ctf_worldflaglist; while (head) { @@ -117,7 +117,7 @@ void havocbot_goalrating_ctf_enemyflag(float ratingscale) } if (head) navigation_routerating(head, ratingscale, 10000); -}; +} void havocbot_goalrating_ctf_enemybase(float ratingscale) { @@ -127,7 +127,7 @@ void havocbot_goalrating_ctf_enemybase(float ratingscale) return; } - local entity head; + entity head; head = havocbot_ctf_find_enemy_flag(self); @@ -135,23 +135,24 @@ void havocbot_goalrating_ctf_enemybase(float ratingscale) return; navigation_routerating(head.basewaypoint, ratingscale, 10000); -}; +} void havocbot_goalrating_ctf_ourstolenflag(float ratingscale) { - local entity mf; + entity mf; mf = havocbot_ctf_find_flag(self); if(mf.cnt == FLAG_BASE) return; - navigation_routerating(mf, ratingscale, 10000); -}; + if(mf.tag_entity) + navigation_routerating(mf.tag_entity, ratingscale, 10000); +} void havocbot_goalrating_ctf_droppedflags(float ratingscale, vector org, float radius) { - local entity head; + entity head; head = ctf_worldflaglist; while (head) { @@ -170,12 +171,12 @@ void havocbot_goalrating_ctf_droppedflags(float ratingscale, vector org, float r head = head.ctf_worldflagnext; } -}; +} void havocbot_goalrating_ctf_carrieritems(float ratingscale, vector org, float sradius) { - local entity head; - local float t; + entity head; + float t; head = findchainfloat(bot_pickup, TRUE); while (head) { @@ -191,7 +192,7 @@ void havocbot_goalrating_ctf_carrieritems(float ratingscale, vector org, float s } head = head.chain; } -}; +} void havocbot_role_ctf_setrole(entity bot, float role) { @@ -203,6 +204,7 @@ void havocbot_role_ctf_setrole(entity bot, float role) bot.havocbot_role = havocbot_role_ctf_carrier; bot.havocbot_role_timeout = 0; bot.havocbot_cantfindflag = time + 10; + bot.bot_strategytime = 0; break; case HAVOCBOT_CTF_ROLE_DEFENSE: dprint("defense"); @@ -224,16 +226,18 @@ void havocbot_role_ctf_setrole(entity bot, float role) bot.havocbot_previous_role = bot.havocbot_role; bot.havocbot_role = havocbot_role_ctf_retriever; bot.havocbot_role_timeout = time + 10; + bot.bot_strategytime = 0; break; case HAVOCBOT_CTF_ROLE_ESCORT: dprint("escort"); bot.havocbot_previous_role = bot.havocbot_role; bot.havocbot_role = havocbot_role_ctf_escort; bot.havocbot_role_timeout = time + 30; + bot.bot_strategytime = 0; break; } dprint("\n"); -}; +} void havocbot_role_ctf_carrier() { @@ -271,11 +275,11 @@ void havocbot_role_ctf_carrier() return; } } -}; +} void havocbot_role_ctf_escort() { - local entity mf, ef; + entity mf, ef; if(self.deadflag != DEAD_NO) { @@ -331,12 +335,12 @@ void havocbot_role_ctf_escort() havocbot_goalrating_items(10000, self.origin, 10000); navigation_goalrating_end(); } -}; +} void havocbot_role_ctf_offense() { - local entity mf, ef; - local vector pos; + entity mf, ef; + vector pos; if(self.deadflag != DEAD_NO) { @@ -412,12 +416,12 @@ void havocbot_role_ctf_offense() havocbot_goalrating_items(1000, self.origin, 10000); navigation_goalrating_end(); } -}; +} // Retriever (temporary role): void havocbot_role_ctf_retriever() { - local entity mf; + entity mf; if(self.deadflag != DEAD_NO) { @@ -450,7 +454,7 @@ void havocbot_role_ctf_retriever() if (self.bot_strategytime < time) { - local float radius; + float radius; radius = 10000; self.bot_strategytime = time + autocvar_bot_ai_strategyinterval; @@ -461,11 +465,11 @@ void havocbot_role_ctf_retriever() havocbot_goalrating_items(500, self.origin, radius); navigation_goalrating_end(); } -}; +} void havocbot_role_ctf_middle() { - local entity mf; + entity mf; if(self.deadflag != DEAD_NO) { @@ -497,7 +501,7 @@ void havocbot_role_ctf_middle() if (self.bot_strategytime < time) { - local vector org; + vector org; org = havocbot_ctf_middlepoint; org_z = self.origin_z; @@ -512,11 +516,11 @@ void havocbot_role_ctf_middle() havocbot_goalrating_ctf_enemybase(2500); navigation_goalrating_end(); } -}; +} void havocbot_role_ctf_defense() { - local entity mf; + entity mf; if(self.deadflag != DEAD_NO) { @@ -548,8 +552,8 @@ void havocbot_role_ctf_defense() } if (self.bot_strategytime < time) { - local float radius; - local vector org; + float radius; + vector org; org = mf.dropped_origin; radius = havocbot_ctf_middlepoint_radius; @@ -558,8 +562,8 @@ void havocbot_role_ctf_defense() navigation_goalrating_start(); // if enemies are closer to our base, go there - local entity head, closestplayer; - local float distance, bestdistance; + entity head, closestplayer; + float distance, bestdistance; distance = 10000; FOR_EACH_PLAYER(head) { @@ -587,7 +591,7 @@ void havocbot_role_ctf_defense() havocbot_goalrating_items(5000, self.origin, 10000); navigation_goalrating_end(); } -}; +} void havocbot_calculate_middlepoint() { @@ -606,13 +610,13 @@ void havocbot_calculate_middlepoint() } havocbot_ctf_middlepoint = p1 + ((p2-p1) * 0.5); havocbot_ctf_middlepoint_radius = vlen(p2-p1) * 0.5; -}; +} void havocbot_ctf_reset_role(entity bot) { - local float cdefense, cmiddle, coffense; - local entity mf, ef, head; - local float c; + float cdefense, cmiddle, coffense; + entity mf, ef, head; + float c; if(bot.deadflag != DEAD_NO) return; @@ -672,9 +676,9 @@ void havocbot_ctf_reset_role(entity bot) havocbot_role_ctf_setrole(bot, HAVOCBOT_CTF_ROLE_OFFENSE); else havocbot_role_ctf_setrole(bot, HAVOCBOT_CTF_ROLE_MIDDLE); -}; +} void havocbot_chooserole_ctf() { havocbot_ctf_reset_role(self); -}; +} diff --git a/qcsrc/server/bot/havocbot/role_freezetag.qc b/qcsrc/server/bot/havocbot/role_freezetag.qc new file mode 100644 index 0000000000..4e5669eb2e --- /dev/null +++ b/qcsrc/server/bot/havocbot/role_freezetag.qc @@ -0,0 +1,109 @@ +void() havocbot_role_ft_freeing; +void() havocbot_role_ft_offense; + +void havocbot_goalrating_freeplayers(float ratingscale, vector org, float sradius) +{ + entity head; + float distance; + + FOR_EACH_PLAYER(head) + { + if ((head != self) && (head.team == self.team)) + { + if (head.freezetag_frozen) + { + distance = vlen(head.origin - org); + if (distance > sradius) + continue; + navigation_routerating(head, ratingscale, 2000); + } + else + { + // If teamate is not frozen still seek them out as fight better + // in a group. + navigation_routerating(head, ratingscale/3, 2000); + } + } + } +} + +void havocbot_role_ft_offense() +{ + entity head; + float unfrozen; + + if(self.deadflag != DEAD_NO) + return; + + if (!self.havocbot_role_timeout) + self.havocbot_role_timeout = time + random() * 10 + 20; + + // Count how many players on team are unfrozen. + unfrozen = 0; + FOR_EACH_PLAYER(head) + { + if ((head.team == self.team) && (!head.freezetag_frozen)) + unfrozen++; + } + + // If only one left on team or if role has timed out then start trying to free players. + if (((unfrozen == 0) && (!self.freezetag_frozen)) || (time > self.havocbot_role_timeout)) + { + dprint("changing role to freeing\n"); + self.havocbot_role = havocbot_role_ft_freeing; + self.havocbot_role_timeout = 0; + return; + } + + if (time > self.bot_strategytime) + { + self.bot_strategytime = time + autocvar_bot_ai_strategyinterval; + + navigation_goalrating_start(); + havocbot_goalrating_items(10000, self.origin, 10000); + havocbot_goalrating_enemyplayers(20000, self.origin, 10000); + havocbot_goalrating_freeplayers(9000, self.origin, 10000); + //havocbot_goalrating_waypoints(1, self.origin, 1000); + navigation_goalrating_end(); + } +} + +void havocbot_role_ft_freeing() +{ + if(self.deadflag != DEAD_NO) + return; + + if (!self.havocbot_role_timeout) + self.havocbot_role_timeout = time + random() * 10 + 20; + + if (time > self.havocbot_role_timeout) + { + dprint("changing role to offense\n"); + self.havocbot_role = havocbot_role_ft_offense; + self.havocbot_role_timeout = 0; + return; + } + + if (time > self.bot_strategytime) + { + self.bot_strategytime = time + autocvar_bot_ai_strategyinterval; + + navigation_goalrating_start(); + havocbot_goalrating_items(8000, self.origin, 10000); + havocbot_goalrating_enemyplayers(10000, self.origin, 10000); + havocbot_goalrating_freeplayers(20000, self.origin, 10000); + //havocbot_goalrating_waypoints(1, self.origin, 1000); + navigation_goalrating_end(); + } +} + +void havocbot_chooserole_ft() +{ + if(self.deadflag != DEAD_NO) + return; + + if (random() < 0.5) + self.havocbot_role = havocbot_role_ft_freeing; + else + self.havocbot_role = havocbot_role_ft_offense; +} diff --git a/qcsrc/server/bot/havocbot/role_keepaway.qc b/qcsrc/server/bot/havocbot/role_keepaway.qc new file mode 100644 index 0000000000..ede6208a16 --- /dev/null +++ b/qcsrc/server/bot/havocbot/role_keepaway.qc @@ -0,0 +1,82 @@ +void() havocbot_role_ka_carrier; +void() havocbot_role_ka_collector; +void() havocbot_chooserole_ka; + +entity ka_ball; + +// Keepaway +// If you don't have the ball, get it; if you do, kill people. + +void havocbot_goalrating_ball(float ratingscale, vector org) +{ + float t; + entity ball_owner; + ball_owner = ka_ball.owner; + + if (ball_owner == self) + return; + + // If ball is carried by player then hunt them down. + if (ball_owner) + { + t = (self.health + self.armorvalue) / (ball_owner.health + ball_owner.armorvalue); + navigation_routerating(ball_owner, t * ratingscale, 2000); + } + + // Ball has been dropped so collect. + navigation_routerating(ka_ball, ratingscale, 2000); +} + +void havocbot_role_ka_carrier() +{ + if (self.deadflag != DEAD_NO) + return; + + if (time > self.bot_strategytime) + { + self.bot_strategytime = time + autocvar_bot_ai_strategyinterval; + + navigation_goalrating_start(); + havocbot_goalrating_items(10000, self.origin, 10000); + havocbot_goalrating_enemyplayers(20000, self.origin, 10000); + //havocbot_goalrating_waypoints(1, self.origin, 1000); + navigation_goalrating_end(); + } + + if (!self.ballcarried) + { + self.havocbot_role = havocbot_role_ka_collector; + self.bot_strategytime = 0; + } +} + +void havocbot_role_ka_collector() +{ + if (self.deadflag != DEAD_NO) + return; + + if (time > self.bot_strategytime) + { + self.bot_strategytime = time + autocvar_bot_ai_strategyinterval; + + navigation_goalrating_start(); + havocbot_goalrating_items(10000, self.origin, 10000); + havocbot_goalrating_enemyplayers(1000, self.origin, 10000); + havocbot_goalrating_ball(20000, self.origin); + navigation_goalrating_end(); + } + + if (self.ballcarried) + { + self.havocbot_role = havocbot_role_ka_carrier; + self.bot_strategytime = 0; + } +} + +void havocbot_chooserole_ka() +{ + if (self.ballcarried) + self.havocbot_role = havocbot_role_ka_carrier; + else + self.havocbot_role = havocbot_role_ka_collector; +} diff --git a/qcsrc/server/bot/havocbot/role_keyhunt.qc b/qcsrc/server/bot/havocbot/role_keyhunt.qc index 8e30b37b5c..3b641d9ce7 100644 --- a/qcsrc/server/bot/havocbot/role_keyhunt.qc +++ b/qcsrc/server/bot/havocbot/role_keyhunt.qc @@ -8,7 +8,7 @@ entity kh_worldkeylist; void havocbot_goalrating_kh(float ratingscale_team, float ratingscale_dropped, float ratingscale_enemy) { - local entity head; + entity head; for (head = kh_worldkeylist; head; head = head.kh_worldkeynext) { if(head.owner == self) @@ -33,7 +33,7 @@ void havocbot_goalrating_kh(float ratingscale_team, float ratingscale_dropped, f } havocbot_goalrating_items(1, self.origin, 10000); -}; +} void havocbot_role_kh_carrier() { @@ -101,7 +101,7 @@ void havocbot_role_kh_defense() navigation_goalrating_end(); } -}; +} void havocbot_role_kh_offense() { @@ -143,7 +143,7 @@ void havocbot_role_kh_offense() navigation_goalrating_end(); } -}; +} void havocbot_role_kh_freelancer() { @@ -193,11 +193,11 @@ void havocbot_role_kh_freelancer() navigation_goalrating_end(); } -}; +} void havocbot_chooserole_kh() { - local float r; + float r; if(self.deadflag != DEAD_NO) return; @@ -209,4 +209,4 @@ void havocbot_chooserole_kh() self.havocbot_role = havocbot_role_kh_defense; else self.havocbot_role = havocbot_role_kh_freelancer; -}; +} diff --git a/qcsrc/server/bot/havocbot/role_onslaught.qc b/qcsrc/server/bot/havocbot/role_onslaught.qc index bc84340287..3ae7379be7 100644 --- a/qcsrc/server/bot/havocbot/role_onslaught.qc +++ b/qcsrc/server/bot/havocbot/role_onslaught.qc @@ -27,8 +27,8 @@ void(float ratingscale, vector org, float sradius) havocbot_goalrating_enemyplay void havocbot_goalrating_ons_offenseitems(float ratingscale, vector org, float sradius) { - local entity head; - local float t, i, c, needarmor, needweapons; + entity head; + float t, i, c, needarmor, needweapons; // Needs armor/health? if(self.health<100) @@ -67,7 +67,7 @@ void havocbot_goalrating_ons_offenseitems(float ratingscale, vector org, float s } head = head.chain; } -}; +} void havocbot_role_ons_setrole(entity bot, float role) { @@ -94,12 +94,12 @@ void havocbot_role_ons_setrole(entity bot, float role) break; } dprint("\n"); -}; +} float havocbot_ons_teamcount(entity bot, float role) { - local float c; - local entity head; + float c; + entity head; FOR_EACH_PLAYER(head) if(head.team==self.team) @@ -107,7 +107,7 @@ float havocbot_ons_teamcount(entity bot, float role) ++c; return c; -}; +} void havocbot_goalrating_ons_controlpoints_attack(float ratingscale) { @@ -231,12 +231,12 @@ void havocbot_goalrating_ons_controlpoints_attack(float ratingscale) if not(found) navigation_routerating(cp, ratingscale, 10000); } -}; +} float havocbot_goalrating_ons_generator_attack(float ratingscale) { - local entity g, wp, bestwp; - local float found, best; + entity g, wp, bestwp; + float found, best; for (g = findchain(classname, "onslaught_generator"); g; g = g.chain) { @@ -286,7 +286,7 @@ float havocbot_goalrating_ons_generator_attack(float ratingscale) } } return FALSE; -}; +} void havocbot_role_ons_offense() { @@ -321,22 +321,22 @@ void havocbot_role_ons_offense() self.bot_strategytime = time + autocvar_bot_ai_strategyinterval; } -}; +} void havocbot_role_ons_assistant() { havocbot_ons_reset_role(self); -}; +} void havocbot_role_ons_defense() { havocbot_ons_reset_role(self); -}; +} void havocbot_ons_reset_role(entity bot) { - local entity head; - local float c; + entity head; + float c; if(self.deadflag != DEAD_NO) return; @@ -358,9 +358,9 @@ void havocbot_ons_reset_role(entity bot) } havocbot_role_ons_setrole(bot, HAVOCBOT_ONS_ROLE_OFFENSE); -}; +} void havocbot_chooserole_ons() { havocbot_ons_reset_role(self); -}; +} diff --git a/qcsrc/server/bot/havocbot/roles.qc b/qcsrc/server/bot/havocbot/roles.qc index cfd0503985..91eb2ec1a5 100644 --- a/qcsrc/server/bot/havocbot/roles.qc +++ b/qcsrc/server/bot/havocbot/roles.qc @@ -7,15 +7,17 @@ void havocbot_goalrating_items(float ratingscale, vector org, float sradius) { - local entity head; - local entity player; - local float rating, d, discard, distance, friend_distance, enemy_distance; + entity head; + entity player; + float rating, d, discard, distance, friend_distance, enemy_distance; + vector o; ratingscale = ratingscale * 0.0001; // items are rated around 10000 already head = findchainfloat(bot_pickup, TRUE); while (head) { - distance = vlen(head.origin - org); + o = (head.absmin + head.absmax) * 0.5; + distance = vlen(o - org); friend_distance = 10000; enemy_distance = 10000; rating = 0; @@ -28,7 +30,7 @@ void havocbot_goalrating_items(float ratingscale, vector org, float sradius) // Check if the item can be picked up safely if(head.classname == "droppedweapon") { - traceline(head.origin, head.origin + '0 0 -1500', TRUE, world); + traceline(o, o + '0 0 -1500', TRUE, world); d = pointcontents(trace_endpos + '0 0 1'); if(d & CONTENT_WATER || d & CONTENT_SLIME || d & CONTENT_LAVA) @@ -53,7 +55,7 @@ void havocbot_goalrating_items(float ratingscale, vector org, float sradius) } } - if(teams_matter) + if(teamplay) { discard = FALSE; @@ -63,7 +65,7 @@ void havocbot_goalrating_items(float ratingscale, vector org, float sradius) if ( self == player || player.deadflag ) continue; - d = vlen(player.origin - head.origin); // distance between player and item + d = vlen(player.origin - o); // distance between player and item if ( player.team == self.team ) { @@ -123,15 +125,15 @@ void havocbot_goalrating_items(float ratingscale, vector org, float sradius) navigation_routerating(head, rating * ratingscale, 2000); head = head.chain; } -}; +} void havocbot_goalrating_controlpoints(float ratingscale, vector org, float sradius) { - local entity head; + entity head; head = findchain(classname, "dom_controlpoint"); while (head) { - if (vlen(head.origin - org) < sradius) + if (vlen(( ( head.absmin + head.absmax ) * 0.5 ) - org) < sradius) { if(head.cnt > -1) // this is just being fought for navigation_routerating(head, ratingscale, 5000); @@ -142,13 +144,13 @@ void havocbot_goalrating_controlpoints(float ratingscale, vector org, float srad } head = head.chain; } -}; +} void havocbot_goalrating_enemyplayers(float ratingscale, vector org, float sradius) { - local entity head; - local float t, noteam, distance; - noteam = ((self.team == 0) || !teams_matter); // fteqcc sucks + entity head; + float t, noteam, distance; + noteam = ((self.team == 0) || !teamplay); // fteqcc sucks if (autocvar_bot_nofire) return; @@ -160,18 +162,12 @@ void havocbot_goalrating_enemyplayers(float ratingscale, vector org, float sradi FOR_EACH_PLAYER(head) { // TODO: Merge this logic with the bot_shouldattack function - if (self != head) - if (head.health > 0) - if ((noteam && (!bot_ignore_bots || clienttype(head) == CLIENTTYPE_REAL)) || head.team != self.team) + if(bot_shouldattack(head)) { distance = vlen(head.origin - org); if (distance < 100 || distance > sradius) continue; - if(g_minstagib) - if(head.items & IT_STRENGTH) - continue; - // rate only visible enemies /* traceline(self.origin + self.view_ofs, head.origin, MOVE_NOMONSTERS, self); @@ -194,14 +190,18 @@ void havocbot_goalrating_enemyplayers(float ratingscale, vector org, float sradi continue; } + // TODO: rate waypoints near the targetted player at that moment, instead of the player itself + // adding a player as a goal seems to be quite dangerous, especially on space maps + // remove hack in navigation_poptouchedgoals() after performing this change + t = (self.health + self.armorvalue ) / (head.health + head.armorvalue ); navigation_routerating(head, t * ratingscale, 2000); } } -}; +} // choose a role according to the situation -void() havocbot_role_dm; +void havocbot_role_dm(); //DOM: //go to best items, or control points you don't own @@ -220,7 +220,7 @@ void havocbot_role_dom() //havocbot_goalrating_waypoints(1, self.origin, 1000); navigation_goalrating_end(); } -}; +} //DM: //go to best items @@ -238,7 +238,7 @@ void havocbot_role_dm() //havocbot_goalrating_waypoints(1, self.origin, 1000); navigation_goalrating_end(); } -}; +} //Race: //go to next checkpoint, and annoy enemies @@ -270,24 +270,6 @@ void havocbot_role_race() } } - navigation_goalrating_end(); - } -}; - -// Keepaway -// If you don't have the ball, get it; if you do, kill people. -void havocbot_role_ka() -{ - if(self.deadflag != DEAD_NO) - return; - - if (self.bot_strategytime < time) - { - self.bot_strategytime = time + autocvar_bot_ai_strategyinterval; - navigation_goalrating_start(); - havocbot_goalrating_items(10000, self.origin, 10000); - havocbot_goalrating_enemyplayers(20000, self.origin, 10000); - //havocbot_goalrating_waypoints(1, self.origin, 1000); navigation_goalrating_end(); } } @@ -295,27 +277,21 @@ void havocbot_role_ka() void havocbot_chooserole_dm() { self.havocbot_role = havocbot_role_dm; -}; +} void havocbot_chooserole_race() { self.havocbot_role = havocbot_role_race; -}; +} void havocbot_chooserole_dom() { self.havocbot_role = havocbot_role_dom; -}; - -void havocbot_chooserole_ka() -{ - self.havocbot_role = havocbot_role_ka; } void havocbot_chooserole() { dprint("choosing a role...\n"); - navigation_clearroute(); self.bot_strategytime = 0; if (g_ctf) havocbot_chooserole_ctf(); @@ -329,6 +305,10 @@ void havocbot_chooserole() havocbot_chooserole_ons(); else if (g_keepaway) havocbot_chooserole_ka(); + else if (g_freezetag) + havocbot_chooserole_ft(); + else if (g_assault) + havocbot_chooserole_ast(); else // assume anything else is deathmatch havocbot_chooserole_dm(); -}; +} diff --git a/qcsrc/server/bot/navigation.qc b/qcsrc/server/bot/navigation.qc index f3e5c26a8f..3387fdfef8 100644 --- a/qcsrc/server/bot/navigation.qc +++ b/qcsrc/server/bot/navigation.qc @@ -4,20 +4,21 @@ float tracewalk(entity e, vector start, vector m1, vector m2, vector end, float movemode) { - local vector org; - local vector move; - local vector dir; - local float dist; - local float totaldist; - local float stepdist; - local float yaw; - local float ignorehazards; - local float swimming; - - #ifdef DEBUG_TRACEWALK + vector org; + vector move; + vector dir; + float dist; + float totaldist; + float stepdist; + float yaw; + float ignorehazards; + float swimming; + + if(autocvar_bot_debug_tracewalk) + { debugresetnodes(); debugnode(start); - #endif + } move = end - start; move_z = 0; @@ -44,9 +45,9 @@ float tracewalk(entity e, vector start, vector m1, vector m2, vector end, float if (trace_startsolid) { // Bad start - #ifdef DEBUG_TRACEWALK + if(autocvar_bot_debug_tracewalk) debugnodestatus(start, DEBUG_NODE_FAIL); - #endif + //print("tracewalk: ", vtos(start), " is a bad start\n"); return FALSE; } @@ -59,15 +60,14 @@ float tracewalk(entity e, vector start, vector m1, vector m2, vector end, float if (boxesoverlap(end, end, org + m1 + '-1 -1 -1', org + m2 + '1 1 1')) { // Succeeded - #ifdef DEBUG_TRACEWALK + if(autocvar_bot_debug_tracewalk) debugnodestatus(org, DEBUG_NODE_SUCCESS); - #endif + //print("tracewalk: ", vtos(start), " can reach ", vtos(end), "\n"); return TRUE; } - #ifdef DEBUG_TRACEWALK + if(autocvar_bot_debug_tracewalk) debugnode(org); - #endif if (dist <= 0) break; @@ -80,9 +80,9 @@ float tracewalk(entity e, vector start, vector m1, vector m2, vector end, float if (trace_dpstartcontents & (DPCONTENTS_SLIME | DPCONTENTS_LAVA)) { // hazards blocking path - #ifdef DEBUG_TRACEWALK + if(autocvar_bot_debug_tracewalk) debugnodestatus(org, DEBUG_NODE_FAIL); - #endif + //print("tracewalk: ", vtos(start), " hits a hazard when trying to reach ", vtos(end), "\n"); return FALSE; } @@ -92,9 +92,8 @@ float tracewalk(entity e, vector start, vector m1, vector m2, vector end, float move = normalize(end - org); tracebox(org, m1, m2, org + move * stepdist, movemode, e); - #ifdef DEBUG_TRACEWALK + if(autocvar_bot_debug_tracewalk) debugnode(trace_endpos); - #endif if (trace_fraction < 1) { @@ -102,18 +101,18 @@ float tracewalk(entity e, vector start, vector m1, vector m2, vector end, float org = trace_endpos - normalize(org - trace_endpos) * stepdist; for(; org_z < end_z + self.maxs_z; org_z += stepdist) { - #ifdef DEBUG_TRACEWALK + if(autocvar_bot_debug_tracewalk) debugnode(org); - #endif + if(pointcontents(org) == CONTENT_EMPTY) break; } if not (pointcontents(org + '0 0 1') == CONTENT_EMPTY) { - #ifdef DEBUG_TRACEWALK + if(autocvar_bot_debug_tracewalk) debugnodestatus(org, DEBUG_NODE_FAIL); - #endif + return FALSE; //print("tracewalk: ", vtos(start), " failed under water\n"); } @@ -128,44 +127,48 @@ float tracewalk(entity e, vector start, vector m1, vector m2, vector end, float move = dir * stepdist + org; tracebox(org, m1, m2, move, movemode, e); - #ifdef DEBUG_TRACEWALK + if(autocvar_bot_debug_tracewalk) debugnode(trace_endpos); - #endif // hit something if (trace_fraction < 1) { - // check if we can walk over this obstacle + // check if we can walk over this obstacle, possibly by jumpstepping tracebox(org + stepheightvec, m1, m2, move + stepheightvec, movemode, e); if (trace_fraction < 1 || trace_startsolid) { - #ifdef DEBUG_TRACEWALK - debugnodestatus(trace_endpos, DEBUG_NODE_WARNING); - #endif - - // check for doors - traceline( org, move, movemode, e); - if ( trace_ent.classname == "door_rotating" || trace_ent.classname == "door") + tracebox(org + jumpstepheightvec, m1, m2, move + jumpstepheightvec, movemode, e); + if (trace_fraction < 1 || trace_startsolid) { - local vector nextmove; - move = trace_endpos; - while(trace_ent.classname == "door_rotating" || trace_ent.classname == "door") + if(autocvar_bot_debug_tracewalk) + debugnodestatus(trace_endpos, DEBUG_NODE_WARNING); + + // check for doors + traceline( org, move, movemode, e); + if ( trace_ent.classname == "door_rotating" || trace_ent.classname == "door") { - nextmove = move + (dir * stepdist); - traceline( move, nextmove, movemode, e); - move = nextmove; + vector nextmove; + move = trace_endpos; + while(trace_ent.classname == "door_rotating" || trace_ent.classname == "door") + { + nextmove = move + (dir * stepdist); + traceline( move, nextmove, movemode, e); + move = nextmove; + } + } + else + { + if(autocvar_bot_debug_tracewalk) + debugnodestatus(trace_endpos, DEBUG_NODE_FAIL); + + //print("tracewalk: ", vtos(start), " hit something when trying to reach ", vtos(end), "\n"); + //te_explosion(trace_endpos); + //print(ftos(e.dphitcontentsmask), "\n"); + return FALSE; // failed } } else - { - #ifdef DEBUG_TRACEWALK - debugnodestatus(trace_endpos, DEBUG_NODE_FAIL); - #endif - //print("tracewalk: ", vtos(start), " hit something when trying to reach ", vtos(end), "\n"); - //te_explosion(trace_endpos); - //print(ftos(e.dphitcontentsmask), "\n"); - return FALSE; // failed - } + move = trace_endpos; } else move = trace_endpos; @@ -182,7 +185,7 @@ float tracewalk(entity e, vector start, vector m1, vector m2, vector end, float // moved successfully if(swimming) { - local float c; + float c; c = pointcontents(org + '0 0 1'); if not(c == CONTENT_WATER || c == CONTENT_LAVA || c == CONTENT_SLIME) swimming = FALSE; @@ -197,12 +200,11 @@ float tracewalk(entity e, vector start, vector m1, vector m2, vector end, float //print("tracewalk: ", vtos(start), " did not arrive at ", vtos(end), " but at ", vtos(org), "\n"); // moved but didn't arrive at the intended destination - #ifdef DEBUG_TRACEWALK + if(autocvar_bot_debug_tracewalk) debugnodestatus(org, DEBUG_NODE_FAIL); - #endif return FALSE; -}; +} ///////////////////////////////////////////////////////////////////////////// // goal stack @@ -245,7 +247,7 @@ void navigation_clearroute() self.goalstack29 = world; self.goalstack30 = world; self.goalstack31 = world; -}; +} // add a new goal at the beginning of the stack // (in other words: add a new prerequisite before going to the later goals) @@ -288,7 +290,7 @@ void navigation_pushroute(entity e) self.goalstack02 = self.goalstack01; self.goalstack01 = self.goalcurrent; self.goalcurrent = e; -}; +} // remove first goal from stack // (in other words: remove a prerequisite for reaching the later goals) @@ -328,14 +330,39 @@ void navigation_poproute() self.goalstack29 = self.goalstack30; self.goalstack30 = self.goalstack31; self.goalstack31 = world; -}; +} + +float navigation_waypoint_will_link(vector v, vector org, entity ent, float walkfromwp, float bestdist) +{ + float dist; + dist = vlen(v - org); + if (bestdist > dist) + { + traceline(v, org, TRUE, ent); + if (trace_fraction == 1) + { + if (walkfromwp) + { + if (tracewalk(ent, v, PL_MIN, PL_MAX, org, bot_navigation_movemode)) + return TRUE; + } + else + { + if (tracewalk(ent, org, PL_MIN, PL_MAX, v, bot_navigation_movemode)) + return TRUE; + } + } + } + return FALSE; +} // find the spawnfunc_waypoint near a dynamic goal such as a dropped weapon -entity navigation_findnearestwaypoint(entity ent, float walkfromwp) +entity navigation_findnearestwaypoint_withdist(entity ent, float walkfromwp, float bestdist) { - local entity waylist, w, best; - local float dist, bestdist; - local vector v, org, pm1, pm2; + entity waylist, w, best; + float dist; + vector v, org, pm1, pm2; + pm1 = ent.origin + ent.mins; pm2 = ent.origin + ent.maxs; waylist = findchain(classname, "waypoint"); @@ -360,7 +387,6 @@ entity navigation_findnearestwaypoint(entity ent, float walkfromwp) te_plasmaburn(org); best = world; - bestdist = 1050; // box check failed, try walk w = waylist; @@ -371,7 +397,7 @@ entity navigation_findnearestwaypoint(entity ent, float walkfromwp) { if (w.wpisbox) { - local vector wm1, wm2; + vector wm1, wm2; wm1 = w.origin + w.mins; wm2 = w.origin + w.maxs; v_x = bound(wm1_x, org_x, wm2_x); @@ -380,43 +406,27 @@ entity navigation_findnearestwaypoint(entity ent, float walkfromwp) } else v = w.origin; - dist = vlen(v - org); - if (bestdist > dist) + if(navigation_waypoint_will_link(v, org, ent, walkfromwp, bestdist)) { - traceline(v, org, TRUE, ent); - if (trace_fraction == 1) - { - if (walkfromwp) - { - //print("^1can I reach ", vtos(org), " from ", vtos(v), "?\n"); - if (tracewalk(ent, v, PL_MIN, PL_MAX, org, bot_navigation_movemode)) - { - bestdist = dist; - best = w; - } - } - else - { - if (tracewalk(ent, org, PL_MIN, PL_MAX, v, bot_navigation_movemode)) - { - bestdist = dist; - best = w; - } - } - } + bestdist = vlen(v - org); + best = w; } } w = w.chain; } return best; } +entity navigation_findnearestwaypoint(entity ent, float walkfromwp) +{ + return navigation_findnearestwaypoint_withdist(ent, walkfromwp, 1050); +} // finds the waypoints near the bot initiating a navigation query float navigation_markroutes_nearestwaypoints(entity waylist, float maxdist) { - local entity head; - local vector v, m1, m2, diff; - local float c; + entity head; + vector v, m1, m2, diff; + float c; // navigation_testtracewalk = TRUE; c = 0; head = waylist; @@ -459,9 +469,9 @@ float navigation_markroutes_nearestwaypoints(entity waylist, float maxdist) // updates a path link if a spawnfunc_waypoint link is better than the current one void navigation_markroutes_checkwaypoint(entity w, entity wp, float cost2, vector p) { - local vector m1; - local vector m2; - local vector v; + vector m1; + vector m2; + vector v; if (wp.wpisbox) { m1 = wp.absmin; @@ -480,14 +490,14 @@ void navigation_markroutes_checkwaypoint(entity w, entity wp, float cost2, vecto wp.wpfire = 1; wp.wpnearestpoint = v; } -}; +} // queries the entire spawnfunc_waypoint network for pathes leading away from the bot void navigation_markroutes(entity fixed_source_waypoint) { - local entity w, wp, waylist; - local float searching, cost, cost2; - local vector p; + entity w, wp, waylist; + float searching, cost, cost2; + vector p; w = waylist = findchain(classname, "waypoint"); while (w) { @@ -511,7 +521,7 @@ void navigation_markroutes(entity fixed_source_waypoint) { // try a short range search for the nearest waypoints, and expand the search repeatedly if none are found // as this search is expensive we will use lower values if the bot is on the air - local float i, increment, maxdistance; + float i, increment, maxdistance; if(self.flags & FL_ONGROUND) { increment = 750; @@ -576,14 +586,14 @@ void navigation_markroutes(entity fixed_source_waypoint) w = w.chain; } } -}; +} // queries the entire spawnfunc_waypoint network for pathes leading to the bot void navigation_markroutes_inverted(entity fixed_source_waypoint) { - local entity w, wp, waylist; - local float searching, cost, cost2; - local vector p; + entity w, wp, waylist; + float searching, cost, cost2; + vector p; w = waylist = findchain(classname, "waypoint"); while (w) { @@ -639,22 +649,28 @@ void navigation_markroutes_inverted(entity fixed_source_waypoint) w = w.chain; } } -}; +} // updates the best goal according to a weighted calculation of travel cost and item value of a new proposed item void navigation_routerating(entity e, float f, float rangebias) { entity nwp; + vector o; if (!e) return; + if(e.blacklisted) + return; + + o = (e.absmin + e.absmax) * 0.5; + //print("routerating ", etos(e), " = ", ftos(f), " - ", ftos(rangebias), "\n"); // Evaluate path using jetpack if(g_jetpack) if(self.items & IT_JETPACK) if(autocvar_bot_ai_navigation_jetpack) - if(vlen(self.origin - e.origin) > autocvar_bot_ai_navigation_jetpack_mindistance) + if(vlen(self.origin - o) > autocvar_bot_ai_navigation_jetpack_mindistance) { vector pointa, pointb; @@ -665,7 +681,7 @@ void navigation_routerating(entity e, float f, float rangebias) pointa = trace_endpos - '0 0 1'; // Point B - traceline(e.origin, e.origin + '0 0 65535', MOVE_NORMAL, e); + traceline(o, o + '0 0 65535', MOVE_NORMAL, e); pointb = trace_endpos - '0 0 1'; // Can I see these two points from the sky? @@ -676,8 +692,8 @@ void navigation_routerating(entity e, float f, float rangebias) // dprint("jetpack ai: can bridge these two points\n"); // Lower the altitude of these points as much as possible - local float zdistance, xydistance, cost, t, fuel; - local vector down, npa, npb; + float zdistance, xydistance, cost, t, fuel; + vector down, npa, npb; down = '0 0 -1' * (PL_MAX_z - PL_MIN_z) * 10; @@ -749,14 +765,48 @@ void navigation_routerating(entity e, float f, float rangebias) } else { + float search; + + search = TRUE; + + if(e.flags & FL_ITEM) + { + if not(e.flags & FL_WEAPON) + if(e.nearestwaypoint) + search = FALSE; + } + else if (e.flags & FL_WEAPON) + { + if(e.classname != "droppedweapon") + if(e.nearestwaypoint) + search = FALSE; + } + + if(search) if (time > e.nearestwaypointtimeout) { nwp = navigation_findnearestwaypoint(e, TRUE); if(nwp) e.nearestwaypoint = nwp; else + { dprint("FAILED to find a nearest waypoint to '", e.classname, "' #", etos(e), "\n"); + if(e.flags & FL_ITEM) + e.blacklisted = TRUE; + else if (e.flags & FL_WEAPON) + { + if(e.classname != "droppedweapon") + e.blacklisted = TRUE; + } + + if(e.blacklisted) + { + dprint("The entity '", e.classname, "' is going to be excluded from path finding during this match\n"); + return; + } + } + // TODO: Cleaner solution, probably handling this timeout from ctf.qc if(e.classname=="item_flag_team") e.nearestwaypointtimeout = time + 2; @@ -772,7 +822,7 @@ void navigation_routerating(entity e, float f, float rangebias) { //te_wizspike(nwp.wpnearestpoint); // dprint(e.classname, " ", ftos(f), "/(1+", ftos((nwp.wpcost + vlen(e.origin - nwp.wpnearestpoint))), "/", ftos(rangebias), ") = "); - f = f * rangebias / (rangebias + (nwp.wpcost + vlen(e.origin - nwp.wpnearestpoint))); + f = f * rangebias / (rangebias + (nwp.wpcost + vlen(o - nwp.wpnearestpoint))); //dprint("considering ", e.classname, " (with rating ", ftos(f), ")\n"); //dprint(ftos(f)); if (navigation_bestrating < f) @@ -783,7 +833,7 @@ void navigation_routerating(entity e, float f, float rangebias) } } //dprint("\n"); -}; +} // adds an item to the the goal stack with the path to a given item float navigation_routetogoal(entity e, vector startposition) @@ -805,7 +855,7 @@ float navigation_routetogoal(entity e, vector startposition) return TRUE; // if it can reach the goal there is nothing more to do - if (tracewalk(self, startposition, PL_MIN, PL_MAX, e.origin, bot_navigation_movemode)) + if (tracewalk(self, startposition, PL_MIN, PL_MAX, (e.absmin + e.absmax) * 0.5, bot_navigation_movemode)) return TRUE; // see if there are waypoints describing a path to the item @@ -828,13 +878,13 @@ float navigation_routetogoal(entity e, vector startposition) } return FALSE; -}; +} // removes any currently touching waypoints from the goal stack // (this is how bots detect if they reached a goal) void navigation_poptouchedgoals() { - local vector org, m1, m2; + vector org, m1, m2; org = self.origin; m1 = org + self.mins; m2 = org + self.maxs; @@ -855,8 +905,34 @@ void navigation_poptouchedgoals() } } + // If for some reason the bot is closer to the next goal, pop the current one + if(self.goalstack01) + if(vlen(self.goalcurrent.origin - self.origin) > vlen(self.goalstack01.origin - self.origin)) + if(checkpvs(self.origin + self.view_ofs, self.goalstack01)) + if(tracewalk(self, self.origin, self.mins, self.maxs, (self.goalstack01.absmin + self.goalstack01.absmax) * 0.5, bot_navigation_movemode)) + { + /// dprint("path optimized for ", self.netname, ", removed a goal from the queue\n"); + navigation_poproute(); + // TODO this may also be a nice idea to do "early" (e.g. by + // manipulating the vlen() comparisons) to shorten paths in + // general - this would make bots walk more "on rails" than + // "zigzagging" which they currently do with sufficiently + // random-like waypoints, and thus can make a nice bot + // personality property + } + + // HACK: remove players/bots as goals, they can lead a bot to unexpected places (cliffs, lava, etc) + // TODO: rate waypoints near the targetted player at that moment, instead of the player itself + if(self.goalcurrent.classname=="player") + navigation_poproute(); + + // aid for detecting jump pads better (distance based check fails sometimes) + if(self.goalcurrent.wpflags & WAYPOINTFLAG_TELEPORT && self.jumppadcount > 0 ) + navigation_poproute(); + // Loose goal touching check when running if(self.aistatus & AI_STATUS_RUNNING) + if(self.speed >= autocvar_sv_maxspeed) // if -really- running if(self.goalcurrent.classname=="waypoint") { if(vlen(self.origin - self.goalcurrent.origin)<150) @@ -894,49 +970,45 @@ void navigation_poptouchedgoals() // begin a goal selection session (queries spawnfunc_waypoint network) void navigation_goalrating_start() { + if(self.aistatus & AI_STATUS_STUCK) + return; + self.navigation_jetpack_goal = world; navigation_bestrating = -1; self.navigation_hasgoals = FALSE; + navigation_clearroute(); navigation_bestgoal = world; navigation_markroutes(world); -}; +} // ends a goal selection session (updates goal stack to the best goal) void navigation_goalrating_end() { + if(self.aistatus & AI_STATUS_STUCK) + return; + navigation_routetogoal(navigation_bestgoal, self.origin); // dprint("best goal ", self.goalcurrent.classname , "\n"); - // Hack: if it can't walk to any goal just move blindly to the first visible waypoint + // If the bot got stuck then try to reach the farthest waypoint if not (self.navigation_hasgoals) + if (autocvar_bot_wander_enable) { - dprint(self.netname, " can't walk to any goal, going to a near waypoint\n"); - - entity head; - - RandomSelection_Init(); - head = findradius(self.origin,1000); - while(head) + if not(self.aistatus & AI_STATUS_STUCK) { - if(head.classname=="waypoint") - if(!(head.wpflags & WAYPOINTFLAG_GENERATED)) - if(vlen(self.origin-head.origin)>100) - if(checkpvs(self.view_ofs,head)) - RandomSelection_Add(head, 0, string_null, 1 + (vlen(self.origin-head.origin)<500), 0); - head = head.chain; + dprint(self.netname, " cannot walk to any goal\n"); + self.aistatus |= AI_STATUS_STUCK; } - if(RandomSelection_chosen_ent) - navigation_routetogoal(RandomSelection_chosen_ent, self.origin); self.navigation_hasgoals = FALSE; // Reset this value } -}; +} void botframe_updatedangerousobjects(float maxupdate) { - local entity head, bot_dodgelist; - local vector m1, m2, v; - local float c, d, danger; + entity head, bot_dodgelist; + vector m1, m2, v, o; + float c, d, danger; c = 0; bot_dodgelist = findchainfloat(bot_dodge, TRUE); botframe_dangerwaypoint = find(botframe_dangerwaypoint, classname, "waypoint"); @@ -952,10 +1024,11 @@ void botframe_updatedangerousobjects(float maxupdate) v_x = bound(m1_x, v_x, m2_x); v_y = bound(m1_y, v_y, m2_y); v_z = bound(m1_z, v_z, m2_z); - d = head.bot_dodgerating - vlen(head.origin - v); + o = (head.absmin + head.absmax) * 0.5; + d = head.bot_dodgerating - vlen(o - v); if (d > 0) { - traceline(head.origin, v, TRUE, world); + traceline(o, v, TRUE, world); if (trace_fraction == 1) danger = danger + d; } @@ -967,9 +1040,99 @@ void botframe_updatedangerousobjects(float maxupdate) break; botframe_dangerwaypoint = find(botframe_dangerwaypoint, classname, "waypoint"); } -}; +} + +void navigation_unstuck() +{ + float search_radius = 1000; + + if not(autocvar_bot_wander_enable) + return; + + if not(bot_waypoint_queue_owner) + { + // dprint(self.netname, " sutck, taking over the waypoints queue\n"); + bot_waypoint_queue_owner = self; + bot_waypoint_queue_bestgoal = world; + bot_waypoint_queue_bestgoalrating = 0; + } -#ifdef DEBUG_TRACEWALK + if(bot_waypoint_queue_owner!=self) + return; + + if (bot_waypoint_queue_goal) + { + // evaluate the next goal on the queue + float d = vlen(self.origin - bot_waypoint_queue_goal.origin); + // dprint(self.netname, " evaluating ", bot_waypoint_queue_goal.classname, " with distance ", ftos(d), "\n"); + if(tracewalk(bot_waypoint_queue_goal, self.origin, PL_MIN, PL_MAX, bot_waypoint_queue_goal.origin, bot_navigation_movemode)) + { + if( d > bot_waypoint_queue_bestgoalrating) + { + bot_waypoint_queue_bestgoalrating = d; + bot_waypoint_queue_bestgoal = bot_waypoint_queue_goal; + } + } + bot_waypoint_queue_goal = bot_waypoint_queue_goal.bot_waypoint_queue_nextgoal; + + if not(bot_waypoint_queue_goal) + { + if (bot_waypoint_queue_bestgoal) + { + dprint(self.netname, " stuck, reachable waypoint found, heading to it\n"); + navigation_routetogoal(bot_waypoint_queue_bestgoal, self.origin); + self.bot_strategytime = time + autocvar_bot_ai_strategyinterval; + self.aistatus &~= AI_STATUS_STUCK; + } + else + { + dprint(self.netname, " stuck, cannot walk to any waypoint at all\n"); + } + + bot_waypoint_queue_owner = world; + } + } + else + { + if(bot_strategytoken!=self) + return; + + // build a new queue + dprint(self.netname, " stuck, scanning reachable waypoints within ", ftos(search_radius)," qu\n"); + + entity head, first; + + first = world; + head = findradius(self.origin, search_radius); + + while(head) + { + if(head.classname=="waypoint") + // if(!(head.wpflags & WAYPOINTFLAG_GENERATED)) + { + if(bot_waypoint_queue_goal) + bot_waypoint_queue_goal.bot_waypoint_queue_nextgoal = head; + else + first = head; + + bot_waypoint_queue_goal = head; + bot_waypoint_queue_goal.bot_waypoint_queue_nextgoal = world; + } + + head = head.chain; + } + + if (first) + bot_waypoint_queue_goal = first; + else + { + dprint(self.netname, " stuck, cannot walk to any waypoint at all\n"); + bot_waypoint_queue_owner = world; + } + } +} + +// Support for debugging tracewalk visually void debugresetnodes() { @@ -993,29 +1156,27 @@ void debugnode(vector node) void debugnodestatus(vector position, float status) { - vector color; + vector c; switch (status) { case DEBUG_NODE_SUCCESS: - color = '0 15 0'; + c = '0 15 0'; break; case DEBUG_NODE_WARNING: - color = '15 15 0'; + c = '15 15 0'; break; case DEBUG_NODE_FAIL: - color = '15 0 0'; + c = '15 0 0'; break; default: - color = '15 15 15'; + c = '15 15 15'; } - te_customflash(position, 40, 2, color); + te_customflash(position, 40, 2, c); } -#endif - -#ifdef DEBUG_BOT_GOALSTACK +// Support for debugging the goal stack visually .float goalcounter; .vector lastposition; @@ -1023,43 +1184,43 @@ void debugnodestatus(vector position, float status) // Debug the goal stack visually void debuggoalstack() { - local entity target; - local vector org; - - if(self.goalcounter==0)target=self.goalcurrent; - else if(self.goalcounter==1)target=self.goalstack01; - else if(self.goalcounter==2)target=self.goalstack02; - else if(self.goalcounter==3)target=self.goalstack03; - else if(self.goalcounter==4)target=self.goalstack04; - else if(self.goalcounter==5)target=self.goalstack05; - else if(self.goalcounter==6)target=self.goalstack06; - else if(self.goalcounter==7)target=self.goalstack07; - else if(self.goalcounter==8)target=self.goalstack08; - else if(self.goalcounter==9)target=self.goalstack09; - else if(self.goalcounter==10)target=self.goalstack10; - else if(self.goalcounter==11)target=self.goalstack11; - else if(self.goalcounter==12)target=self.goalstack12; - else if(self.goalcounter==13)target=self.goalstack13; - else if(self.goalcounter==14)target=self.goalstack14; - else if(self.goalcounter==15)target=self.goalstack15; - else if(self.goalcounter==16)target=self.goalstack16; - else if(self.goalcounter==17)target=self.goalstack17; - else if(self.goalcounter==18)target=self.goalstack18; - else if(self.goalcounter==19)target=self.goalstack19; - else if(self.goalcounter==20)target=self.goalstack20; - else if(self.goalcounter==21)target=self.goalstack21; - else if(self.goalcounter==22)target=self.goalstack22; - else if(self.goalcounter==23)target=self.goalstack23; - else if(self.goalcounter==24)target=self.goalstack24; - else if(self.goalcounter==25)target=self.goalstack25; - else if(self.goalcounter==26)target=self.goalstack26; - else if(self.goalcounter==27)target=self.goalstack27; - else if(self.goalcounter==28)target=self.goalstack28; - else if(self.goalcounter==29)target=self.goalstack29; - else if(self.goalcounter==30)target=self.goalstack30; - else if(self.goalcounter==31)target=self.goalstack31; - - if(target==world) + entity goal; + vector org, go; + + if(self.goalcounter==0)goal=self.goalcurrent; + else if(self.goalcounter==1)goal=self.goalstack01; + else if(self.goalcounter==2)goal=self.goalstack02; + else if(self.goalcounter==3)goal=self.goalstack03; + else if(self.goalcounter==4)goal=self.goalstack04; + else if(self.goalcounter==5)goal=self.goalstack05; + else if(self.goalcounter==6)goal=self.goalstack06; + else if(self.goalcounter==7)goal=self.goalstack07; + else if(self.goalcounter==8)goal=self.goalstack08; + else if(self.goalcounter==9)goal=self.goalstack09; + else if(self.goalcounter==10)goal=self.goalstack10; + else if(self.goalcounter==11)goal=self.goalstack11; + else if(self.goalcounter==12)goal=self.goalstack12; + else if(self.goalcounter==13)goal=self.goalstack13; + else if(self.goalcounter==14)goal=self.goalstack14; + else if(self.goalcounter==15)goal=self.goalstack15; + else if(self.goalcounter==16)goal=self.goalstack16; + else if(self.goalcounter==17)goal=self.goalstack17; + else if(self.goalcounter==18)goal=self.goalstack18; + else if(self.goalcounter==19)goal=self.goalstack19; + else if(self.goalcounter==20)goal=self.goalstack20; + else if(self.goalcounter==21)goal=self.goalstack21; + else if(self.goalcounter==22)goal=self.goalstack22; + else if(self.goalcounter==23)goal=self.goalstack23; + else if(self.goalcounter==24)goal=self.goalstack24; + else if(self.goalcounter==25)goal=self.goalstack25; + else if(self.goalcounter==26)goal=self.goalstack26; + else if(self.goalcounter==27)goal=self.goalstack27; + else if(self.goalcounter==28)goal=self.goalstack28; + else if(self.goalcounter==29)goal=self.goalstack29; + else if(self.goalcounter==30)goal=self.goalstack30; + else if(self.goalcounter==31)goal=self.goalstack31; + + if(goal==world) { self.goalcounter = 0; self.lastposition='0 0 0'; @@ -1072,10 +1233,9 @@ void debuggoalstack() org = self.lastposition; - te_lightning2(world, org, target.origin); - self.lastposition = target.origin; + go = ( goal.absmin + goal.absmax ) * 0.5; + te_lightning2(world, org, go); + self.lastposition = go; self.goalcounter++; } - -#endif diff --git a/qcsrc/server/bot/navigation.qh b/qcsrc/server/bot/navigation.qh index 666db4e5ee..b3b40ce03e 100644 --- a/qcsrc/server/bot/navigation.qh +++ b/qcsrc/server/bot/navigation.qh @@ -6,6 +6,7 @@ float navigation_bestrating; float bot_navigation_movemode; float navigation_testtracewalk; +vector jumpstepheightvec; vector stepheightvec; entity botframe_dangerwaypoint; @@ -27,29 +28,31 @@ entity navigation_bestgoal; .float navigation_hasgoals; .float lastteleporttime; +.float blacklisted; + .entity navigation_jetpack_goal; .vector navigation_jetpack_point; -#ifdef DEBUG_TRACEWALK float DEBUG_NODE_SUCCESS = 1; float DEBUG_NODE_WARNING = 2; float DEBUG_NODE_FAIL = 3; vector debuglastnode; -#endif + +entity bot_waypoint_queue_owner; // Owner of the temporary list of goals +entity bot_waypoint_queue_goal; // Head of the temporary list of goals +.entity bot_waypoint_queue_nextgoal; +entity bot_waypoint_queue_bestgoal; +float bot_waypoint_queue_bestgoalrating; /* * Functions */ -#ifdef DEBUG_TRACEWALK void debugresetnodes(); void debugnode(vector node); void debugnodestatus(vector position, float status); -#endif -#ifdef DEBUG_BOT_GOALSTACK void debuggoalstack(); -#endif float tracewalk(entity e, vector start, vector m1, vector m2, vector end, float movemode); @@ -66,6 +69,7 @@ void navigation_routerating(entity e, float f, float rangebias); void navigation_poptouchedgoals(); void navigation_goalrating_start(); void navigation_goalrating_end(); +void navigation_unstuck(); void botframe_updatedangerousobjects(float maxupdate); diff --git a/qcsrc/server/bot/scripting.qc b/qcsrc/server/bot/scripting.qc index ef25a958d2..2fdbdd3f4f 100644 --- a/qcsrc/server/bot/scripting.qc +++ b/qcsrc/server/bot/scripting.qc @@ -21,6 +21,28 @@ void bot_queuecommand(entity bot, string cmdstring) } bufstr_set(bot.bot_cmdqueuebuf, bot.bot_cmdqueuebuf_end, cmdstring); + + // if the command was a "sound" command, precache the sound NOW + // this prevents lagging! + { + float sp; + string parm; + string cmdstr; + + sp = strstrofs(cmdstr, " ", 0); + if(sp < 0) + { + parm = ""; + } + else + { + parm = substring(cmdstr, sp + 1, -1); + cmdstr = substring(cmdstr, 0, sp); + } + if(cmdstr == "sound") + precache_sound(cmdstr); + } + bot.bot_cmdqueuebuf_end += 1; } @@ -63,8 +85,8 @@ float bot_havecommand(entity bot, float idx) #define MAX_BOT_PLACES 4 .float bot_places_count; -.entity bot_places[MAX_BOT_PLACES]; FTEQCC_YOU_SUCK_THIS_IS_NOT_UNREFERENCED(bot_places); -.string bot_placenames[MAX_BOT_PLACES]; FTEQCC_YOU_SUCK_THIS_IS_NOT_UNREFERENCED(bot_placenames); +.entity bot_places[MAX_BOT_PLACES]; +.string bot_placenames[MAX_BOT_PLACES]; entity bot_getplace(string placename) { entity e; @@ -131,11 +153,12 @@ entity bot_getplace(string placename) #define BOT_CMD_BARRIER 20 #define BOT_CMD_CONSOLE 21 #define BOT_CMD_SOUND 22 -#define BOT_CMD_WHILE 23 // TODO: Not implemented yet -#define BOT_CMD_WEND 24 // TODO: Not implemented yet -#define BOT_CMD_CHASE 25 // TODO: Not implemented yet +#define BOT_CMD_DEBUG_ASSERT_CANFIRE 23 +#define BOT_CMD_WHILE 24 // TODO: Not implemented yet +#define BOT_CMD_WEND 25 // TODO: Not implemented yet +#define BOT_CMD_CHASE 26 // TODO: Not implemented yet -#define BOT_CMD_COUNTER 23 // Update this value if you add/remove a command +#define BOT_CMD_COUNTER 24 // Update this value if you add/remove a command // NOTE: Following commands should be implemented on the bot ai // If a new command should be handled by the target ai(s) please declare it here @@ -241,13 +264,16 @@ void bot_commands_init() bot_cmd_string[BOT_CMD_SOUND] = "sound"; bot_cmd_parm_type[BOT_CMD_SOUND] = BOT_CMD_PARAMETER_STRING; + bot_cmd_string[BOT_CMD_DEBUG_ASSERT_CANFIRE] = "debug_assert_canfire"; + bot_cmd_parm_type[BOT_CMD_DEBUG_ASSERT_CANFIRE] = BOT_CMD_PARAMETER_FLOAT; + bot_cmds_initialized = TRUE; } // Returns first bot with matching name entity find_bot_by_name(string name) { - local entity bot; + entity bot; bot = findchainflags(flags, FL_CLIENT); while (bot) @@ -265,8 +291,8 @@ entity find_bot_by_name(string name) // Returns a bot by number on list entity find_bot_by_number(float number) { - local entity bot; - local float c; + entity bot; + float c; if(!number) return world; @@ -287,7 +313,7 @@ entity find_bot_by_number(float number) float bot_decodecommand(string cmdstring) { - local float cmd_parm_type, i; + float cmd_parm_type, i; float sp; string parm; @@ -346,8 +372,8 @@ float bot_decodecommand(string cmdstring) void bot_cmdhelp(string scmd) { - local float i, ntype; - local string stype; + float i, ntype; + string stype; if(!bot_cmds_initialized) bot_commands_init(); @@ -448,6 +474,9 @@ void bot_cmdhelp(string scmd) case BOT_CMD_SOUND: print("play sound file at bot location"); break; + case BOT_CMD_DEBUG_ASSERT_CANFIRE: + print("verify the state of the weapon entity"); + break; default: print("This command has no description yet."); break; @@ -458,14 +487,14 @@ void bot_cmdhelp(string scmd) void bot_list_commands() { - local float i; - local string ptype; + float i; + string ptype; if(!bot_cmds_initialized) bot_commands_init(); print("List of all available commands:\n"); - print(" Command\t\t\t\tParameter Type\n"); + print(" Command - Parameter Type\n"); for(i=1;i<BOT_CMD_COUNTER;++i) { @@ -484,7 +513,7 @@ void bot_list_commands() ptype = "none"; break; } - print(strcat(" ",bot_cmd_string[i],"\t\t\t\t<",ptype,"> \n")); + print(strcat(" ",bot_cmd_string[i]," - <",ptype,"> \n")); } } @@ -596,7 +625,7 @@ float bot_cmd_turn() float bot_cmd_select_weapon() { - local float id; + float id; id = bot_cmd.bot_cmd_parm_float; @@ -650,8 +679,8 @@ float bot_cmd_eval(string expr) float bot_cmd_if() { - local string expr, val_a, val_b; - local float cmpofs; + string expr, val_a, val_b; + float cmpofs; if(self.bot_cmd_condition_status != CMD_CONDITION_NONE) { @@ -748,7 +777,7 @@ float bot_cmd_aim() // Current direction if(self.bot_cmd_aim_endtime) { - local float progress; + float progress; progress = min(1 - (self.bot_cmd_aim_endtime - time) / (self.bot_cmd_aim_endtime - self.bot_cmd_aim_begintime),1); self.v_angle = self.bot_cmd_aim_begin + ((self.bot_cmd_aim_end - self.bot_cmd_aim_begin) * progress); @@ -763,25 +792,25 @@ float bot_cmd_aim() } // New aiming direction - local string parms; - local float tokens, step; + string parms; + float tokens, step; parms = bot_cmd.bot_cmd_parm_string; tokens = tokenizebyseparator(parms, " "); - if(tokens==2) + if(tokens<2||tokens>3) + return CMD_STATUS_ERROR; + + step = (tokens == 3) ? stof(argv(2)) : 0; + + if(step == 0) { self.v_angle_x -= stof(argv(1)); self.v_angle_y += stof(argv(0)); return CMD_STATUS_FINISHED; } - if(tokens<2||tokens>3) - return CMD_STATUS_ERROR; - - step = stof(argv(2)); - self.bot_cmd_aim_begin = self.v_angle; self.bot_cmd_aim_end_x = self.v_angle_x - stof(argv(1)); @@ -801,10 +830,10 @@ float bot_cmd_aimtarget() return bot_cmd_aim(); } - local entity e; - local string parms; - local vector v; - local float tokens, step; + entity e; + string parms; + vector v; + float tokens, step; parms = bot_cmd.bot_cmd_parm_string; @@ -998,7 +1027,7 @@ float bot_cmd_keypress_handler(string key, float enabled) float bot_cmd_presskey() { - local string key; + string key; key = bot_cmd.bot_cmd_parm_string; @@ -1009,7 +1038,7 @@ float bot_cmd_presskey() float bot_cmd_releasekey() { - local string key; + string key; key = bot_cmd.bot_cmd_parm_string; @@ -1061,7 +1090,49 @@ float bot_cmd_sound() f = bot_cmd.bot_cmd_parm_string; precache_sound(f); - sound(self, CHAN_WEAPON2, f, VOL_BASE, ATTN_MIN); + sound(self, CH_WEAPON_B, f, VOL_BASE, ATTN_MIN); + + return CMD_STATUS_FINISHED; +} + +.entity tuba_note; +float bot_cmd_debug_assert_canfire() +{ + float f; + f = bot_cmd.bot_cmd_parm_float; + + if(self.weaponentity.state != WS_READY) + { + if(f) + { + self.colormod = '0 8 8'; + print("Bot wants to fire, inhibited by weaponentity state\n"); + } + } + else if(ATTACK_FINISHED(self) > time) + { + if(f) + { + self.colormod = '8 0 8'; + print("Bot wants to fire, inhibited by ATTACK_FINISHED\n"); + } + } + else if(self.tuba_note) + { + if(f) + { + self.colormod = '8 0 0'; + print("Bot wants to fire, bot still has an active tuba note\n"); + } + } + else + { + if(!f) + { + self.colormod = '8 8 0'; + print("Bot thinks it has fired, but apparently did not\n"); + } + } return CMD_STATUS_FINISHED; } @@ -1142,14 +1213,18 @@ void bot_resetqueues() // NOTE: Of course you need to include your commands here too :) float bot_execute_commands_once() { - local float status, ispressingkey; - - if(self.deadflag!=DEAD_NO) - return 0; + float status, ispressingkey; // Find command bot_setcurrentcommand(); + // if we have no bot command, better return + // old logic kept pressing previously pressed keys, but that has problems + // (namely, it means you cannot make a bot "normal" ever again) + // to keep a bot walking for a while, use the "wait" bot command + if(bot_cmd == world) + return FALSE; + // Ignore all commands except continue when the bot is paused if(self.bot_exec_status & BOT_EXEC_STATUS_PAUSED) if(bot_cmd.bot_cmd_type!=BOT_CMD_CONTINUE) @@ -1165,9 +1240,6 @@ float bot_execute_commands_once() // Keep pressing keys raised by the "presskey" command ispressingkey = !!bot_presskeys(); - if(bot_cmd==world) - return ispressingkey; - // Handle conditions if not(bot_cmd.bot_cmd_type==BOT_CMD_FI||bot_cmd.bot_cmd_type==BOT_CMD_ELSE) if(self.bot_cmd_condition_status & CMD_CONDITION_TRUE && self.bot_cmd_condition_status & CMD_CONDITION_FALSE_BLOCK) @@ -1254,6 +1326,9 @@ float bot_execute_commands_once() case BOT_CMD_SOUND: status = bot_cmd_sound(); break; + case BOT_CMD_DEBUG_ASSERT_CANFIRE: + status = bot_cmd_debug_assert_canfire(); + break; default: print(strcat("ERROR: Invalid command on queue with id '",ftos(bot_cmd.bot_cmd_type),"'\n")); return 0; @@ -1271,7 +1346,7 @@ float bot_execute_commands_once() { if(autocvar_g_debug_bot_commands) { - local string parms; + string parms; switch(bot_cmd_parm_type[bot_cmd.bot_cmd_type]) { diff --git a/qcsrc/server/bot/waypoints.qc b/qcsrc/server/bot/waypoints.qc index b39e59f762..4db72e407d 100644 --- a/qcsrc/server/bot/waypoints.qc +++ b/qcsrc/server/bot/waypoints.qc @@ -3,7 +3,7 @@ // (suitable for spawnfunc_waypoint editor) entity waypoint_spawn(vector m1, vector m2, float f) { - local entity w; + entity w; w = find(world, classname, "waypoint"); if not(f & WAYPOINTFLAG_PERSONAL) @@ -23,7 +23,7 @@ entity waypoint_spawn(vector m1, vector m2, float f) setsize(w, m1 - w.origin, m2 - w.origin); if (vlen(w.size) > 0) w.wpisbox = TRUE; - + if(!w.wpisbox) { setsize(w, PL_MIN - '1 1 0', PL_MAX + '1 1 0'); @@ -67,12 +67,12 @@ entity waypoint_spawn(vector m1, vector m2, float f) w.model = ""; return w; -}; +} // add a new link to the spawnfunc_waypoint, replacing the furthest link it already has void waypoint_addlink(entity from, entity to) { - local float c; + float c; if (from == to) return; @@ -92,7 +92,7 @@ void waypoint_addlink(entity from, entity to) { // if either is a box we have to find the nearest points on them to // calculate the distance properly - local vector v1, v2, m1, m2; + vector v1, v2, m1, m2; v1 = from.origin; m1 = to.absmin; m2 = to.absmax; @@ -144,17 +144,18 @@ void waypoint_addlink(entity from, entity to) if (from.wp01mincost < c) {from.wp02 = to;from.wp02mincost = c;return;} from.wp02 = from.wp01;from.wp02mincost = from.wp01mincost; if (from.wp00mincost < c) {from.wp01 = to;from.wp01mincost = c;return;} from.wp01 = from.wp00;from.wp01mincost = from.wp00mincost; from.wp00 = to;from.wp00mincost = c;return; -}; +} // relink this spawnfunc_waypoint // (precompile a list of all reachable waypoints from this spawnfunc_waypoint) // (SLOW!) void waypoint_think() { - local entity e; - local vector sv, sm1, sm2, ev, em1, em2, dv; + entity e; + vector sv, sm1, sm2, ev, em1, em2, dv; + + bot_calculate_stepheightvec(); - stepheightvec = autocvar_sv_stepheight * '0 0 1'; bot_navigation_movemode = ((autocvar_bot_navigation_ignoreplayers) ? MOVE_NOMONSTERS : MOVE_NORMAL); //dprint("waypoint_think wpisbox = ", ftos(self.wpisbox), "\n"); @@ -225,12 +226,12 @@ void waypoint_think() } navigation_testtracewalk = 0; self.wplinked = TRUE; -}; +} void waypoint_clearlinks(entity wp) { // clear links to other waypoints - local float f; + float f; f = 10000000; wp.wp00 = wp.wp01 = wp.wp02 = wp.wp03 = wp.wp04 = wp.wp05 = wp.wp06 = wp.wp07 = world; wp.wp08 = wp.wp09 = wp.wp10 = wp.wp11 = wp.wp12 = wp.wp13 = wp.wp14 = wp.wp15 = world; @@ -243,7 +244,7 @@ void waypoint_clearlinks(entity wp) wp.wp24mincost = wp.wp25mincost = wp.wp26mincost = wp.wp27mincost = wp.wp28mincost = wp.wp29mincost = wp.wp30mincost = wp.wp31mincost = f; wp.wplinked = FALSE; -}; +} // tell a spawnfunc_waypoint to relink void waypoint_schedulerelink(entity wp) @@ -253,7 +254,7 @@ void waypoint_schedulerelink(entity wp) // TODO: add some sort of visible box in edit mode for box waypoints if (autocvar_g_waypointeditor) { - local vector m1, m2; + vector m1, m2; m1 = wp.mins; m2 = wp.maxs; setmodel(wp, "models/runematch/rune.mdl"); wp.effects = EF_LOWPRECISION; @@ -286,7 +287,7 @@ void spawnfunc_waypoint() // schedule a relink after other waypoints have had a chance to spawn waypoint_clearlinks(self); //waypoint_schedulerelink(self); -}; +} // remove a spawnfunc_waypoint, and schedule all neighbors to relink void waypoint_remove(entity e) @@ -326,12 +327,12 @@ void waypoint_remove(entity e) waypoint_schedulerelink(e.wp31); // and now remove the spawnfunc_waypoint remove(e); -}; +} // empties the map of waypoints void waypoint_removeall() { - local entity head, next; + entity head, next; head = findchain(classname, "waypoint"); while (head) { @@ -339,13 +340,13 @@ void waypoint_removeall() remove(head); head = next; } -}; +} // tell all waypoints to relink // (is this useful at all?) void waypoint_schedulerelinkall() { - local entity head; + entity head; relink_total = relink_walkculled = relink_pvsculled = relink_lengthculled = 0; head = findchain(classname, "waypoint"); while (head) @@ -353,15 +354,15 @@ void waypoint_schedulerelinkall() waypoint_schedulerelink(head); head = head.chain; } -}; +} // Load waypoint links from file float waypoint_load_links() { - local string filename, s; - local float file, tokens, c, found; - local entity wp_from, wp_to; - local vector wp_to_pos, wp_from_pos; + string filename, s; + float file, tokens, c, found; + entity wp_from, wp_to; + vector wp_to_pos, wp_from_pos; filename = strcat("maps/", mapname); filename = strcat(filename, ".waypoints.cache"); file = fopen(filename, FILE_READ); @@ -410,10 +411,10 @@ float waypoint_load_links() if(!found) { - // can't find that waypoint - fclose(file); - return FALSE; + dprint("waypoint_load_links: couldn't find 'from' waypoint at ", vtos(wp_from.origin),"\n"); + continue; } + } // Search "to" waypoint @@ -432,9 +433,8 @@ float waypoint_load_links() if(!found) { - // can't find that waypoint - fclose(file); - return FALSE; + dprint("waypoint_load_links: couldn't find 'to' waypoint at ", vtos(wp_to.origin),"\n"); + continue; } ++c; @@ -451,14 +451,14 @@ float waypoint_load_links() botframe_cachedwaypointlinks = TRUE; return TRUE; -}; +} void waypoint_load_links_hardwired() { - local string filename, s; - local float file, tokens, c, found; - local entity wp_from, wp_to; - local vector wp_to_pos, wp_from_pos; + string filename, s; + float file, tokens, c, found; + entity wp_from, wp_to; + vector wp_to_pos, wp_from_pos; filename = strcat("maps/", mapname); filename = strcat(filename, ".waypoints.hardwired"); file = fopen(filename, FILE_READ); @@ -496,11 +496,11 @@ void waypoint_load_links_hardwired() // Search "from" waypoint if(wp_from.origin!=wp_from_pos) { - wp_from = findradius(wp_from_pos, 1); + wp_from = findradius(wp_from_pos, 5); found = FALSE; while(wp_from) { - if(vlen(wp_from.origin-wp_from_pos)<1) + if(vlen(wp_from.origin-wp_from_pos)<5) if(wp_from.classname == "waypoint") { found = TRUE; @@ -517,11 +517,11 @@ void waypoint_load_links_hardwired() } // Search "to" waypoint - wp_to = findradius(wp_to_pos, 1); + wp_to = findradius(wp_to_pos, 5); found = FALSE; while(wp_to) { - if(vlen(wp_to.origin-wp_to_pos)<1) + if(vlen(wp_to.origin-wp_to_pos)<5) if(wp_to.classname == "waypoint") { found = TRUE; @@ -538,6 +538,8 @@ void waypoint_load_links_hardwired() ++c; waypoint_addlink(wp_from, wp_to); + wp_from.wphardwired = TRUE; + wp_to.wphardwired = TRUE; } fclose(file); @@ -547,14 +549,14 @@ void waypoint_load_links_hardwired() dprint(" waypoint links from maps/"); dprint(mapname); dprint(".waypoints.hardwired\n"); -}; +} // Save all waypoint links to a file void waypoint_save_links() { - local string filename, s; - local float file, c, i; - local entity w, link; + string filename, s; + float file, c, i; + entity w, link; filename = strcat("maps/", mapname); filename = strcat(filename, ".waypoints.cache"); file = fopen(filename, FILE_WRITE); @@ -625,14 +627,14 @@ void waypoint_save_links() print(" waypoints links to maps/"); print(mapname); print(".waypoints.cache\n"); -}; +} // save waypoints to gamedir/data/maps/mapname.waypoints void waypoint_saveall() { - local string filename, s; - local float file, c; - local entity w; + string filename, s; + float file, c; + entity w; filename = strcat("maps/", mapname); filename = strcat(filename, ".waypoints"); file = fopen(filename, FILE_WRITE); @@ -669,14 +671,14 @@ void waypoint_saveall() } waypoint_save_links(); botframe_loadedforcedlinks = FALSE; -}; +} // load waypoints from file float waypoint_loadall() { - local string filename, s; - local float file, cwp, cwb, fl; - local vector m1, m2; + string filename, s; + float file, cwp, cwb, fl; + vector m1, m2; cwp = 0; cwb = 0; filename = strcat("maps/", mapname); @@ -720,7 +722,7 @@ float waypoint_loadall() dprint(" failed\n"); } return cwp + cwb; -}; +} vector waypoint_fixorigin(vector position) { @@ -734,7 +736,7 @@ vector waypoint_fixorigin(vector position) void waypoint_spawnforitem_force(entity e, vector org) { - local entity w; + entity w; // Fix the waypoint altitude if necessary org = waypoint_fixorigin(org); @@ -770,14 +772,14 @@ void waypoint_spawnforitem(entity e) return; waypoint_spawnforitem_force(e, e.origin); -}; +} -void waypoint_spawnforteleporter(entity e, vector destination, float timetaken) +void waypoint_spawnforteleporter_boxes(entity e, vector org1, vector org2, vector destination1, vector destination2, float timetaken) { - local entity w; - local entity dw; - w = waypoint_spawn(e.absmin, e.absmax, WAYPOINTFLAG_GENERATED | WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_NORELINK); - dw = waypoint_spawn(destination, destination, WAYPOINTFLAG_GENERATED); + entity w; + entity dw; + w = waypoint_spawn(org1, org2, WAYPOINTFLAG_GENERATED | WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_NORELINK); + dw = waypoint_spawn(destination1, destination2, WAYPOINTFLAG_GENERATED); // one way link to the destination w.wp00 = dw; w.wp00mincost = timetaken; // this is just for jump pads @@ -785,7 +787,20 @@ void waypoint_spawnforteleporter(entity e, vector destination, float timetaken) // (teleporters are not goals, so this is probably useless) e.nearestwaypoint = w; e.nearestwaypointtimeout = time + 1000000000; -}; +} + +void waypoint_spawnforteleporter_v(entity e, vector org, vector destination, float timetaken) +{ + org = waypoint_fixorigin(org); + destination = waypoint_fixorigin(destination); + waypoint_spawnforteleporter_boxes(e, org, org, destination, destination, timetaken); +} + +void waypoint_spawnforteleporter(entity e, vector destination, float timetaken) +{ + destination = waypoint_fixorigin(destination); + waypoint_spawnforteleporter_boxes(e, e.absmin, e.absmax, destination, destination, timetaken); +} entity waypoint_spawnpersonal(vector position) { @@ -804,11 +819,11 @@ entity waypoint_spawnpersonal(vector position) waypoint_schedulerelink(w); return w; -}; +} void botframe_showwaypointlinks() { - local entity player, head, w; + entity player, head, w; if (time < botframe_waypointeditorlightningtime) return; botframe_waypointeditorlightningtime = time + 0.5; @@ -861,4 +876,206 @@ void botframe_showwaypointlinks() } player = find(player, classname, "player"); } -}; +} + +float botframe_autowaypoints_fixdown(vector v) +{ + tracebox(v, PL_MIN, PL_MAX, v + '0 0 -64', MOVE_NOMONSTERS, world); + if(trace_fraction >= 1) + return 0; + return 1; +} + +float botframe_autowaypoints_createwp(vector v, entity p, .entity fld) +{ + entity w; + + w = find(world, classname, "waypoint"); + while (w) + { + // if a matching spawnfunc_waypoint already exists, don't add a duplicate + if (boxesoverlap(v - '32 32 32', v + '32 32 32', w.absmin, w.absmax)) + //if (boxesoverlap(v - '4 4 4', v + '4 4 4', w.absmin, w.absmax)) + return 0; + w = find(w, classname, "waypoint"); + } + + waypoint_schedulerelink(p.fld = waypoint_spawn(v, v, 0)); + return 1; +} + +// return value: +// 1 = WP created +// 0 = no action needed +// -1 = temp fail, try from world too +// -2 = permanent fail, do not retry +float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .entity fld) +{ + // make it possible to go from p to wp, if we can + // if wp is world, nearest is chosen + + entity w; + vector porg; + float t, tmin, tmax; + vector o; + vector save; + + if(!botframe_autowaypoints_fixdown(p.origin)) + return -2; + porg = trace_endpos; + + if(wp) + { + // if any WP w fulfills wp -> w -> porg, then switch from wp to w + + // if wp -> porg, then OK + float maxdist; + if(navigation_waypoint_will_link(wp.origin, porg, p, walkfromwp, 1050)) + { + // we may find a better one + maxdist = vlen(wp.origin - porg); + } + else + { + // accept any "good" + maxdist = 2100; + } + + float bestdist; + bestdist = maxdist; + w = find(world, classname, "waypoint"); + while (w) + { + if(w != wp && !(w.wpflags & WAYPOINTFLAG_NORELINK)) + { + float d; + d = vlen(wp.origin - w.origin) + vlen(w.origin - porg); + if(d < bestdist) + if(navigation_waypoint_will_link(wp.origin, w.origin, p, walkfromwp, 1050)) + if(navigation_waypoint_will_link(w.origin, porg, p, walkfromwp, 1050)) + { + bestdist = d; + p.fld = w; + } + } + w = find(w, classname, "waypoint"); + } + if(bestdist < maxdist) + { + print("update chain to new nearest WP ", etos(p.fld), "\n"); + return 0; + } + + if(bestdist < 2100) + { + // we know maxdist < 2100 + // so wp -> porg is still valid + // all is good + p.fld = wp; + return 0; + } + + // otherwise, no existing WP can fix our issues + } + else + { + save = p.origin; + setorigin(p, porg); + w = navigation_findnearestwaypoint(p, walkfromwp); + setorigin(p, save); + if(w) + { + p.fld = w; + return 0; + } + } + + tmin = 0; + tmax = 1; + for(;;) + { + if(tmax - tmin < 0.001) + { + // did not get a good candidate + return -1; + } + + t = (tmin + tmax) * 0.5; + o = antilag_takebackorigin(p, time - t); + if(!botframe_autowaypoints_fixdown(o)) + return -1; + o = trace_endpos; + + if(wp) + { + if(!navigation_waypoint_will_link(wp.origin, o, p, walkfromwp, 1050)) + { + // we cannot walk from wp.origin to o + // get closer to tmax + tmin = t; + continue; + } + } + else + { + save = p.origin; + setorigin(p, o); + w = navigation_findnearestwaypoint(p, walkfromwp); + setorigin(p, save); + if(!w) + { + // we cannot walk from any WP to o + // get closer to tmax + tmin = t; + continue; + } + } + + // if we get here, o is valid regarding waypoints + // check if o is connected right to the player + // we break if it succeeds, as that means o is a good waypoint location + if(navigation_waypoint_will_link(o, porg, p, walkfromwp, 1050)) + break; + + // o is no good, we need to get closer to the player + tmax = t; + } + + print("spawning a waypoint for connecting to ", etos(wp), "\n"); + botframe_autowaypoints_createwp(o, p, fld); + return 1; +} + +// automatically create missing waypoints +.entity botframe_autowaypoints_lastwp0, botframe_autowaypoints_lastwp1; +void botframe_autowaypoints_fix(entity p, float walkfromwp, .entity fld) +{ + float r; + r = botframe_autowaypoints_fix_from(p, walkfromwp, p.fld, fld); + if(r != -1) + return; + r = botframe_autowaypoints_fix_from(p, walkfromwp, world, fld); + if(r != -1) + return; + + print("emergency: got no good nearby WP to build a link from, starting a new chain\n"); + if(!botframe_autowaypoints_fixdown(p.origin)) + return; // shouldn't happen, caught above + botframe_autowaypoints_createwp(trace_endpos, p, fld); +} + +void botframe_autowaypoints() +{ + entity p; + entity wp0, wp1; + FOR_EACH_REALPLAYER(p) + { + if(p.deadflag) + continue; + // going back is broken, so only fix waypoints to walk TO the player + //botframe_autowaypoints_fix(p, FALSE, botframe_autowaypoints_lastwp0); + botframe_autowaypoints_fix(p, TRUE, botframe_autowaypoints_lastwp1); + //te_explosion(p.botframe_autowaypoints_lastwp0.origin); + } +} + diff --git a/qcsrc/server/bot/waypoints.qh b/qcsrc/server/bot/waypoints.qh index 9c84de84bb..fb7beea0fc 100644 --- a/qcsrc/server/bot/waypoints.qh +++ b/qcsrc/server/bot/waypoints.qh @@ -24,7 +24,7 @@ float botframe_cachedwaypointlinks; .float wp16mincost, wp17mincost, wp18mincost, wp19mincost, wp20mincost, wp21mincost, wp22mincost, wp23mincost; .float wp24mincost, wp25mincost, wp26mincost, wp27mincost, wp28mincost, wp29mincost, wp30mincost, wp31mincost; -.float wpfire, wpcost, wpconsidered, wpisbox, wpflags, wplinked; +.float wpfire, wpcost, wpconsidered, wpisbox, wpflags, wplinked, wphardwired; .vector wpnearestpoint; @@ -57,3 +57,5 @@ entity waypoint_spawn(vector m1, vector m2, float f); entity waypoint_spawnpersonal(vector position); vector waypoint_fixorigin(vector position); + +void botframe_autowaypoints(); diff --git a/qcsrc/server/builtins.qh b/qcsrc/server/builtins.qh index ef54b1d38f..e69de29bb2 100644 --- a/qcsrc/server/builtins.qh +++ b/qcsrc/server/builtins.qh @@ -1,72 +0,0 @@ - -void makevectors (vector ang) = #1; -void setorigin (entity e, vector o) = #2; -void setmodel (entity e, string m) = #3; -void setsize (entity e, vector min, vector max) = #4; - -void crash (void) = #6; -float random (void) = #7; -//void(entity e, float chan, string samp, float vol, float atten) sound = #8; -vector normalize (vector v) = #9; -void error (string e) = #10; -void objerror_builtin (string e) = #11; // do not call, use objerror wrapper -float vlen (vector v) = #12; -float vectoyaw (vector v) = #13; -entity spawn (void) = #14; -void remove_builtin (entity e) = #15; -void traceline (vector v1, vector v2, float nomonst, entity forent) = #16; -entity checkclient (void) = #17; -entity find (entity start, .string fld, string match) = #18; -//string precache_sound (string s) = #19; -string precache_model (string s) = #20; -void(entity client, string s) stuffcmd = #21; -entity findradius (vector org, float rad) = #22; -void bprint (string s, ...) = #23; -void(entity client, string s) sprint = #24; -void dprint (string s, ...) = #25; -string ftos (float f) = #26; -string vtos (vector v) = #27; -void coredump (void) = #28; -void traceon (void) = #29; -void traceoff (void) = #30; -void eprint (entity e) = #31; -float walkmove (float yaw, float dist) = #32; - -float droptofloor_builtin () = #34; -void lightstyle (float style, string value) = #35; -float rint (float v) = #36; -float floor (float v) = #37; -float ceil (float v) = #38; - -float checkbottom (entity e) = #40; -float pointcontents (vector v) = #41; - -float fabs (float f) = #43; -vector(entity e, float speed) aim = #44; -float cvar (string s) = #45; -void localcmd (string s, ...) = #46; -entity nextent (entity e) = #47; -void particle (vector v, vector d, float colour, float count) = #48; -void ChangeYaw (void) = #49; - -vector vectoangles (vector v, ...) = #51; -void(float to, float f) WriteByte = #52; -void(float to, float f) WriteChar = #53; -void(float to, float f) WriteShort = #54; -void(float to, float f) WriteLong = #55; -void(float to, float f) WriteCoord = #56; -void(float to, float f) WriteAngle = #57; -void(float to, string s) WriteString = #58; -void(float to, entity s) WriteEntity = #59; -void movetogoal (float step) = #67; -string precache_file (string s) = #68; -void makestatic (entity e) = #69; -void changelevel (string s) = #70; - -void cvar_set (string var, string val) = #72; -//void(entity client, string s) centerprint = #73; -void ambientsound (vector pos, string samp, float vol, float atten) = #74; -string precache_model2 (string s) = #75; -string precache_sound2 (string s) = #76; -string precache_file2 (string s) = #77; -void(entity e) setspawnparms = #78; diff --git a/qcsrc/server/campaign.qc b/qcsrc/server/campaign.qc index 9a36546716..5a68e96058 100644 --- a/qcsrc/server/campaign.qc +++ b/qcsrc/server/campaign.qc @@ -108,7 +108,7 @@ void CampaignPreInit() title = campaign_shortdesc[0]; title = strzone(strcat("Level ", ftos(campaign_level + 1), ": ", title)); - campaign_message = strzone(strcat("\n\n\n\n\n\n\n\n\n\n^1\n", title, "\n^3\n", campaign_longdesc[0], "\n\n^1press jump to enter the game")); + campaign_message = strzone(strcat(title, "\n^3\n", campaign_longdesc[0], "\n\n^1press jump to enter the game")); strunzone(title); } @@ -169,7 +169,7 @@ void CampaignPreIntermission() entity head; float won; float lost; - local string savevar; + string savevar; won = 0; @@ -219,10 +219,13 @@ void CampaignPreIntermission() if(campaign_entries < 2) { // I have won - savevar = strcat("g_campaign", campaign_name, "_won"); - CampaignSaveCvar(savevar, 1); - // advance level (for menu to show it right) - CampaignSaveCvar(campaign_index_var, campaign_level + 1); + if(campaign_level == cvar_normal(campaign_index_var)) + { + savevar = strcat("g_campaign", campaign_name, "_won"); + CampaignSaveCvar(savevar, 1); + // advance level (for menu to show it right) + CampaignSaveCvar(campaign_index_var, campaign_level + 1); + } } else if(campaign_level == cvar_normal(campaign_index_var)) { @@ -256,6 +259,8 @@ void CampaignPostIntermission() void CampaignLevelWarp(float n) { + if(n < 0) + n = campaign_level + 1; CampaignFile_Unload(); CampaignFile_Load(n, 1); if(campaign_entries) diff --git a/qcsrc/server/cheats.qc b/qcsrc/server/cheats.qc index fc54d49148..57a09fe380 100644 --- a/qcsrc/server/cheats.qc +++ b/qcsrc/server/cheats.qc @@ -89,8 +89,7 @@ float CheatsAllowed(float i, float argc, float fr) // the cheat gets passed as a ADD_CHEATS(self,cheating); \ return attempting #define IS_CHEAT(i,argc,fr) \ - ++attempting; \ - if(!CheatsAllowed(i,argc,fr)) \ + if((++attempting, !CheatsAllowed(i,argc,fr))) \ break float CheatImpulse(float i) @@ -229,7 +228,7 @@ float CheatImpulse(float i) IS_CHEAT(i, 0, 0); FOR_EACH_PLAYER(e) { - get_model_parameters(e.playermodel, e.skinindex); + get_model_parameters(e.playermodel, e.skin); if(get_model_parameters_sex == "Female") { makevectors(e.angles); @@ -249,7 +248,7 @@ float CheatImpulse(float i) e2 = spawn(); setorigin(e2, org); pointparticles(particleeffectnum("rocket_explode"), org, '0 0 0', 1); - sound(e2, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); + sound(e2, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); RadiusDamage(e2, e, 1000, 0, 128, e, 500, DEATH_CHEAT, world); remove(e2); } @@ -303,7 +302,7 @@ float CheatCommand(float argc) // arguments: // effectname effectnum = particleeffectnum(argv(1)); - W_SetupShot(self, FALSE, FALSE, "", CHAN_WEAPON, 0); + W_SetupShot(self, FALSE, FALSE, "", CH_WEAPON_A, 0); traceline(w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, MOVE_NORMAL, self); trailparticles(self, effectnum, w_shotorg, trace_endpos); DID_CHEAT(); @@ -318,7 +317,7 @@ float CheatCommand(float argc) // arguments: // modelname mode f = stof(argv(2)); - W_SetupShot(self, FALSE, FALSE, "", CHAN_WEAPON, 0); + W_SetupShot(self, FALSE, FALSE, "", CH_WEAPON_A, 0); traceline(w_shotorg, w_shotorg + w_shotdir * 2048, MOVE_NORMAL, self); if((trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT) || trace_fraction == 1) { @@ -604,14 +603,6 @@ float CheatCommand(float argc) remove(e); DID_CHEAT(); break; - case "warp": - IS_CHEAT(0, argc, 0); - if(argc == 2) if(autocvar_g_campaign) - { - CampaignLevelWarp(stof(argv(1))); - DID_CHEAT(); - } - break; case "god": IS_CHEAT(0, argc, 0); BITXOR_ASSIGN(self.flags, FL_GODMODE); @@ -672,7 +663,7 @@ float CheatCommand(float argc) END_CHEAT_FUNCTION(); } -void crosshair_trace_plusvisibletriggers(entity pl); +float Drag(entity e, float grab, float ischeat); void Drag_Begin(entity dragger, entity draggee, vector touchpoint); void Drag_Finish(entity dragger); float Drag_IsDraggable(entity draggee); @@ -690,58 +681,53 @@ float CheatFrame() { BEGIN_CHEAT_FUNCTION(); - if(Drag_IsDragging(self)) + // Dragging can be used as either a cheat, or a function for some objects. If sv_cheats is active, + // the cheat dragging is used (unlimited pickup range and any entity can be carried). If sv_cheats + // is disabled, normal dragging is used (limited pickup range and only dragable objects can be carried), + // grabbing itself no longer being accounted as cheating. + + switch(0) { - if(self.BUTTON_DRAG) - { - if(self.impulse == 10 || self.impulse == 15 || self.impulse == 18) - { - Drag_MoveForward(self); - self.impulse = 0; - } - else if(self.impulse == 12 || self.impulse == 16 || self.impulse == 19) - { - Drag_MoveBackward(self); - self.impulse = 0; - } - else if(self.impulse >= 1 && self.impulse <= 9) + default: + if(self.maycheat || (gamestart_sv_cheats && autocvar_sv_cheats)) { - Drag_SetSpeed(self, self.impulse - 1); + // use cheat dragging if cheats are enabled + crosshair_trace_plusvisibletriggers(self); + Drag(trace_ent, TRUE, TRUE); } - else if(self.impulse == 14) + else { - Drag_SetSpeed(self, 9); - } + // drag is TRUE if the object can be picked up. While an object is being carried, the Drag() function + // must execute for it either way, otherwise it would cause bugs if it went out of the player's trace. + // This also makes sure that an object can only pe picked up if in range, but does not get dropped if + // it goes out of range while slinging it around. - if(frametime) - Drag_Update(self); - } - else - { - Drag_Finish(self); - } - } - else - { - if(Drag_CanDrag(self)) - if(self.BUTTON_DRAG) - { + float drag; crosshair_trace_plusvisibletriggers(self); - if(trace_ent) - if(Drag_IsDraggable(trace_ent)) - switch(0) - { - default: - IS_CHEAT(0, 0, CHRAME_DRAG); - if(trace_ent.draggedby) - Drag_Finish(trace_ent.draggedby); - if(trace_ent.tag_entity) - detach_sameorigin(trace_ent); - Drag_Begin(self, trace_ent, trace_endpos); - DID_CHEAT(); - break; - } + if(vlen(self.origin - trace_ent.origin) <= autocvar_g_grab_range) + { + switch(trace_ent.grab) + { + case 0: // can't grab + break; + case 1: // owner can grab + if(trace_ent.owner == self || trace_ent.realowner == self) + drag = TRUE; + break; + case 2: // owner and team mates can grab + if(!IsDifferentTeam(trace_ent.owner, self) || !IsDifferentTeam(trace_ent.realowner, self) || trace_ent.team == self.team) + drag = TRUE; + break; + case 3: // anyone can grab + drag = TRUE; + break; + default: + break; + } + } + Drag(trace_ent, drag, FALSE); // execute dragging } + break; } END_CHEAT_FUNCTION(); @@ -753,20 +739,72 @@ float CheatFrame() // ENTITY DRAGGING -void crosshair_trace_plusvisibletriggers(entity pl) +float Drag(entity e, float pick, float ischeat) { - entity first; - entity e; - first = findchainfloat(solid, SOLID_TRIGGER); + BEGIN_CHEAT_FUNCTION(); - for (e = first; e; e = e.chain) - if (e.model != "") - e.solid = SOLID_BSP; + // returns TRUE when an entity has been picked up + // If pick is TRUE, the object can also be picked up if it's not being held already + // If pick is FALSE, only keep dragging the object if it's already being held - crosshair_trace(pl); + switch(0) + { + default: + if(Drag_IsDragging(self)) + { + if(self.BUTTON_DRAG) + { + if(self.impulse == 10 || self.impulse == 15 || self.impulse == 18) + { + Drag_MoveForward(self); + self.impulse = 0; + } + else if(self.impulse == 12 || self.impulse == 16 || self.impulse == 19) + { + Drag_MoveBackward(self); + self.impulse = 0; + } + else if(self.impulse >= 1 && self.impulse <= 9) + { + Drag_SetSpeed(self, self.impulse - 1); + } + else if(self.impulse == 14) + { + Drag_SetSpeed(self, 9); + } - for (e = first; e; e = e.chain) - e.solid = SOLID_TRIGGER; + if(frametime) + Drag_Update(self); + } + else + { + Drag_Finish(self); + } + } + else + { + if(Drag_CanDrag(self)) + if(self.BUTTON_DRAG && pick) + { + if(e) + if(Drag_IsDraggable(e)) + { + if(ischeat) + IS_CHEAT(0, 0, CHRAME_DRAG); + if(e.draggedby) + Drag_Finish(e.draggedby); + if(e.tag_entity) + detach_sameorigin(e); + Drag_Begin(self, e, trace_endpos); + if(ischeat) + DID_CHEAT(); + return TRUE; + } + } + } + break; + } + return FALSE; } // on dragger: @@ -837,6 +875,8 @@ void Drag_Finish(entity dragger) float Drag_IsDraggable(entity draggee) { // TODO add more checks for bad stuff here + if(draggee == world) + return FALSE; if(draggee.classname == "func_bobbing") return FALSE; if(draggee.classname == "door") // FIXME find out why these must be excluded, or work around the problem (trying to drag these causes like 4 fps) @@ -945,11 +985,6 @@ void Drag_MoveDrag(entity from, entity to) } } - - - - - void DragBox_Think() { if(self.aiment && self.enemy) diff --git a/qcsrc/server/cl_client.qc b/qcsrc/server/cl_client.qc index fea11ec930..298fd47e3c 100644 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@ -2,15 +2,8 @@ void race_send_recordtime(float msg); void race_SendRankings(float pos, float prevpos, float del, float msg); void send_CSQC_teamnagger() { - WriteByte(0, SVC_TEMPENTITY); - WriteByte(0, TE_CSQC_TEAMNAGGER); -} - -void send_CSQC_cr_maxbullets(entity e) { - msg_entity = e; - WriteByte(MSG_ONE, SVC_TEMPENTITY); - WriteByte(MSG_ONE, TE_CSQC_CR_MAXBULLETS); - WriteByte(MSG_ONE, autocvar_g_balance_campingrifle_magazinecapacity); + WriteByte(MSG_BROADCAST, SVC_TEMPENTITY); + WriteByte(MSG_BROADCAST, TE_CSQC_TEAMNAGGER); } void Announce(string snd) { @@ -119,18 +112,18 @@ void spawnfunc_info_player_deathmatch (void) void spawnpoint_use() { - if(teams_matter) + if(teamplay) if(have_team_spawns > 0) { self.team = activator.team; some_spawn_has_been_used = 1; } -}; +} // Returns: // _x: prio (-1 if unusable) // _y: weight -vector Spawn_Score(entity spot, entity playerlist, float teamcheck, float anypoint) +vector Spawn_Score(entity spot, float mindist, float teamcheck) { float shortest, thisdist; float prio; @@ -139,9 +132,9 @@ vector Spawn_Score(entity spot, entity playerlist, float teamcheck, float anypoi prio = 0; // filter out spots for the wrong team - if(teamcheck) - if(spot.team != teamcheck) - return '-1 0 0'; + if(teamcheck >= 0) + if(spot.team != teamcheck) + return '-1 0 0'; if(race_spawns) if(spot.target == "") @@ -158,147 +151,80 @@ vector Spawn_Score(entity spot, entity playerlist, float teamcheck, float anypoi return '-1 0 0'; } + shortest = vlen(world.maxs - world.mins); + FOR_EACH_PLAYER(player) if (player != self) + { + thisdist = vlen(player.origin - spot.origin); + if (thisdist < shortest) + shortest = thisdist; + } + if(shortest > mindist) + prio += SPAWN_PRIO_GOOD_DISTANCE; + + spawn_score = prio * '1 0 0' + shortest * '0 1 0'; + spawn_spot = spot; + // filter out spots for assault if(spot.target != "") { - local entity ent; - float good, found; - ent = find(world, targetname, spot.target); + entity ent; + float found; - while(ent) { - if(ent.classname == "target_objective") + found = 0; + for(ent = world; (ent = find(ent, targetname, spot.target)); ) + { + ++found; + if(ent.spawn_evalfunc) { - found = 1; - if(ent.health < 0 || ent.health >= ASSAULT_VALUE_INACTIVE) - return '-1 0 0'; - good = 1; + entity oldself = self; + self = ent; + spawn_score = ent.spawn_evalfunc(oldself, spot, spawn_score); + self = oldself; + if(spawn_score_x < 0) + return spawn_score; } - else if(ent.classname == "trigger_race_checkpoint") - { - found = 1; - if(!anypoint) // spectators may spawn everywhere - - { - if(g_race_qualifying) - { - // spawn at first - if(ent.race_checkpoint != 0) - return '-1 0 0'; - if(spot.race_place != race_lowest_place_spawn) - return '-1 0 0'; - } - else - { - if(ent.race_checkpoint != self.race_respawn_checkpoint) - return '-1 0 0'; - // try reusing the previous spawn - if(ent == self.race_respawn_spotref || spot == self.race_respawn_spotref) - prio += 1; - if(ent.race_checkpoint == 0) - { - float pl; - pl = self.race_place; - if(pl > race_highest_place_spawn) - pl = 0; - if(pl == 0 && !self.race_started) - pl = race_highest_place_spawn; // use last place if he has not even touched finish yet - if(spot.race_place != pl) - return '-1 0 0'; - } - } - } - good = 1; - } - ent = find(ent, targetname, spot.target); } - if(found && !good) + if(!found) + { + dprint("WARNING: spawnpoint at ", vtos(spot.origin), " could not find its target ", spot.target, "\n"); return '-1 0 0'; + } } - player = playerlist; - shortest = vlen(world.maxs - world.mins); - for(player = playerlist; player; player = player.chain) - if (player != self) - { - thisdist = vlen(player.origin - spot.origin); - if (thisdist < shortest) - shortest = thisdist; - } - return prio * '1 0 0' + shortest * '0 1 0'; + MUTATOR_CALLHOOK(Spawn_Score); + return spawn_score; +} + +void Spawn_ScoreAll(entity firstspot, float mindist, float teamcheck) +{ + entity spot; + for(spot = firstspot; spot; spot = spot.chain) + spot.spawnpoint_score = Spawn_Score(spot, mindist, teamcheck); } -float spawn_allbad; -float spawn_allgood; -entity Spawn_FilterOutBadSpots(entity firstspot, entity playerlist, float mindist, float teamcheck, float anypoint) +entity Spawn_FilterOutBadSpots(entity firstspot, float mindist, float teamcheck) { - local entity spot, spotlist, spotlistend; - spawn_allgood = TRUE; - spawn_allbad = TRUE; + entity spot, spotlist, spotlistend; spotlist = world; spotlistend = world; + Spawn_ScoreAll(firstspot, mindist, teamcheck); + for(spot = firstspot; spot; spot = spot.chain) { - spot.spawnpoint_score = Spawn_Score(spot, playerlist, teamcheck, anypoint); - - if(autocvar_spawn_debugview) - { - setmodel(spot, "models/runematch/rune.mdl"); - if(spot.spawnpoint_score_y < mindist) - { - spot.colormod = '1 0 0'; - spot.scale = 1; - } - else - { - spot.colormod = '0 1 0'; - spot.scale = spot.spawnpoint_score_y / mindist; - } - } - if(spot.spawnpoint_score_x >= 0) // spawning allowed here { - if(spot.spawnpoint_score_y < mindist) - { - // too short distance - spawn_allgood = FALSE; - } - else - { - // perfect - spawn_allbad = FALSE; - - if(spotlistend) - spotlistend.chain = spot; - spotlistend = spot; - if(!spotlist) - spotlist = spot; - - /* - if(teamcheck) - if(spot.team != teamcheck) - error("invalid spawn added"); - - print("added ", etos(spot), "\n"); - */ - } + if(spotlistend) + spotlistend.chain = spot; + spotlistend = spot; + if(!spotlist) + spotlist = spot; } } if(spotlistend) spotlistend.chain = world; - /* - entity e; - if(teamcheck) - for(e = spotlist; e; e = e.chain) - { - print("seen ", etos(e), "\n"); - if(e.team != teamcheck) - error("invalid spawn found"); - } - */ - return spotlist; } @@ -306,7 +232,7 @@ entity Spawn_WeightedPoint(entity firstspot, float lower, float upper, float exp { // weight of a point: bound(lower, mindisttoplayer, upper)^exponent // multiplied by spot.cnt (useful if you distribute many spawnpoints in a small area) - local entity spot; + entity spot; RandomSelection_Init(); for(spot = firstspot; spot; spot = spot.chain) @@ -324,21 +250,38 @@ Finds a point to respawn */ entity SelectSpawnPoint (float anypoint) { - local float teamcheck; - local entity firstspot_new; - local entity spot, firstspot, playerlist; + float teamcheck; + entity spot, firstspot; spot = find (world, classname, "testplayerstart"); if (spot) return spot; - teamcheck = 0; + if(anypoint || autocvar_g_spawn_useallspawns) + teamcheck = -1; + else if(have_team_spawns > 0) + { + if(have_team_spawns_forteam[self.team] == 0) + { + // we request a spawn for a team, and we have team + // spawns, but that team has no spawns? + if(have_team_spawns_forteam[0]) + // try noteam spawns + teamcheck = 0; + else + // if not, any spawn has to do + teamcheck = -1; + } + else + teamcheck = self.team; // MUST be team + } + else if(have_team_spawns == 0 && have_team_spawns_forteam[0]) + teamcheck = 0; // MUST be noteam + else + teamcheck = -1; + // if we get here, we either require team spawns but have none, or we require non-team spawns and have none; use any spawn then - if(!anypoint && have_team_spawns > 0) - teamcheck = self.team; - // get the list of players - playerlist = findchain(classname, "player"); // get the entire list of spots firstspot = findchain(classname, "info_player_deathmatch"); // filter out the bad ones @@ -349,42 +292,26 @@ entity SelectSpawnPoint (float anypoint) } else { - firstspot_new = Spawn_FilterOutBadSpots(firstspot, playerlist, 100, teamcheck, anypoint); - if(!firstspot_new) - firstspot_new = Spawn_FilterOutBadSpots(firstspot, playerlist, -1, teamcheck, anypoint); - firstspot = firstspot_new; + float mindist; + if (arena_roundbased && !g_ca) + mindist = 800; + else + mindist = 100; + firstspot = Spawn_FilterOutBadSpots(firstspot, mindist, teamcheck); // there is 50/50 chance of choosing a random spot or the furthest spot // (this means that roughly every other spawn will be furthest, so you // usually won't get fragged at spawn twice in a row) - if (arena_roundbased && !g_ca) - { - firstspot_new = Spawn_FilterOutBadSpots(firstspot, playerlist, 800, teamcheck, anypoint); - if(firstspot_new) - firstspot = firstspot_new; - spot = Spawn_WeightedPoint(firstspot, 1, 1, 1); - } - else if (random() > autocvar_g_spawn_furthest) + if (random() > autocvar_g_spawn_furthest) spot = Spawn_WeightedPoint(firstspot, 1, 1, 1); else spot = Spawn_WeightedPoint(firstspot, 1, 5000, 5); // chooses a far far away spawnpoint } - if(autocvar_spawn_debugview) - { - print("spot mindistance: ", vtos(spot.spawnpoint_score), "\n"); - - entity e; - if(teamcheck) - for(e = firstspot; e; e = e.chain) - if(e.team != teamcheck) - error("invalid spawn found"); - } - if (!spot) { if(autocvar_spawn_debug) - GotoNextMap(); + GotoNextMap(0); else { if(some_spawn_has_been_used) @@ -414,160 +341,36 @@ string CheckPlayerModel(string plyermodel) { // to change a cvar default, we'll have a small leak here. FallbackPlayerModel = strzone(cvar_defstring("_cl_playermodel")); } - if(strlen(plyermodel) < 4) - return FallbackPlayerModel; + // only in right path if( substring(plyermodel,0,14) != "models/player/") return FallbackPlayerModel; - else if(autocvar_sv_servermodelsonly) + // only good file extensions + if(substring(plyermodel,-4,4) != ".zym") + if(substring(plyermodel,-4,4) != ".dpm") + if(substring(plyermodel,-4,4) != ".iqm") + if(substring(plyermodel,-4,4) != ".md3") + if(substring(plyermodel,-4,4) != ".psk") + return FallbackPlayerModel; + // forbid the LOD models + if(substring(plyermodel, -9,5) == "_lod1") + return FallbackPlayerModel; + if(substring(plyermodel, -9,5) == "_lod2") + return FallbackPlayerModel; + if(plyermodel != strtolower(plyermodel)) + return FallbackPlayerModel; + // also, restrict to server models + if(autocvar_sv_servermodelsonly) { - if(substring(plyermodel,-4,4) != ".zym") - if(substring(plyermodel,-4,4) != ".dpm") - if(substring(plyermodel,-4,4) != ".iqm") - if(substring(plyermodel,-4,4) != ".md3") - if(substring(plyermodel,-4,4) != ".psk") - return FallbackPlayerModel; - // forbid the LOD models - if(substring(plyermodel, -9,5) == "_lod1") - return FallbackPlayerModel; - if(substring(plyermodel, -9,5) == "_lod2") - return FallbackPlayerModel; - if(plyermodel != strtolower(plyermodel)) - return FallbackPlayerModel; if(!fexists(plyermodel)) return FallbackPlayerModel; } return plyermodel; } -/* -============= -Client_customizeentityforclient - -LOD reduction -============= -*/ -void Client_uncustomizeentityforclient() -{ - if(self.modelindex == 0) // no need to uncustomize then - return; - self.modelindex = self.modelindex_lod0; - self.skin = self.skinindex; -} - -float Client_customizeentityforclient() -{ - entity modelsource; - - if(self.modelindex == 0) - return TRUE; - - // forcemodel stuff - -#ifdef PROFILING - float t0; - t0 = gettime(GETTIME_HIRES); // reference -#endif - - modelsource = self; - -#ifdef ALLOW_FORCEMODELS - if(other.cvar_cl_forceplayermodelsfromxonotic) - if not(self.modelindex_lod0_from_xonotic) - modelsource = other; - if(other.cvar_cl_forceplayermodels && sv_clforceplayermodels) - modelsource = other; -#endif - - self.skin = modelsource.skinindex; - -#if 0 - if(modelsource == self) - self.skin = modelsource.skinindex; - else - self.skin = mod(modelsource.skinindex, 3); // forbid the fbskins as forced skins -#endif - - // self: me - // other: the player viewing me - float distance; - float f; - - if(other.cvar_cl_playerdetailreduction <= 0) - { - if(other.cvar_cl_playerdetailreduction <= -2) - self.modelindex = modelsource.modelindex_lod2; - else if(other.cvar_cl_playerdetailreduction <= -1) - self.modelindex = modelsource.modelindex_lod1; - else - self.modelindex = modelsource.modelindex_lod0; - } - else - { - distance = vlen(self.origin - other.origin); - f = (distance + 100.0) * other.cvar_cl_playerdetailreduction; - if(f > sv_loddistance2) - self.modelindex = modelsource.modelindex_lod2; - else if(f > sv_loddistance1) - self.modelindex = modelsource.modelindex_lod1; - else - self.modelindex = modelsource.modelindex_lod0; - } - -#ifdef PROFILING - float t1; - t1 = gettime(GETTIME_HIRES); // reference - client_cefc_accumulator += (t1 - t0); -#endif - - return TRUE; -} - -void setmodel_lod(entity e, string modelname) +void setplayermodel(entity e, string modelname) { - string s; - - if(sv_loddistance1) - { - // FIXME: this only supports 3-letter extensions - s = strcat(substring(modelname, 0, strlen(modelname)-4), "_lod1", substring(modelname, -4, 4)); - if(fexists(s)) - { - setmodel(e, s); // players have high precision - self.modelindex_lod1 = self.modelindex; - } - else - self.modelindex_lod1 = -1; - - s = strcat(substring(modelname, 0, strlen(modelname)-4), "_lod2", substring(modelname, -4, 4)); - if(fexists(s)) - { - setmodel(e, s); // players have high precision - self.modelindex_lod2 = self.modelindex; - } - else - self.modelindex_lod2 = -1; - - precache_model(modelname); - setmodel(e, modelname); // players have high precision - self.modelindex_lod0 = self.modelindex; - - if(self.modelindex_lod1 < 0) - self.modelindex_lod1 = self.modelindex; - - if(self.modelindex_lod2 < 0) - self.modelindex_lod2 = self.modelindex; - } - else - { - precache_model(modelname); - setmodel(e, modelname); // players have high precision - self.modelindex_lod0 = self.modelindex; - // save it for possible player model forcing - } - - s = whichpack(self.model); - self.modelindex_lod0_from_xonotic = ((s == "") || (substring(s, 0, 4) == "data")); - + precache_model(modelname); + setmodel(e, modelname); player_setupanimsformodel(); UpdatePlayerSounds(); } @@ -583,7 +386,7 @@ void FixPlayermodel(); void PutObserverInServer (void) { entity spot; - + self.hud = HUD_NORMAL; race_PreSpawnObserver(); spot = SelectSpawnPoint (TRUE); @@ -601,6 +404,9 @@ void PutObserverInServer (void) DropAllRunes(self); MUTATOR_CALLHOOK(MakePlayerObserver); + if (g_minstagib) + minstagib_stop_countdown(); + Portal_ClearAll(self); if(self.alivetime) @@ -609,6 +415,9 @@ void PutObserverInServer (void) self.alivetime = 0; } + if(self.vehicle) + vehicles_exit(VHEF_RELESE); + if(self.flagcarried) DropFlag(self.flagcarried, world, world); @@ -640,13 +449,14 @@ void PutObserverInServer (void) accuracy_resend(self); self.spectatortime = time; - + self.classname = "observer"; self.iscreature = FALSE; + self.damagedbycontents = FALSE; self.health = -666; self.takedamage = DAMAGE_NO; self.solid = SOLID_NOT; - self.movetype = MOVETYPE_NOCLIP; + self.movetype = MOVETYPE_FLY_WORLDONLY; // user preference is controlled by playerprethink self.flags = FL_CLIENT | FL_NOTARGET; self.armorvalue = 666; self.effects = 0; @@ -656,7 +466,7 @@ void PutObserverInServer (void) self.pauseregen_finished = 0; self.damageforcescale = 0; self.death_time = 0; - self.dead_frame = 0; + self.respawn_time = 0; self.alpha = 0; self.scale = 0; self.fade_time = 0; @@ -675,17 +485,21 @@ void PutObserverInServer (void) self.fixangle = TRUE; self.crouch = FALSE; - self.view_ofs = PL_VIEW_OFS; - setorigin (self, spot.origin); - setsize (self, '0 0 0', '0 0 0'); + setorigin (self, (spot.origin + PL_VIEW_OFS)); // offset it so that the spectator spawns higher off the ground, looks better this way self.prevorigin = self.origin; self.items = 0; self.weapons = 0; self.model = ""; FixPlayermodel(); - self.model = ""; - self.modelindex = 0; + setmodel(self, "null"); + self.drawonlytoclient = self; + + setsize (self, PL_CROUCH_MIN, PL_CROUCH_MAX); // give the spectator some space between walls for MOVETYPE_FLY_WORLDONLY + self.view_ofs = '0 0 0'; // so that your view doesn't go into the ceiling with MOVETYPE_FLY_WORLDONLY, previously "PL_VIEW_OFS" + self.weapon = 0; + self.weaponname = ""; + self.switchingweapon = 0; self.weaponmodel = ""; self.weaponentity = world; self.exteriorweaponentity = world; @@ -697,9 +511,6 @@ void PutObserverInServer (void) self.oldvelocity = self.velocity; self.fire_endtime = -1; - if(sv_loddistance1) - SetCustomizer(self, Client_customizeentityforclient, Client_uncustomizeentityforclient); - if(g_arena) { if(self.version_mismatch) @@ -720,22 +531,31 @@ void PutObserverInServer (void) else self.frags = FRAGS_LMS_LOSER; } + else if(g_ca) + { + if(self.caplayer) + self.frags = FRAGS_LMS_LOSER; + else + self.frags = FRAGS_SPECTATOR; + } else self.frags = FRAGS_SPECTATOR; } +.float model_randomizer; void FixPlayermodel() { - local string defaultmodel; - local float defaultskin, chmdl, oldskin; - local vector m1, m2; + string defaultmodel; + float defaultskin, chmdl, oldskin, n, i; + vector m1, m2; defaultmodel = ""; - if(autocvar_sv_defaultcharacter == 1) { + if(autocvar_sv_defaultcharacter == 1) + { defaultskin = 0; - if(teams_matter) + if(teamplay) { string s; s = Team_ColorNameLowerCase(self.team); @@ -751,13 +571,17 @@ void FixPlayermodel() defaultmodel = autocvar_sv_defaultplayermodel; defaultskin = autocvar_sv_defaultplayerskin; } - } - if(self.modelindex == 0 && self.deadflag == DEAD_NO) - { - if(self.model != "") - bprint("\{1}^1Player ", self.netname, "^1 has a zero modelindex, trying to fix...\n"); - self.model = ""; // force the != checks to return true + n = tokenize_console(defaultmodel); + if(n > 0) + defaultmodel = argv(floor(n * self.model_randomizer)); + + i = strstrofs(defaultmodel, ":", 0); + if(i >= 0) + { + defaultskin = stof(substring(defaultmodel, i+1, -1)); + defaultmodel = substring(defaultmodel, 0, i); + } } if(defaultmodel != "") @@ -766,32 +590,32 @@ void FixPlayermodel() { m1 = self.mins; m2 = self.maxs; - setmodel_lod (self, defaultmodel); + setplayermodel (self, defaultmodel); setsize (self, m1, m2); chmdl = TRUE; } - oldskin = self.skinindex; - self.skinindex = defaultskin; + oldskin = self.skin; + self.skin = defaultskin; } else { if (self.playermodel != self.model || self.playermodel == "") { self.playermodel = CheckPlayerModel(self.playermodel); // this is never "", so no endless loop m1 = self.mins; m2 = self.maxs; - setmodel_lod (self, self.playermodel); + setplayermodel (self, self.playermodel); setsize (self, m1, m2); chmdl = TRUE; } - oldskin = self.skinindex; - self.skinindex = stof(self.playerskin); + oldskin = self.skin; + self.skin = stof(self.playerskin); } - if(chmdl || oldskin != self.skinindex) + if(chmdl || oldskin != self.skin) self.species = player_getspecies(); // model or skin has changed - if(!teams_matter) + if(!teamplay) if(strlen(autocvar_sv_defaultplayercolors)) if(self.clientcolors != stof(autocvar_sv_defaultplayercolors)) setcolor(self, stof(autocvar_sv_defaultplayercolors)); @@ -832,6 +656,9 @@ void PutClientInServer (void) WriteByte(MSG_ONE, SVC_SETVIEW); WriteEntity(MSG_ONE, self); } + + // reset player keys + self.itemkeys = 0; // player is dead and becomes observer // FIXME fix LMS scoring for new system @@ -871,6 +698,7 @@ void PutClientInServer (void) self.classname = "player"; self.wasplayer = TRUE; self.iscreature = TRUE; + self.damagedbycontents = TRUE; self.movetype = MOVETYPE_WALK; self.solid = SOLID_SLIDEBOX; self.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_SOLID; @@ -879,14 +707,17 @@ void PutClientInServer (void) if(clienttype(self) == CLIENTTYPE_BOT && autocvar_g_botclip_collisions) self.dphitcontentsmask |= DPCONTENTS_BOTCLIP; self.frags = FRAGS_PLAYER; - if(independent_players) + if(INDEPENDENT_PLAYERS) MAKE_INDEPENDENT_PLAYER(self); self.flags = FL_CLIENT; + if(autocvar__notarget) + self.flags |= FL_NOTARGET; self.takedamage = DAMAGE_AIM; if(g_minstagib) self.effects = EF_FULLBRIGHT; else self.effects = 0; + self.effects |= EF_TELEPORT_BIT | EF_RESTARTANIM_BIT; self.air_finished = time + 12; self.dmg = 2; if(autocvar_g_balance_nex_charge) @@ -929,7 +760,6 @@ void PutClientInServer (void) } self.items = start_items; - self.jump_interval = time; self.spawnshieldtime = time + autocvar_g_spawnshieldtime; self.pauserotarmor_finished = time + autocvar_g_balance_pause_armor_rot_spawn; @@ -945,8 +775,7 @@ void PutClientInServer (void) } self.damageforcescale = 2; self.death_time = 0; - self.dead_frame = 0; - self.alpha = 0; + self.respawn_time = 0; self.scale = 0; self.fade_time = 0; self.pain_frame = 0; @@ -984,11 +813,9 @@ void PutClientInServer (void) WriteByte(MSG_ONE, TE_CSQC_SPAWN); }); - if(sv_loddistance1) - SetCustomizer(self, Client_customizeentityforclient, Client_uncustomizeentityforclient); - self.model = ""; FixPlayermodel(); + self.drawonlytoclient = world; self.crouch = FALSE; self.view_ofs = PL_VIEW_OFS; @@ -999,7 +826,9 @@ void PutClientInServer (void) self.oldorigin = self.origin; self.prevorigin = self.origin; self.lastrocket = world; // stop rocket guiding, no revenge from the grave! - + self.lastteleporttime = time; // prevent insane speeds due to changing origin + self.hud = HUD_NORMAL; + if(g_arena) { Spawnqueue_Remove(self); @@ -1021,8 +850,6 @@ void PutClientInServer (void) self.killcount = 0; } - self.cnt = WEP_LASER; - CL_SpawnWeaponentity(); self.alpha = default_player_alpha; self.colormod = '1 1 1' * autocvar_g_player_brightness; @@ -1034,17 +861,11 @@ void PutClientInServer (void) race_PostSpawn(spot); - if(autocvar_spawn_debug) - { - sprint(self, strcat("spawnpoint origin: ", vtos(spot.origin), "\n")); - remove(spot); // usefull for checking if there are spawnpoints, that let drop through the floor - } - //stuffcmd(self, "chase_active 0"); //stuffcmd(self, "set viewsize $tmpviewsize \n"); if (autocvar_g_spawnsound) - sound (self, CHAN_TRIGGER, "misc/spawn.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER, "misc/spawn.wav", VOL_BASE, ATTN_NORM); if(g_assault) { if(self.team == assault_attacker_team) @@ -1057,23 +878,46 @@ void PutClientInServer (void) // reset fields the weapons may use for (j = WEP_FIRST; j <= WEP_LAST; ++j) + { weapon_action(j, WR_RESETPLAYER); + // all weapons must be fully loaded when we spawn + entity e; + e = get_weaponinfo(j); + if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars + self.(weapon_load[j]) = cvar(strcat("g_balance_", e.netname, "_reload_ammo")); + } + oldself = self; self = spot; activator = oldself; + string s; + s = self.target; + self.target = string_null; SUB_UseTargets(); + self.target = s; activator = world; self = oldself; + spawn_spot = spot; MUTATOR_CALLHOOK(PlayerSpawn); + if(autocvar_spawn_debug) + { + sprint(self, strcat("spawnpoint origin: ", vtos(spot.origin), "\n")); + remove(spot); // usefull for checking if there are spawnpoints, that let drop through the floor + } + self.switchweapon = w_getbestweapon(self); - self.cnt = self.switchweapon; + self.cnt = -1; // W_LastWeapon will not complain self.weapon = 0; + self.weaponname = ""; + self.switchingweapon = 0; if(!self.alivetime) self.alivetime = time; + + antilag_clear(self); } else if(self.classname == "observer" || (g_ca && !allowed_to_spawn)) { PutObserverInServer (); } @@ -1112,8 +956,11 @@ float ClientInit_SendEntity(entity to, float sf) WriteCoord(MSG_ENTITY, self.ebouncefactor); // g_balance_grenadelauncher_bouncefactor WriteCoord(MSG_ENTITY, self.ebouncestop); // g_balance_grenadelauncher_bouncestop WriteByte(MSG_ENTITY, autocvar_g_balance_nex_secondary); // client has to know if it should zoom or not - WriteByte(MSG_ENTITY, autocvar_g_balance_campingrifle_secondary); // client has to know if it should zoom or not + WriteByte(MSG_ENTITY, autocvar_g_balance_rifle_secondary); // client has to know if it should zoom or not WriteByte(MSG_ENTITY, serverflags); // client has to know if it should zoom or not + WriteByte(MSG_ENTITY, autocvar_g_balance_minelayer_limit); // minelayer max mines + WriteByte(MSG_ENTITY, autocvar_g_balance_hagar_secondary_load_max); // hagar max loadable rockets + WriteCoord(MSG_ENTITY, autocvar_g_trueaim_minrange); return TRUE; } @@ -1235,7 +1082,19 @@ void ClientKill_Now_TeamChange() void ClientKill_Now() { - remove(self.killindicator); + if(self.vehicle) + { + vehicles_exit(VHEF_RELESE); + if(!self.killindicator_teamchange) + { + self.vehicle_health = -1; + Damage(self, self, self, 1 , DEATH_KILL, self.origin, '0 0 0'); + } + } + + if(self.killindicator && !wasfreed(self.killindicator)) + remove(self.killindicator); + self.killindicator = world; if(self.killindicator_teamchange) @@ -1248,7 +1107,14 @@ void ClientKill_Now() } void KillIndicator_Think() { - if (!self.owner.modelindex) + if (gameover) + { + self.owner.killindicator = world; + remove(self); + return; + } + + if (self.owner.alpha < 0) { self.owner.killindicator = world; remove(self); @@ -1274,27 +1140,22 @@ void KillIndicator_Think() { if(self.cnt <= 10) AnnounceTo(self.owner, strcat(ftos(self.cnt), "")); - if(self.owner.killindicator_teamchange) - { - if(self.owner.killindicator_teamchange == -1) - centerprint(self.owner, strcat("Changing team in ", ftos(self.cnt), " seconds")); - else if(self.owner.killindicator_teamchange == -2) - centerprint(self.owner, strcat("Spectating in ", ftos(self.cnt), " seconds")); - else - centerprint(self.owner, strcat("Changing to ", ColoredTeamName(self.owner.killindicator_teamchange), " in ", ftos(self.cnt), " seconds")); - } - else - centerprint(self.owner, strcat("^1Suicide in ", ftos(self.cnt), " seconds")); } self.nextthink = time + 1; self.cnt -= 1; } } +float clientkilltime; void ClientKill_TeamChange (float targetteam) // 0 = don't change, -1 = auto, -2 = spec { float killtime; + float starttime; entity e; + + if (gameover) + return; + killtime = autocvar_g_balance_kill_delay; if(g_race_qualifying || g_cts) @@ -1313,25 +1174,28 @@ void ClientKill_TeamChange (float targetteam) // 0 = don't change, -1 = auto, -2 if(!self.killindicator) { - if(self.modelindex && self.deadflag == DEAD_NO) + if(self.deadflag == DEAD_NO) { killtime = max(killtime, self.clientkill_nexttime - time); self.clientkill_nexttime = time + killtime + autocvar_g_balance_kill_antispam; } - if(killtime <= 0 || !self.modelindex || self.deadflag != DEAD_NO) + if(killtime <= 0 || self.classname != "player" || self.deadflag != DEAD_NO) { ClientKill_Now(); } else { + starttime = max(time, clientkilltime); + self.killindicator = spawn(); self.killindicator.owner = self; self.killindicator.scale = 0.5; setattachment(self.killindicator, self, ""); setorigin(self.killindicator, '0 0 52'); self.killindicator.think = KillIndicator_Think; - self.killindicator.nextthink = time + (self.lip) * 0.05; + self.killindicator.nextthink = starttime + (self.lip) * 0.05; + clientkilltime = max(clientkilltime, self.killindicator.nextthink + 0.05); self.killindicator.cnt = ceil(killtime); self.killindicator.count = bound(0, ceil(killtime), 10); //sprint(self, strcat("^1You'll be dead in ", ftos(self.killindicator.cnt), " seconds\n")); @@ -1346,7 +1210,8 @@ void ClientKill_TeamChange (float targetteam) // 0 = don't change, -1 = auto, -2 setattachment(e.killindicator, e, ""); setorigin(e.killindicator, '0 0 52'); e.killindicator.think = KillIndicator_Think; - e.killindicator.nextthink = time + (e.lip) * 0.05; + e.killindicator.nextthink = starttime + (e.lip) * 0.05; + clientkilltime = max(clientkilltime, e.killindicator.nextthink + 0.05); e.killindicator.cnt = ceil(killtime); } self.lip = 0; @@ -1355,23 +1220,47 @@ void ClientKill_TeamChange (float targetteam) // 0 = don't change, -1 = auto, -2 if(self.killindicator) { if(targetteam == 0) // just die + { self.killindicator.colormod = '0 0 0'; + if(clienttype(self) == CLIENTTYPE_REAL) + if(self.killindicator.cnt > 0) + Send_CSQC_Centerprint_Generic(self, CPID_TEAMCHANGE, "^1Suicide in %d seconds", 1, self.killindicator.cnt); + } else if(targetteam == -1) // auto + { self.killindicator.colormod = '0 1 0'; + if(clienttype(self) == CLIENTTYPE_REAL) + if(self.killindicator.cnt > 0) + Send_CSQC_Centerprint_Generic(self, CPID_TEAMCHANGE, "Changing team in %d seconds", 1, self.killindicator.cnt); + } else if(targetteam == -2) // spectate + { self.killindicator.colormod = '0.5 0.5 0.5'; + if(clienttype(self) == CLIENTTYPE_REAL) + if(self.killindicator.cnt > 0) + Send_CSQC_Centerprint_Generic(self, CPID_TEAMCHANGE, "Spectating in %d seconds", 1, self.killindicator.cnt); + } else + { self.killindicator.colormod = TeamColor(targetteam); + if(clienttype(self) == CLIENTTYPE_REAL) + if(self.killindicator.cnt > 0) + Send_CSQC_Centerprint_Generic(self, CPID_TEAMCHANGE, strcat("Changing to ", ColoredTeamName(targetteam), " in %d seconds"), 1, self.killindicator.cnt); + } } + } void ClientKill (void) { + if (gameover) + return; + if((g_arena || g_ca) && ((champion && champion.classname == "player" && player_count > 1) || player_count == 1)) // don't allow a kill in this case either { // do nothing } - else if(g_freezetag && self.freezetag_frozen == 1) + else if(self.freezetag_frozen) { // do nothing } @@ -1390,55 +1279,6 @@ void CTS_ClientKill (entity e) // silent version of ClientKill, used when player e.lip = 0; } -void DoTeamChange(float destteam) -{ - float t, c0; - if(!teams_matter) - { - if(destteam >= 0) - SetPlayerColors(self, destteam); - return; - } - if(self.classname == "player") - if(destteam == -1) - { - CheckAllowedTeams(self); - t = FindSmallestTeam(self, TRUE); - switch(self.team) - { - case COLOR_TEAM1: c0 = c1; break; - case COLOR_TEAM2: c0 = c2; break; - case COLOR_TEAM3: c0 = c3; break; - case COLOR_TEAM4: c0 = c4; break; - default: c0 = 999; - } - switch(t) - { - case 1: - if(c0 > c1) - destteam = COLOR_TEAM1; - break; - case 2: - if(c0 > c2) - destteam = COLOR_TEAM2; - break; - case 3: - if(c0 > c3) - destteam = COLOR_TEAM3; - break; - case 4: - if(c0 > c4) - destteam = COLOR_TEAM4; - break; - } - if(destteam == -1) - return; - } - if(destteam == self.team && destteam >= 0 && !self.killindicator) - return; - ClientKill_TeamChange(destteam); -} - void FixClientCvars(entity e) { // send prediction settings to the client @@ -1500,6 +1340,7 @@ Called when a client connects to the server string ColoredTeamName(float t); void DecodeLevelParms (void); //void dom_player_join_team(entity pl); +void set_dom_state(entity e); void ClientConnect (void) { float t; @@ -1516,7 +1357,7 @@ void ClientConnect (void) DecodeLevelParms(); #ifdef WATERMARK - sprint(self, strcat("^4SVQC Build information: ", WATERMARK(), "\n")); + sprint(self, strcat("^4SVQC Build information: ^1", WATERMARK(), "\n")); #endif self.classname = "player_joining"; @@ -1539,7 +1380,7 @@ void ClientConnect (void) playerdemo_init(); anticheat_init(); - + race_PreSpawnObserver(); //if(g_domination) @@ -1583,7 +1424,7 @@ void ClientConnect (void) else self.team_forced = 0; - if(!teams_matter) + if(!teamplay) if(self.team_forced > 0) self.team_forced = 0; @@ -1592,7 +1433,7 @@ void ClientConnect (void) if((autocvar_sv_spectate == 1 && !g_lms) || autocvar_g_campaign || self.team_forced < 0) { self.classname = "observer"; } else { - if(teams_matter) + if(teamplay) { if(autocvar_g_balance_teams || autocvar_g_balance_teams_force) { @@ -1613,6 +1454,11 @@ void ClientConnect (void) self.playerid = (playerid_last = playerid_last + 1); + PlayerStats_AddEvent(sprintf("kills-%d", self.playerid)); + + if(clienttype(self) == CLIENTTYPE_BOT) + PlayerStats_AddPlayer(self); + if(autocvar_sv_eventlog) GameLogEcho(strcat(":join:", ftos(self.playerid), ":", ftos(num_for_edict(self)), ":", ((clienttype(self) == CLIENTTYPE_REAL) ? self.netaddress : "bot"), ":", self.netname)); @@ -1629,11 +1475,8 @@ void ClientConnect (void) bprint("\n"); - self.welcomemessage_time = 0; - stuffcmd(self, strcat(clientstuff, "\n")); - stuffcmd(self, strcat("exec maps/", mapname, ".cfg\n")); - stuffcmd(self, "cl_particles_reloadeffects\n"); + stuffcmd(self, "cl_particles_reloadeffects\n"); // TODO do we still need this? FixClientCvars(self); @@ -1643,9 +1486,6 @@ void ClientConnect (void) // Wazat's grappling hook SetGrappleHookBindings(); - // get autoswitch state from player when he toggles it - stuffcmd(self, "alias autoswitch \"set cl_autoswitch $1 ; cmd autoswitch $1\"\n"); // default.cfg-ed in 2.4.1 - // get version info from player stuffcmd(self, "cmd clientversion $gameversion\n"); @@ -1653,7 +1493,7 @@ void ClientConnect (void) GetCvars(0); // notify about available teams - if(teams_matter) + if(teamplay) { CheckAllowedTeams(self); t = 0; if(c1 >= 0) t |= 1; if(c2 >= 0) t |= 2; if(c3 >= 0) t |= 4; if(c4 >= 0) t |= 8; @@ -1662,8 +1502,6 @@ void ClientConnect (void) else stuffcmd(self, "set _teams_available 0\n"); - stuffcmd(self, strcat("set gametype ", ftos(game), "\n")); - if(g_arena || g_ca) { self.classname = "observer"; @@ -1675,8 +1513,7 @@ void ClientConnect (void) ctf_clientconnect(); }*/ - if(teams_matter || radar_showennemies) - attach_entcs(); + attach_entcs(); bot_relinkplayerlist(); @@ -1687,7 +1524,7 @@ void ClientConnect (void) } self.jointime = time; - self.allowedTimeouts = autocvar_sv_timeout_number; + self.allowed_timeouts = autocvar_sv_timeout_number; if(clienttype(self) == CLIENTTYPE_REAL) { @@ -1741,11 +1578,17 @@ void ClientConnect (void) else if(autocvar_sv_teamnagger && !(autocvar_bot_vs_human && (c3==-1 && c4==-1)) && !g_ca) // teamnagger is currently bad for ca send_CSQC_teamnagger(); - send_CSQC_cr_maxbullets(self); + if (g_domination) + set_dom_state(self); CheatInitClient(); - PlayerStats_AddPlayer(self); + if(!autocvar_g_campaign) + Send_CSQC_Centerprint_Generic(self, CPID_MOTD, getwelcomemessage(), autocvar_welcome_message_time, 0); + + CSQCMODEL_AUTOINIT(); + + self.model_randomizer = random(); } /* @@ -1756,10 +1599,12 @@ Called when a client disconnects from the server ============= */ .entity chatbubbleentity; -.entity teambubbleentity; void ReadyCount(); void ClientDisconnect (void) { + if(self.vehicle) + vehicles_exit(VHEF_RELESE); + if not(self.flags & FL_CLIENT) { print("Warning: ClientDisconnect without ClientConnect\n"); @@ -1798,6 +1643,7 @@ void ClientDisconnect (void) Portal_ClearAll(self); + RemoveGrapplingHook(self); if(self.flagcarried) DropFlag(self.flagcarried, world, world); if(self.ballcarried && g_nexball) @@ -1810,9 +1656,6 @@ void ClientDisconnect (void) if (self.chatbubbleentity) remove (self.chatbubbleentity); - if (self.teambubbleentity) - remove (self.teambubbleentity); - if (self.killindicator) remove (self.killindicator); @@ -1853,7 +1696,7 @@ void ClientDisconnect (void) void ChatBubbleThink() { self.nextthink = time; - if (!self.owner.modelindex || self.owner.chatbubbleentity != self) + if ((self.owner.alpha < 0) || self.owner.chatbubbleentity != self) { if(self.owner) // but why can that ever be world? self.owner.chatbubbleentity = world; @@ -1868,11 +1711,11 @@ void ChatBubbleThink() self.model = self.mdl; else self.model = ""; -}; +} void UpdateChatBubble() { - if (!self.modelindex) + if (self.alpha < 0) return; // spawn a chatbubble entity if needed if (!self.chatbubbleentity) @@ -1893,93 +1736,40 @@ void UpdateChatBubble() } -void TeamBubbleThink() -{ - self.nextthink = time; - if (!self.owner.modelindex || self.owner.teambubbleentity != self) - { - if(self.owner) // but why can that ever be world? - self.owner.teambubbleentity = world; - remove(self); - return; - } -// setorigin(self, self.owner.origin + '0 0 15' + self.owner.maxs_z * '0 0 1'); // bandwidth hog. setattachment does this now - if (self.owner.BUTTON_CHAT || self.owner.deadflag || self.owner.killindicator) - self.model = ""; - else - self.model = self.mdl; - -}; - -float TeamBubble_customizeentityforclient() -{ - return (self.owner != other && self.owner.team == other.team && other.killcount > -666); -} - -void UpdateTeamBubble() -{ - if (!self.modelindex || !teams_matter) - return; - // spawn a teambubble entity if needed - if (!self.teambubbleentity && teams_matter) - { - self.teambubbleentity = spawn(); - self.teambubbleentity.owner = self; - self.teambubbleentity.exteriormodeltoclient = self; - self.teambubbleentity.think = TeamBubbleThink; - self.teambubbleentity.nextthink = time; - setmodel(self.teambubbleentity, "models/misc/teambubble.spr"); // precision set below -// setorigin(self.teambubbleentity, self.origin + '0 0 15' + self.maxs_z * '0 0 1'); - setorigin(self.teambubbleentity, '0 0 15' + self.maxs_z * '0 0 1'); - setattachment(self.teambubbleentity, self, ""); // sticks to moving player better, also conserves bandwidth - self.teambubbleentity.mdl = self.teambubbleentity.model; - self.teambubbleentity.model = self.teambubbleentity.mdl; - self.teambubbleentity.customizeentityforclient = TeamBubble_customizeentityforclient; - self.teambubbleentity.effects = EF_LOWPRECISION; - } -} - // LordHavoc: this hack will be removed when proper _pants/_shirt layers are // added to the model skins /*void UpdateColorModHack() { - local float c; + float c; c = self.clientcolors & 15; // LordHavoc: only bothering to support white, green, red, yellow, blue - if (!teams_matter) self.colormod = '0 0 0'; + if (!teamplay) self.colormod = '0 0 0'; else if (c == 0) self.colormod = '1.00 1.00 1.00'; else if (c == 3) self.colormod = '0.10 1.73 0.10'; else if (c == 4) self.colormod = '1.73 0.10 0.10'; else if (c == 12) self.colormod = '1.22 1.22 0.10'; else if (c == 13) self.colormod = '0.10 0.10 1.73'; else self.colormod = '1 1 1'; -};*/ +}*/ -.float oldcolormap; void respawn(void) { - if(self.modelindex != 0 && autocvar_g_respawn_ghosts) + if(self.alpha >= 0 && autocvar_g_respawn_ghosts) { self.solid = SOLID_NOT; self.takedamage = DAMAGE_NO; self.movetype = MOVETYPE_FLY; self.velocity = '0 0 1' * autocvar_g_respawn_ghosts_speed; self.avelocity = randomvec() * autocvar_g_respawn_ghosts_speed * 3 - randomvec() * autocvar_g_respawn_ghosts_speed * 3; - self.effects |= EF_ADDITIVE; - self.oldcolormap = self.colormap; - self.colormap = 512; + self.effects |= CSQCMODEL_EF_RESPAWNGHOST; pointparticles(particleeffectnum("respawn_ghost"), self.origin, '0 0 0', 1); if(autocvar_g_respawn_ghosts_maxtime) SUB_SetFade (self, time + autocvar_g_respawn_ghosts_maxtime / 2 + random () * (autocvar_g_respawn_ghosts_maxtime - autocvar_g_respawn_ghosts_maxtime / 2), 1.5); } CopyBody(1); + self.effects |= EF_NODRAW; // prevent another CopyBody - if(self.oldcolormap) - { - self.colormap = self.oldcolormap; - self.oldcolormap = 0; - } PutClientInServer(); } @@ -1988,71 +1778,30 @@ void play_countdown(float finished, string samp) if(clienttype(self) == CLIENTTYPE_REAL) if(floor(finished - time - frametime) != floor(finished - time)) if(finished - time < 6) - sound (self, CHAN_AUTO, samp, VOL_BASE, ATTN_NORM); -} - -/** - * When sv_timeout is used this function returs strings like - * "Timeout begins in 2 seconds!\n" or "Timeout ends in 23 seconds!\n". - * Called by centerprint functions - * @param addOneSecond boolean, set to 1 if the welcome-message centerprint asks for the text - */ -string getTimeoutText(float addOneSecond) { - if (!autocvar_sv_timeout || !timeoutStatus) - return ""; - - local string retStr; - if (timeoutStatus == 1) { - if (addOneSecond == 1) { - retStr = strcat("Timeout begins in ", ftos(remainingLeadTime + 1), " seconds!\n"); - } - else { - retStr = strcat("Timeout begins in ", ftos(remainingLeadTime), " seconds!\n"); - } - return retStr; - } - else if (timeoutStatus == 2) { - if (addOneSecond) { - retStr = strcat("Timeout ends in ", ftos(remainingTimeoutTime + 1), " seconds!\n"); - //don't show messages like "Timeout ends in 0 seconds"... - if ((remainingTimeoutTime + 1) > 0) - return retStr; - else - return ""; - } - else { - retStr = strcat("Timeout ends in ", ftos(remainingTimeoutTime), " seconds!\n"); - //don't show messages like "Timeout ends in 0 seconds"... - if (remainingTimeoutTime > 0) - return retStr; - else - return ""; - } - } - else return ""; + sound (self, CH_INFO, samp, VOL_BASE, ATTN_NORM); } void player_powerups (void) { // add a way to see what the items were BEFORE all of these checks for the mutator hook olditems = self.items; - + if((self.items & IT_USING_JETPACK) && !self.deadflag) { - SoundEntity_StartSound(self, CHAN_PLAYER, "misc/jetpack_fly.wav", VOL_BASE, autocvar_g_jetpack_attenuation); + SoundEntity_StartSound(self, CH_TRIGGER_SINGLE, "misc/jetpack_fly.wav", VOL_BASE, autocvar_g_jetpack_attenuation); self.modelflags |= MF_ROCKET; } else { - SoundEntity_StopSound(self, CHAN_PLAYER); + SoundEntity_StopSound(self, CH_TRIGGER_SINGLE); self.modelflags &~= MF_ROCKET; } self.effects &~= (EF_RED | EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT | EF_FLAME | EF_NODEPTHTEST); - if(!self.modelindex || self.deadflag) // don't apply the flags if the player is gibbed + if(self.alpha < 0 || self.deadflag) // don't apply the flags if the player is gibbed return; - + Fire_ApplyDamage(self); Fire_ApplyEffect(self); @@ -2085,7 +1834,7 @@ void player_powerups (void) if (self.items & IT_INVINCIBLE) { play_countdown(self.invincible_finished, "misc/poweroff.wav"); - if (time > self.invincible_finished && autocvar_g_balance_powerup_timer) + if (time > self.invincible_finished) { self.items = self.items - (self.items & IT_INVINCIBLE); sprint(self, "^3Speed has worn off\n"); @@ -2106,7 +1855,7 @@ void player_powerups (void) { play_countdown(self.strength_finished, "misc/poweroff.wav"); self.effects = self.effects | (EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT); - if (time > self.strength_finished && autocvar_g_balance_powerup_timer) + if (time > self.strength_finished) { self.items = self.items - (self.items & IT_STRENGTH); sprint(self, "^3Strength has worn off\n"); @@ -2124,7 +1873,7 @@ void player_powerups (void) { play_countdown(self.invincible_finished, "misc/poweroff.wav"); self.effects = self.effects | (EF_RED | EF_ADDITIVE | EF_FULLBRIGHT); - if (time > self.invincible_finished && autocvar_g_balance_powerup_timer) + if (time > self.invincible_finished) { self.items = self.items - (self.items & IT_INVINCIBLE); sprint(self, "^3Shield has worn off\n"); @@ -2138,27 +1887,27 @@ void player_powerups (void) sprint(self, "^3Shield surrounds you\n"); } } + } + + if(autocvar_g_nodepthtestplayers) + self.effects = self.effects | EF_NODEPTHTEST; - if(autocvar_g_nodepthtestplayers) - self.effects = self.effects | EF_NODEPTHTEST; + if(autocvar_g_fullbrightplayers) + self.effects = self.effects | EF_FULLBRIGHT; - if(autocvar_g_fullbrightplayers) - self.effects = self.effects | EF_FULLBRIGHT; + // midair gamemode: damage only while in the air + // if in midair mode, being on ground grants temporary invulnerability + // (this is so that multishot weapon don't clear the ground flag on the + // first damage in the frame, leaving the player vulnerable to the + // remaining hits in the same frame) + if (self.flags & FL_ONGROUND) + if (g_midair) + self.spawnshieldtime = max(self.spawnshieldtime, time + autocvar_g_midair_shieldtime); - // midair gamemode: damage only while in the air - // if in midair mode, being on ground grants temporary invulnerability - // (this is so that multishot weapon don't clear the ground flag on the - // first damage in the frame, leaving the player vulnerable to the - // remaining hits in the same frame) - if (self.flags & FL_ONGROUND) - if (g_midair) - self.spawnshieldtime = max(self.spawnshieldtime, time + autocvar_g_midair_shieldtime); + if (time >= game_starttime) + if (time < self.spawnshieldtime) + self.effects = self.effects | (EF_ADDITIVE | EF_FULLBRIGHT); - if (time >= game_starttime) - if (time < self.spawnshieldtime) - self.effects = self.effects | (EF_ADDITIVE | EF_FULLBRIGHT); - } - MUTATOR_CALLHOOK(PlayerPowerups); } @@ -2346,18 +2095,26 @@ void SpectateCopy(entity spectatee) { self.ammo_nails = spectatee.ammo_nails; self.ammo_rockets = spectatee.ammo_rockets; self.ammo_fuel = spectatee.ammo_fuel; + self.clip_load = spectatee.clip_load; + self.clip_size = spectatee.clip_size; self.effects = spectatee.effects & EFMASK_CHEAP; // eat performance self.health = spectatee.health; self.impulse = 0; self.items = spectatee.items; self.last_pickup = spectatee.last_pickup; + self.hit_time = spectatee.hit_time; self.metertime = spectatee.metertime; self.strength_finished = spectatee.strength_finished; self.invincible_finished = spectatee.invincible_finished; self.pressedkeys = spectatee.pressedkeys; self.weapons = spectatee.weapons; self.switchweapon = spectatee.switchweapon; + self.switchingweapon = spectatee.switchingweapon; self.weapon = spectatee.weapon; + self.nex_charge = spectatee.nex_charge; + self.nex_chargepool_ammo = spectatee.nex_chargepool_ammo; + self.hagar_load = spectatee.hagar_load; + self.minelayer_mines = spectatee.minelayer_mines; self.punchangle = spectatee.punchangle; self.view_ofs = spectatee.view_ofs; self.v_angle = spectatee.v_angle; @@ -2366,17 +2123,41 @@ void SpectateCopy(entity spectatee) { self.dmg_save = spectatee.dmg_save; self.dmg_inflictor = spectatee.dmg_inflictor; self.angles = spectatee.v_angle; - self.fixangle = TRUE; + if(!self.BUTTON_USE) + self.fixangle = TRUE; setorigin(self, spectatee.origin); setsize(self, spectatee.mins, spectatee.maxs); SetZoomState(spectatee.zoomstate); anticheat_spectatecopy(spectatee); + + //self.vehicle = spectatee.vehicle; + + self.hud = spectatee.hud; + if(spectatee.vehicle) + { + setorigin(self, spectatee.origin); + self.velocity = spectatee.vehicle.velocity; + self.v_angle += spectatee.vehicle.angles; + //self.v_angle_x *= -1; + self.vehicle_health = spectatee.vehicle_health; + self.vehicle_shield = spectatee.vehicle_shield; + self.vehicle_energy = spectatee.vehicle_energy; + self.vehicle_ammo1 = spectatee.vehicle_ammo1; + self.vehicle_ammo2 = spectatee.vehicle_ammo2; + self.vehicle_reload1 = spectatee.vehicle_reload1; + self.vehicle_reload2 = spectatee.vehicle_reload2; + + msg_entity = self; + WriteByte (MSG_ONE, SVC_SETVIEWPORT); + WriteEntity(MSG_ONE, spectatee); + //self.tur_head = spectatee.vehicle.vehicle_viewport; + } } float SpectateUpdate() { if(!self.enemy) - return 0; + return 0; if (self == self.enemy) return 0; @@ -2389,27 +2170,67 @@ float SpectateUpdate() { return 1; } -float SpectateNext() { - other = find(self.enemy, classname, "player"); - if (!other) +// Returns next available player to spectate if g_ca_spectate_enemies == 0 +entity CA_SpectateNext(entity start) { + if (start.team == self.team) { + return start; + } + + other = start; + // continue from current player + while(other && other.team != self.team) { + other = find(other, classname, "player"); + } + + if (!other) { + // restart from begining other = find(other, classname, "player"); + while(other && other.team != self.team) { + other = find(other, classname, "player"); + } + } + + return other; +} +float SpectateNext() { + other = find(self.enemy, classname, "player"); + if (g_ca && !autocvar_g_ca_spectate_enemies && self.caplayer) { + // CA and ca players when spectating enemies is forbidden + other = CA_SpectateNext(other); + } else { + // other modes and ca spectators or spectating enemies is allowed + if (!other) + other = find(other, classname, "player"); + } + if (other) self.enemy = other; if(self.enemy.classname == "player") { - msg_entity = self; - WriteByte(MSG_ONE, SVC_SETVIEW); - WriteEntity(MSG_ONE, self.enemy); - //stuffcmd(self, "set viewsize $tmpviewsize \n"); - self.movetype = MOVETYPE_NONE; - accuracy_resend(self); - - if(!SpectateUpdate()) - PutObserverInServer(); - - return 1; + if(self.enemy.vehicle) + { + msg_entity = self; + WriteByte(MSG_ONE, SVC_SETVIEWPORT); + WriteEntity(MSG_ONE, self.enemy); + //stuffcmd(self, "set viewsize $tmpviewsize \n"); + self.movetype = MOVETYPE_NONE; + accuracy_resend(self); + } + else + { + msg_entity = self; + WriteByte(MSG_ONE, SVC_SETVIEW); + WriteEntity(MSG_ONE, self.enemy); + //stuffcmd(self, "set viewsize $tmpviewsize \n"); + self.movetype = MOVETYPE_NONE; + accuracy_resend(self); + + if(!SpectateUpdate()) + PutObserverInServer(); + } + return 1; } else { return 0; } @@ -2429,22 +2250,23 @@ void ShowRespawnCountdown() return; else { - number = ceil(self.death_time - time); + number = ceil(self.respawn_time - time); if(number <= 0) return; if(number <= self.respawn_countdown) { self.respawn_countdown = number - 1; - if(ceil(self.death_time - (time + 0.5)) == number) // only say it if it is the same number even in 0.5s; to prevent overlapping sounds + if(ceil(self.respawn_time - (time + 0.5)) == number) // only say it if it is the same number even in 0.5s; to prevent overlapping sounds AnnounceTo(self, strcat(ftos(number), "")); } } } +.float prevent_join_msgtime; void LeaveSpectatorMode() { - if(isJoinAllowed()) { - if(!teams_matter || autocvar_g_campaign || autocvar_g_balance_teams || (self.wasplayer && autocvar_g_changeteam_banned) || self.team_forced > 0) { + if(nJoinAllowed(1)) { + if(!teamplay || autocvar_g_campaign || autocvar_g_balance_teams || (self.wasplayer && autocvar_g_changeteam_banned) || self.team_forced > 0) { self.classname = "player"; if(autocvar_g_campaign || autocvar_g_balance_teams || autocvar_g_balance_teams_force) @@ -2459,7 +2281,14 @@ void LeaveSpectatorMode() bprint ("^4", self.netname, "^4 is playing now\n"); if(!autocvar_g_campaign) - centerprint(self,""); // clear MOTD + if (time < self.jointime + autocvar_welcome_message_time) + Send_CSQC_Centerprint_Generic_Expire(self, CPID_MOTD); // clear MOTD + + if (self.prevent_join_msgtime) + { + Send_CSQC_Centerprint_Generic_Expire(self, CPID_PREVENT_JOIN); + self.prevent_join_msgtime = 0; + } return; } else { @@ -2472,7 +2301,11 @@ void LeaveSpectatorMode() } else { //player may not join because of g_maxplayers is set - centerprint_atprio(self, CENTERPRIO_MAPVOTE, PREVENT_JOIN_TEXT); + if (time - self.prevent_join_msgtime > 2) + { + Send_CSQC_Centerprint_Generic(self, CPID_PREVENT_JOIN, PREVENT_JOIN_TEXT, 0, 0); + self.prevent_join_msgtime = time; + } } } @@ -2480,25 +2313,30 @@ void LeaveSpectatorMode() * Determines whether the player is allowed to join. This depends on cvar * g_maxplayers, if it isn't used this function always return TRUE, otherwise * it checks whether the number of currently playing players exceeds g_maxplayers. - * @return bool TRUE if the player is allowed to join, false otherwise + * @return int number of free slots for players, 0 if none */ -float isJoinAllowed() { +float nJoinAllowed(float includeMe) { if(self.team_forced < 0) return FALSE; // forced spectators can never join + // TODO simplify this + entity e; + + float totalClients; + FOR_EACH_CLIENT(e) + totalClients += 1; + if (!autocvar_g_maxplayers) - return TRUE; + return maxclients - totalClients + includeMe; + + float currentlyPlaying; + FOR_EACH_REALPLAYER(e) + currentlyPlaying += 1; - local entity e; - local float currentlyPlaying; - FOR_EACH_REALPLAYER(e) { - if(e.classname == "player") - currentlyPlaying += 1; - } if(currentlyPlaying < autocvar_g_maxplayers) - return TRUE; + return min(maxclients - totalClients + includeMe, autocvar_g_maxplayers - currentlyPlaying); - return FALSE; + return 0; } /** @@ -2514,19 +2352,58 @@ void checkSpectatorBlock() { } } +.float motd_actived_time; // used for both motd and campaign_message +void PrintWelcomeMessage() +{ + if (self.motd_actived_time == 0) { // is there already a message showing? + if (autocvar_g_campaign) { + if ((self.classname == "player" && self.BUTTON_INFO) || (self.classname != "player")) { + self.motd_actived_time = time; + Send_CSQC_Centerprint_Generic(self, CPID_MOTD, campaign_message, -1, 0); + } + } else { + if ((time - self.jointime > autocvar_welcome_message_time) && self.BUTTON_INFO) { + self.motd_actived_time = time; + Send_CSQC_Centerprint_Generic(self, CPID_MOTD, getwelcomemessage(), -1, 0); + } + } + } else { // showing MOTD or campaign message + if (autocvar_g_campaign) { + if (self.BUTTON_INFO) + self.motd_actived_time = time; + else if ((time - self.motd_actived_time > 2) && self.classname == "player") { // hide it some seconds after BUTTON_INFO has been released + self.motd_actived_time = 0; + Send_CSQC_Centerprint_Generic_Expire(self, CPID_MOTD); + } + } else { + if ((time - self.jointime) > autocvar_welcome_message_time) { + if (self.BUTTON_INFO) + self.motd_actived_time = time; + else if (time - self.motd_actived_time > 2) { // hide it some seconds after BUTTON_INFO has been released + self.motd_actived_time = 0; + Send_CSQC_Centerprint_Generic_Expire(self, CPID_MOTD); + } + } + } + } +} + void ObserverThink() { + float prefered_movetype; if (self.flags & FL_JUMPRELEASED) { if (self.BUTTON_JUMP && !self.version_mismatch) { - self.welcomemessage_time = 0; self.flags &~= FL_JUMPRELEASED; self.flags |= FL_SPAWNING; } else if(self.BUTTON_ATCK && !self.version_mismatch) { - self.welcomemessage_time = 0; self.flags &~= FL_JUMPRELEASED; if(SpectateNext() == 1) { self.classname = "spectator"; } + } else { + prefered_movetype = ((!self.BUTTON_USE ? self.cvar_cl_clippedspectating : !self.cvar_cl_clippedspectating) ? MOVETYPE_FLY_WORLDONLY : MOVETYPE_NOCLIP); + if (self.movetype != prefered_movetype) + self.movetype = prefered_movetype; } } else { if (!(self.BUTTON_ATCK || self.BUTTON_JUMP)) { @@ -2539,18 +2416,17 @@ void ObserverThink() } } } - PrintWelcomeMessage(self); + + PrintWelcomeMessage(); } void SpectatorThink() { if (self.flags & FL_JUMPRELEASED) { if (self.BUTTON_JUMP && !self.version_mismatch) { - self.welcomemessage_time = 0; self.flags &~= FL_JUMPRELEASED; self.flags |= FL_SPAWNING; } else if(self.BUTTON_ATCK) { - self.welcomemessage_time = 0; self.flags &~= FL_JUMPRELEASED; if(SpectateNext() == 1) { self.classname = "spectator"; @@ -2559,7 +2435,6 @@ void SpectatorThink() PutClientInServer(); } } else if (self.BUTTON_ATCK2) { - self.welcomemessage_time = 0; self.flags &~= FL_JUMPRELEASED; self.classname = "observer"; PutClientInServer(); @@ -2577,12 +2452,33 @@ void SpectatorThink() return; } } + if(!SpectateUpdate()) + PutObserverInServer(); } - PrintWelcomeMessage(self); + PrintWelcomeMessage(); self.flags |= FL_CLIENT | FL_NOTARGET; } +float ctf_usekey(); +void PlayerUseKey() +{ + if(self.classname != "player") + return; + + if(self.vehicle) + { + vehicles_exit(VHEF_NORMAL); + return; + } + + // a use key was pressed; call handlers + if(ctf_usekey()) + return; + + MUTATOR_CALLHOOK(PlayerUseKey); +} + .float touchexplode_time; /* @@ -2592,11 +2488,14 @@ PlayerPreThink Called every frame for each client before the physics are run ============= */ +.float usekeypressed; void() ctf_setstatus; void() nexball_setstatus; .float items_added; void PlayerPreThink (void) { + WarpZone_PlayerPhysics_FixVAngle(); + self.stat_game_starttime = game_starttime; self.stat_allow_oldnexbeam = autocvar_g_allow_oldnexbeam; self.stat_leadlimit = autocvar_leadlimit; @@ -2627,10 +2526,12 @@ void PlayerPreThink (void) if(self.cvar_g_xonoticversion) if(time > self.version_nagtime) { - if(strstr(self.cvar_g_xonoticversion, "git", 0) < 0) + // don't notify git users + if(strstr(self.cvar_g_xonoticversion, "git", 0) < 0 && strstr(self.cvar_g_xonoticversion, "autobuild", 0) < 0) { - if(strstr(autocvar_g_xonoticversion, "git", 0) >= 0) + if(strstr(autocvar_g_xonoticversion, "git", 0) >= 0 || strstr(autocvar_g_xonoticversion, "autobuild", 0) >= 0) { + // notify release users if connecting to git dprint("^1NOTE^7 to ", self.netname, "^7 - the server is running ^3Xonotic ", autocvar_g_xonoticversion, " (beta)^7, you have ^3Xonotic ", self.cvar_g_xonoticversion, "^1\n"); sprint(self, strcat("\{1}^1NOTE: ^7the server is running ^3Xonotic ", autocvar_g_xonoticversion, " (beta)^7, you have ^3Xonotic ", self.cvar_g_xonoticversion, "^1\n")); } @@ -2640,12 +2541,14 @@ void PlayerPreThink (void) r = vercmp(self.cvar_g_xonoticversion, autocvar_g_xonoticversion); if(r < 0) { - dprint("^1NOTE^7 to ", self.netname, "^7 - ^3Xonotic ", autocvar_g_xonoticversion, "^7 is out, and you still have ^3Xonotic ", self.cvar_g_xonoticversion, "^1 - get the update from ^4http://www.xonotic.com/^1!\n"); - sprint(self, strcat("\{1}^1NOTE: ^3Xonotic ", autocvar_g_xonoticversion, "^7 is out, and you still have ^3Xonotic ", self.cvar_g_xonoticversion, "^1 - get the update from ^4http://www.xonotic.com/^1!\n")); + // give users new version + dprint("^1NOTE^7 to ", self.netname, "^7 - ^3Xonotic ", autocvar_g_xonoticversion, "^7 is out, and you still have ^3Xonotic ", self.cvar_g_xonoticversion, "^1 - get the update from ^4http://www.xonotic.org/^1!\n"); + sprint(self, strcat("\{1}^1NOTE: ^3Xonotic ", autocvar_g_xonoticversion, "^7 is out, and you still have ^3Xonotic ", self.cvar_g_xonoticversion, "^1 - get the update from ^4http://www.xonotic.org/^1!\n")); } else if(r > 0) { - dprint("^1NOTE^7 to ", self.netname, "^7 - the server is running ^3Xonotic ", autocvar_g_xonoticversion, "^7, you have ^3Xonotic ", self.cvar_g_xonoticversion, "^1\n"); + // notify users about old server version + print("^1NOTE^7 to ", self.netname, "^7 - the server is running ^3Xonotic ", autocvar_g_xonoticversion, "^7, you have ^3Xonotic ", self.cvar_g_xonoticversion, "^1\n"); sprint(self, strcat("\{1}^1NOTE: ^7the server is running ^3Xonotic ", autocvar_g_xonoticversion, "^7, you have ^3Xonotic ", self.cvar_g_xonoticversion, "^1\n")); } } @@ -2667,32 +2570,30 @@ void PlayerPreThink (void) MUTATOR_CALLHOOK(PlayerPreThink); + if(!self.cvar_cl_newusekeysupported) // FIXME remove this - it was a stupid idea to begin with, we can JUST use the button + { + if(self.BUTTON_USE && !self.usekeypressed) + PlayerUseKey(); + self.usekeypressed = self.BUTTON_USE; + } + + PrintWelcomeMessage(); + if(self.classname == "player") { // if(self.netname == "Wazat") // bprint(self.classname, "\n"); CheckRules_Player(); - PrintWelcomeMessage(self); - if (intermission_running) { IntermissionThink (); // otherwise a button could be missed between return; // the think tics } - if(self.teleport_time) - if(time > self.teleport_time) - { - self.teleport_time = 0; - self.effects = self.effects - (self.effects & EF_NODRAW); - } - - if(frametime > 0) // don't do this in cl_movement frames, just in server ticks - UpdateSelectedPlayer(); - //don't allow the player to turn around while game is paused! - if(timeoutStatus == 2) { + if(timeout_status == TIMEOUT_ACTIVE) { + // FIXME turn this into CSQC stuff self.v_angle = self.lastV_angle; self.angles = self.lastV_angle; self.fixangle = TRUE; @@ -2700,34 +2601,40 @@ void PlayerPreThink (void) if(frametime) { - if(self.health <= 0 && autocvar_g_deathglow) +#ifndef NO_LEGACY_NETWORKING + self.glowmod = colormapPaletteColor(self.clientcolors & 0x0F, TRUE) * 2; +#endif + + if(self.weapon == WEP_NEX && autocvar_g_balance_nex_charge) { - if(self.glowmod_x > 0) - self.glowmod_x -= autocvar_g_deathglow * frametime; - else - self.glowmod_x = -1; - if(self.glowmod_y > 0) - self.glowmod_y -= autocvar_g_deathglow * frametime; - else - self.glowmod_y = -1; - if(self.glowmod_z > 0) - self.glowmod_z -= autocvar_g_deathglow * frametime; - else - self.glowmod_z = -1; + self.weaponentity_glowmod_x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_animlimit); + self.weaponentity_glowmod_y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_animlimit); + self.weaponentity_glowmod_z = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_animlimit); + + if(self.nex_charge > autocvar_g_balance_nex_charge_animlimit) + { + self.weaponentity_glowmod_x = self.weaponentity_glowmod_x + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_full * (self.nex_charge - autocvar_g_balance_nex_charge_animlimit) / (1 - autocvar_g_balance_nex_charge_animlimit); + self.weaponentity_glowmod_y = self.weaponentity_glowmod_y + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_full * (self.nex_charge - autocvar_g_balance_nex_charge_animlimit) / (1 - autocvar_g_balance_nex_charge_animlimit); + self.weaponentity_glowmod_z = self.weaponentity_glowmod_z + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_full * (self.nex_charge - autocvar_g_balance_nex_charge_animlimit) / (1 - autocvar_g_balance_nex_charge_animlimit); + } } else - self.glowmod = colormapPaletteColor(self.clientcolors & 0x0F, TRUE) * 2; + self.weaponentity_glowmod = colormapPaletteColor(self.clientcolors & 0x0F, TRUE) * 2; + player_powerups(); } + if (g_minstagib) + minstagib_ammocheck(); + if (self.deadflag != DEAD_NO) { float button_pressed, force_respawn; if(self.personal && g_race_qualifying) { - if(time > self.death_time) + if(time > self.respawn_time) { - self.death_time = time + 1; // only retry once a second + self.respawn_time = time + 1; // only retry once a second respawn(); self.impulse = 141; } @@ -2757,9 +2664,9 @@ void PlayerPreThink (void) } else if (self.deadflag == DEAD_RESPAWNING) { - if(time > self.death_time) + if(time > self.respawn_time) { - self.death_time = time + 1; // only retry once a second + self.respawn_time = time + 1; // only retry once a second respawn(); } } @@ -2767,6 +2674,8 @@ void PlayerPreThink (void) } return; } + // FIXME from now on self.deadflag is always 0 (and self.health is never < 1) + // so (self.deadflag == DEAD_NO) is always true in the code below if(g_touchexplode) if(time > self.touchexplode_time) @@ -2817,14 +2726,14 @@ void PlayerPreThink (void) self.prevorigin = self.origin; - if ((self.BUTTON_CROUCH && !self.hook.state) || self.health <= g_bloodloss) + if (((self.BUTTON_CROUCH && !self.hook.state) || self.health <= g_bloodloss) && self.animstate_startframe != self.anim_melee_x) // prevent crouching if using melee attack { if (!self.crouch) { self.crouch = TRUE; self.view_ofs = PL_CROUCH_VIEW_OFS; setsize (self, PL_CROUCH_MIN, PL_CROUCH_MAX); - setanim(self, self.anim_duck, FALSE, TRUE, TRUE); + // setanim(self, self.anim_duck, FALSE, TRUE, TRUE); // this anim is BROKEN anyway } } else @@ -2878,15 +2787,15 @@ void PlayerPreThink (void) if(frametime) player_anim(); - if (g_minstagib) - minstagib_ammocheck(); - if(g_ctf) ctf_setstatus(); if(g_nexball) nexball_setstatus(); - + + // secret status + secrets_setstatus(); + self.dmg_team = max(0, self.dmg_team - autocvar_g_teamdamage_resetspeed * frametime); //self.angles_y=self.v_angle_y + 90; // temp @@ -2901,7 +2810,7 @@ void PlayerPreThink (void) } if(!zoomstate_set) - SetZoomState(self.BUTTON_ZOOM || (self.BUTTON_ATCK2 && self.weapon == WEP_NEX) || (self.BUTTON_ATCK2 && self.weapon == WEP_CAMPINGRIFLE && autocvar_g_balance_campingrifle_secondary == 0)); + SetZoomState(self.BUTTON_ZOOM || self.BUTTON_ZOOMSCRIPT || (self.BUTTON_ATCK2 && self.weapon == WEP_NEX) || (self.BUTTON_ATCK2 && self.weapon == WEP_RIFLE && autocvar_g_balance_rifle_secondary == 0)); float oldspectatee_status; oldspectatee_status = self.spectatee_status; @@ -2928,7 +2837,7 @@ void PlayerPreThink (void) oldself = self; self = self.teamkill_soundsource; oldpusher = self.pusher; self.pusher = oldself; - PlayerSound(playersound_teamshoot, CHAN_VOICE, VOICETYPE_LASTATTACKER_ONLY); + PlayerSound(playersound_teamshoot, CH_VOICE, VOICETYPE_LASTATTACKER_ONLY); self.pusher = oldpusher; self = oldself; @@ -2938,10 +2847,14 @@ void PlayerPreThink (void) if(time > self.taunt_soundtime) { self.taunt_soundtime = 0; - PlayerSound(playersound_taunt, CHAN_VOICE, VOICETYPE_AUTOTAUNT); + PlayerSound(playersound_taunt, CH_VOICE, VOICETYPE_AUTOTAUNT); } target_voicescript_next(self); + + // if a player goes unarmed after holding a loaded weapon, empty his clip size and remove the crosshair ammo ring + if(!self.weapon) + self.clip_load = self.clip_size = 0; } float isInvisibleString(string s) @@ -2999,46 +2912,55 @@ void PlayerPostThink (void) stuffcmd(self, strcat("name ", self.netname, substring(ftos(random()), 2, -1), "\n")); } - if(sv_maxidle && frametime) + if(sv_maxidle && frametime) // WORKAROUND: only use dropclient in server frames (frametime set). Never use it in cl_movement frames (frametime zero). { - // WORKAROUND: only use dropclient in server frames (frametime set). Never use it in cl_movement frames (frametime zero). - float timeleft; - timeleft = ceil(sv_maxidle - (time - self.parm_idlesince)); - if(timeleft <= 0) - { - bprint("^3", self.netname, "^3 was kicked for idling.\n"); - AnnounceTo(self, "terminated"); - dropclient(self); - return; - } - else if(timeleft <= 10) + if (time - self.parm_idlesince < 1) // instead of (time == self.parm_idlesince) to support sv_maxidle <= 10 { - if(timeleft != self.idlekick_lasttimeleft) + if(self.idlekick_lasttimeleft) { - centerprint_atprio(self, CENTERPRIO_IDLEKICK, strcat("^3Stop idling!\n^3Disconnecting in ", ftos(timeleft), "...")); - AnnounceTo(self, strcat(ftos(timeleft), "")); + Send_CSQC_Centerprint_Generic_Expire(self, CPID_DISCONNECT_IDLING); + self.idlekick_lasttimeleft = 0; } } else { - centerprint_expire(self, CENTERPRIO_IDLEKICK); + float timeleft; + timeleft = ceil(sv_maxidle - (time - self.parm_idlesince)); + if(timeleft == min(10, sv_maxidle - 1)) // - 1 to support sv_maxidle <= 10 + { + if(!self.idlekick_lasttimeleft) + Send_CSQC_Centerprint_Generic(self, CPID_DISCONNECT_IDLING, "^3Stop idling!\n^3Disconnecting in %d seconds...", 1, timeleft); + } + if(timeleft <= 0) + { + bprint("^3", self.netname, "^3 was kicked for idling.\n"); + AnnounceTo(self, "terminated"); + dropclient(self); + return; + } + else if(timeleft <= 10) + { + if(timeleft != self.idlekick_lasttimeleft) + AnnounceTo(self, ftos(timeleft)); + self.idlekick_lasttimeleft = timeleft; + } } - self.idlekick_lasttimeleft = timeleft; } #ifdef TETRIS if(self.impulse == 100) ImpulseCommands(); - if (TetrisPostFrame()) - return; + if (!TetrisPostFrame()) + { #endif CheatFrame(); + //CheckPlayerJump(); + if(self.classname == "player") { CheckRules_Player(); UpdateChatBubble(); - UpdateTeamBubble(); if (self.impulse) ImpulseCommands(); if (intermission_running) @@ -3049,6 +2971,10 @@ void PlayerPostThink (void) } else if (self.classname == "spectator") { //do nothing } + +#ifdef TETRIS + } +#endif /* float i; @@ -3072,7 +2998,7 @@ void PlayerPostThink (void) if(self.waypointsprite_attachedforcarrier) WaypointSprite_UpdateHealth(self.waypointsprite_attachedforcarrier, '1 0 0' * healtharmor_maxdamage(self.health, self.armorvalue, autocvar_g_balance_armor_blockpercent)); - + if(self.classname == "player" && self.deadflag == DEAD_NO && autocvar_r_showbboxes) { if(!self.showheadshotbbox) @@ -3090,18 +3016,19 @@ void PlayerPostThink (void) else { if(self.showheadshotbbox) - remove(self.showheadshotbbox); + if(self.showheadshotbbox && !wasfreed(self.showheadshotbbox)) + remove(self.showheadshotbbox); } playerdemo_write(); - if((g_cts || g_race) && self.cvar_cl_allow_uid2name == 1) + if((g_cts || g_race) && self.cvar_cl_allow_uidtracking == 1 && self.cvar_cl_allow_uid2name == 1) { if(!self.stored_netname) self.stored_netname = strzone(uid2name(self.crypto_idfp)); if(self.stored_netname != self.netname) { - db_put(ServerProgsDB, strcat("uid2name", self.crypto_idfp), self.netname); + db_put(ServerProgsDB, strcat("/uid2name/", self.crypto_idfp), self.netname); strunzone(self.stored_netname); self.stored_netname = strzone(self.netname); } @@ -3111,4 +3038,6 @@ void PlayerPostThink (void) if(g_race) dprint(sprintf("%f %.6f\n", time, race_GetFractionalLapCount(self))); */ + + CSQCMODEL_AUTOUPDATE(); } diff --git a/qcsrc/server/cl_impulse.qc b/qcsrc/server/cl_impulse.qc index ff3903cbad..524e796af2 100644 --- a/qcsrc/server/cl_impulse.qc +++ b/qcsrc/server/cl_impulse.qc @@ -35,7 +35,7 @@ void ImpulseCommands (void) { - local float imp; + float imp; vector org; float i; float m; @@ -46,7 +46,7 @@ void ImpulseCommands (void) return; self.impulse = 0; - if (timeoutStatus == 2) //don't allow any impulses while the game is paused + if (timeout_status == TIMEOUT_ACTIVE) //don't allow any impulses while the game is paused return; if(CheatImpulse(imp)) @@ -70,7 +70,7 @@ void ImpulseCommands (void) W_NextWeapon (0); break; case 11: - W_SwitchWeapon (self.cnt); // previously used + W_LastWeapon(); break; case 12: W_PreviousWeapon (0); @@ -98,13 +98,17 @@ void ImpulseCommands (void) W_PreviousWeapon (1); break; case 20: - W_Reload (); + W_TriggerReload (); break; } } else self.impulse = imp; // retry in next frame } + else if(imp == 21) + { + PlayerUseKey (); + } else if(imp >= 200 && imp <= 229) { if(self.deadflag == DEAD_NO) @@ -131,108 +135,79 @@ void ImpulseCommands (void) switch(imp) { case 30: - wp = WaypointSprite_DeployPersonal("waypoint", self.origin); + wp = WaypointSprite_DeployPersonal("waypoint", self.origin, RADARICON_WAYPOINT, '0 1 1'); if(wp) - { - WaypointSprite_UpdateTeamRadar(wp, RADARICON_WAYPOINT, '0 1 1'); WaypointSprite_Ping(wp); - } sprint(self, "personal waypoint spawned at location\n"); break; case 31: WarpZone_crosshair_trace(self); - wp = WaypointSprite_DeployPersonal("waypoint", trace_endpos); + wp = WaypointSprite_DeployPersonal("waypoint", trace_endpos, RADARICON_WAYPOINT, '0 1 1'); if(wp) - { - WaypointSprite_UpdateTeamRadar(wp, RADARICON_WAYPOINT, '0 1 1'); WaypointSprite_Ping(wp); - } sprint(self, "personal waypoint spawned at crosshair\n"); break; case 32: if(vlen(self.death_origin)) { - wp = WaypointSprite_DeployPersonal("waypoint", self.death_origin); + wp = WaypointSprite_DeployPersonal("waypoint", self.death_origin, RADARICON_WAYPOINT, '0 1 1'); if(wp) - { - WaypointSprite_UpdateTeamRadar(wp, RADARICON_WAYPOINT, '0 1 1'); WaypointSprite_Ping(wp); - } sprint(self, "personal waypoint spawned at death location\n"); } break; case 33: - if(self.deadflag == DEAD_NO && teams_matter) + if(self.deadflag == DEAD_NO && teamplay) { - wp = WaypointSprite_Attach("helpme", TRUE); - if(wp) - WaypointSprite_UpdateTeamRadar(wp, RADARICON_HELPME, '1 0.5 0'); // TODO choose better color + wp = WaypointSprite_Attach("helpme", TRUE, RADARICON_HELPME, '1 0.5 0'); if(!wp) - wp = self.waypointsprite_attachedforcarrier; // flag sprite? - if(wp) + WaypointSprite_HelpMePing(self.waypointsprite_attachedforcarrier); + else WaypointSprite_Ping(wp); sprint(self, "HELP ME attached\n"); } break; case 34: - wp = WaypointSprite_DeployFixed("here", FALSE, self.origin); + wp = WaypointSprite_DeployFixed("here", FALSE, self.origin, RADARICON_HERE, '0 1 0'); if(wp) - { - WaypointSprite_UpdateTeamRadar(wp, RADARICON_HERE, '0 1 0'); WaypointSprite_Ping(wp); - } sprint(self, "HERE spawned at location\n"); break; case 35: WarpZone_crosshair_trace(self); - wp = WaypointSprite_DeployFixed("here", FALSE, trace_endpos); + wp = WaypointSprite_DeployFixed("here", FALSE, trace_endpos, RADARICON_HERE, '0 1 0'); if(wp) - { - WaypointSprite_UpdateTeamRadar(wp, RADARICON_HERE, '0 1 0'); WaypointSprite_Ping(wp); - } sprint(self, "HERE spawned at crosshair\n"); break; case 36: if(vlen(self.death_origin)) { - wp = WaypointSprite_DeployFixed("here", FALSE, self.death_origin); + wp = WaypointSprite_DeployFixed("here", FALSE, self.death_origin, RADARICON_HERE, '0 1 0'); if(wp) - { - WaypointSprite_UpdateTeamRadar(wp, RADARICON_HERE, '0 1 0'); WaypointSprite_Ping(wp); - } sprint(self, "HERE spawned at death location\n"); } break; case 37: - wp = WaypointSprite_DeployFixed("danger", FALSE, self.origin); + wp = WaypointSprite_DeployFixed("danger", FALSE, self.origin, RADARICON_DANGER, '1 0.5 0'); if(wp) - { - WaypointSprite_UpdateTeamRadar(wp, RADARICON_DANGER, '1 0.5 0'); WaypointSprite_Ping(wp); - } sprint(self, "DANGER spawned at location\n"); break; case 38: WarpZone_crosshair_trace(self); - wp = WaypointSprite_DeployFixed("danger", FALSE, trace_endpos); + wp = WaypointSprite_DeployFixed("danger", FALSE, trace_endpos, RADARICON_DANGER, '1 0.5 0'); if(wp) - { - WaypointSprite_UpdateTeamRadar(wp, RADARICON_DANGER, '1 0.5 0'); WaypointSprite_Ping(wp); - } sprint(self, "DANGER spawned at crosshair\n"); break; case 39: if(vlen(self.death_origin)) { - wp = WaypointSprite_DeployFixed("danger", FALSE, self.death_origin); + wp = WaypointSprite_DeployFixed("danger", FALSE, self.death_origin, RADARICON_DANGER, '1 0.5 0'); if(wp) - { - WaypointSprite_UpdateTeamRadar(wp, RADARICON_DANGER, '1 0.5 0'); WaypointSprite_Ping(wp); - } sprint(self, "DANGER spawned at death location\n"); } break; @@ -284,7 +259,7 @@ void ImpulseCommands (void) case 107: for(e = findchain(classname, "waypoint"); e; e = e.chain) { - e.colormod_x = 1; + e.colormod = '0.5 0.5 0.5'; e.effects &~= EF_NODEPTHTEST | EF_RED | EF_BLUE; } e2 = navigation_findnearestwaypoint(self, FALSE); @@ -296,7 +271,7 @@ void ImpulseCommands (void) if(e.wpcost >= 10000000) { print("unreachable: ", etos(e), " ", vtos(e.origin), "\n"); - e.colormod_x = 0.1; + e.colormod_z = 8; e.effects |= EF_NODEPTHTEST | EF_BLUE; ++i; ++m; @@ -311,7 +286,7 @@ void ImpulseCommands (void) if(e.wpcost >= 10000000) { print("cannot reach me: ", etos(e), " ", vtos(e.origin), "\n"); - e.colormod_x = 0.1; + e.colormod_x = 8; if not(e.effects & EF_NODEPTHTEST) // not already reported before ++m; e.effects |= EF_NODEPTHTEST | EF_RED; @@ -342,12 +317,53 @@ void ImpulseCommands (void) setmodel(e, self.model); e.frame = self.frame; e.skin = self.skin; + e.colormod = '8 0.5 8'; setsize(e, '0 0 0', '0 0 0'); ++i; } } if(i) print(ftos(i), " spawnpoints have no nearest waypoint (marked by player model)\n"); + i = 0; + entity start; + start = findchainflags(flags, FL_ITEM); + for(e = start; e; e = e.chain) + { + e.effects &~= EF_NODEPTHTEST | EF_RED | EF_BLUE; + e.colormod = '0.5 0.5 0.5'; + } + for(e = start; e; e = e.chain) + { + if(navigation_findnearestwaypoint(e, FALSE)) + { + } + else + { + print("item without waypoint: ", etos(e), " ", vtos(e.origin), "\n"); + e.effects |= EF_NODEPTHTEST | EF_RED; + e.colormod_x = 8; + ++i; + } + } + if(i) + print(ftos(i), " items have no nearest waypoint and cannot be walked away from (marked with red light)\n"); + i = 0; + for(e = start; e; e = e.chain) + { + org = e.origin; + if(navigation_findnearestwaypoint(e, TRUE)) + { + } + else + { + print("item without waypoint: ", etos(e), " ", vtos(e.origin), "\n"); + e.effects |= EF_NODEPTHTEST | EF_BLUE; + e.colormod_z = 8; + ++i; + } + } + if(i) + print(ftos(i), " items have no nearest waypoint and cannot be walked to (marked with blue light)\n"); break; } } diff --git a/qcsrc/server/cl_physics.qc b/qcsrc/server/cl_physics.qc index e2feca927b..79087eb8a3 100644 --- a/qcsrc/server/cl_physics.qc +++ b/qcsrc/server/cl_physics.qc @@ -23,7 +23,7 @@ When you press the jump key */ void PlayerJump (void) { - if(g_freezetag && self.freezetag_frozen) + if(self.freezetag_frozen) return; // no jumping in freezetag when frozen float mjumpheight; @@ -34,7 +34,15 @@ void PlayerJump (void) { tracebox(self.origin + '0 0 0.01', self.mins, self.maxs, self.origin - '0 0 0.01', MOVE_NORMAL, self); if (trace_fraction < 1 && trace_plane_normal_z > 0.7) + { doublejump = TRUE; + + // we MUST clip velocity here! + float f; + f = self.velocity * trace_plane_normal; + if(f < 0) + self.velocity -= f * trace_plane_normal; + } } mjumpheight = autocvar_sv_jumpvelocity; @@ -61,7 +69,7 @@ void PlayerJump (void) if(!doublejump && self.multijump_ready && self.multijump_count < autocvar_g_multijump && self.velocity_z > autocvar_g_multijump_speed) { // doublejump = FALSE; // checked above in the if - if (autocvar_g_multijump > 0) + if (autocvar_g_multijump) { if (autocvar_g_multijump_add == 0) // in this case we make the z velocity == jumpvelocity { @@ -93,7 +101,8 @@ void PlayerJump (void) self.velocity_y = wishdir_y * curspeed; // keep velocity_z unchanged! } - self.multijump_count += 1; + if (autocvar_g_multijump > 0) + self.multijump_count += 1; } } self.multijump_ready = FALSE; // require releasing and pressing the jump button again for the next jump @@ -103,7 +112,7 @@ void PlayerJump (void) if (!(self.flags & FL_ONGROUND)) return; - if(!sv_pogostick) + if(self.cvar_cl_movement_track_canjump) if (!(self.flags & FL_JUMPRELEASED)) return; @@ -162,19 +171,18 @@ void PlayerJump (void) if (self.crouch) setanim(self, self.anim_duckjump, FALSE, TRUE, TRUE); - else + else if (self.animstate_startframe != self.anim_melee_x || (self.animstate_startframe == self.anim_melee_x && time - self.animstate_starttime >= 21/20)) // jump animation shouldn't override melee until we have animation blending (or until the anim finished, 21/20 = numframes/fps) setanim(self, self.anim_jump, FALSE, TRUE, TRUE); if(g_jump_grunt) - PlayerSound(playersound_jump, CHAN_PLAYER, VOICETYPE_PLAYERSOUND); + PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND); self.restart_jump = -1; // restart jump anim next time // value -1 is used to not use the teleport bit (workaround for tiny hitch when re-jumping) } - void CheckWaterJump() { - local vector start, end; + vector start, end; // check for a jump-out-of-water makevectors (self.angles); @@ -199,7 +207,26 @@ void CheckWaterJump() return; } } -}; +} +void CheckPlayerJump() +{ + if(self.flags & FL_ONGROUND) + { + if (autocvar_g_multijump > 0) + self.multijump_count = 0; + else + self.multijump_count = -2; // the cvar value for infinite jumps is -1, so this needs to be smaller + } + + if (self.BUTTON_JUMP) + PlayerJump (); + else + self.flags |= FL_JUMPRELEASED; + + if (self.waterlevel == WATERLEVEL_SWIMMING) + CheckWaterJump (); + self.prevjumpbutton = self.BUTTON_JUMP; +} float racecar_angle(float forward, float down) { @@ -503,7 +530,7 @@ float AdjustAirAccelQW(float accelqw, float factor) // sv_airaccel_sideways_friction 0 // prvm_globalset server speedclamp_mode 1 // (or 2) -void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float sidefric, float speedlimit) +void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float stretchfactor, float sidefric, float speedlimit) { float vel_straight; float vel_z; @@ -515,8 +542,14 @@ void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float acce float vel_xy_backward, vel_xy_forward; float speedclamp; - speedclamp = (accelqw < 0); - if(speedclamp) + if(stretchfactor > 0) + speedclamp = stretchfactor; + else if(accelqw < 0) + speedclamp = 1; // full clamping, no stretch + else + speedclamp = -1; // no clamping + + if(accelqw < 0) accelqw = -accelqw; if(autocvar_sv_gameplayfix_q2airaccelerate) @@ -559,12 +592,16 @@ void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float acce vel_xy = vel_straight * wishdir + vel_perpend; - if(speedclamp) + if(speedclamp >= 0) { - // ensure we don't get too fast or decelerate faster than we should - vel_xy_current = min(vlen(vel_xy), vel_xy_forward); - if(vel_xy_current > 0) // prevent division by zero - vel_xy = normalize(vel_xy) * vel_xy_current; + float vel_xy_preclamp; + vel_xy_preclamp = vlen(vel_xy); + if(vel_xy_preclamp > 0) // prevent division by zero + { + vel_xy_current += (vel_xy_forward - vel_xy_current) * speedclamp; + if(vel_xy_current < vel_xy_preclamp) + vel_xy = vel_xy * (vel_xy_current / vel_xy_preclamp); + } } self.velocity = vel_xy + vel_z * '0 0 1'; @@ -660,12 +697,14 @@ float speedaward_lastupdate; float speedaward_lastsent; void SV_PlayerPhysics() { - local vector wishvel, wishdir, v; - local float wishspeed, f, maxspd_mod, spd, maxairspd, airaccel, swampspd_mod, buttons; + vector wishvel, wishdir, v; + float wishspeed, f, maxspd_mod, spd, maxairspd, airaccel, swampspd_mod, buttons; string temps; float buttons_prev; float not_allowed_to_move; string c; + + WarpZone_PlayerPhysics_FixVAngle(); maxspd_mod = 1; if(g_minstagib && (self.items & IT_INVINCIBLE)) @@ -693,6 +732,7 @@ void SV_PlayerPhysics() maxspd_mod *= autocvar_g_movement_highspeed; // fix physics stats for g_movement_highspeed + // TODO maybe rather use maxairspeed? needs testing self.stat_sv_airaccel_qw = AdjustAirAccelQW(autocvar_sv_airaccel_qw, maxspd_mod); if(autocvar_sv_airstrafeaccel_qw) self.stat_sv_airstrafeaccel_qw = AdjustAirAccelQW(autocvar_sv_airstrafeaccel_qw, maxspd_mod); @@ -767,7 +807,7 @@ void SV_PlayerPhysics() self.angles_x = random() * 360; self.angles_y = random() * 360; // at least I'm not forcing retardedview by also assigning to angles_z - self.fixangle = 1; + self.fixangle = TRUE; } } @@ -796,8 +836,6 @@ void SV_PlayerPhysics() bot_think(); } - MUTATOR_CALLHOOK(PlayerPhysics); - self.items &~= IT_USING_JETPACK; if(self.classname == "player") @@ -830,6 +868,13 @@ void SV_PlayerPhysics() if (self.movetype == MOVETYPE_NONE) return; + // when we get here, disableclientprediction cannot be 2 + self.disableclientprediction = 0; + if(time < self.ladder_time) + self.disableclientprediction = 1; + + MUTATOR_CALLHOOK(PlayerPhysics); + maxspd_mod = 1; swampspd_mod = 1; @@ -837,6 +882,10 @@ void SV_PlayerPhysics() swampspd_mod = self.swamp_slowdown; //cvar("g_balance_swamp_moverate"); } + // conveyors: first fix velocity + if(self.conveyor.state) + self.velocity -= self.conveyor.movedir; + if(self.classname != "player") { maxspd_mod = autocvar_sv_spectator_speed_multiplier; @@ -886,6 +935,7 @@ void SV_PlayerPhysics() } if(self.flags & FL_ONGROUND) + if(self.classname == "player") // no fall sounds for observers thank you very much if(self.wasFlying) { self.wasFlying = 0; @@ -900,9 +950,9 @@ void SV_PlayerPhysics() if not(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS) { if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS) - GlobalSound(globalsound_metalfall, CHAN_PLAYER, VOICETYPE_PLAYERSOUND); + GlobalSound(globalsound_metalfall, CH_PLAYER, VOICETYPE_PLAYERSOUND); else - GlobalSound(globalsound_fall, CHAN_PLAYER, VOICETYPE_PLAYERSOUND); + GlobalSound(globalsound_fall, CH_PLAYER, VOICETYPE_PLAYERSOUND); } } } @@ -911,24 +961,7 @@ void SV_PlayerPhysics() self.wasFlying = 1; if(self.classname == "player") - { - if(self.flags & FL_ONGROUND) - { - if (autocvar_g_multijump > 0) - self.multijump_count = 0; - else - self.multijump_count = -2; // the cvar value for infinite jumps is -1, so this needs to be smaller - } - - if (self.BUTTON_JUMP) - PlayerJump (); - else - self.flags |= FL_JUMPRELEASED; - - if (self.waterlevel == WATERLEVEL_SWIMMING) - CheckWaterJump (); - self.prevjumpbutton = self.BUTTON_JUMP; - } + CheckPlayerJump(); if (self.flags & FL_WATERJUMP ) { @@ -944,7 +977,7 @@ void SV_PlayerPhysics() { RaceCarPhysics(); } - else if (self.movetype == MOVETYPE_NOCLIP || self.movetype == MOVETYPE_FLY) + else if (self.movetype == MOVETYPE_NOCLIP || self.movetype == MOVETYPE_FLY || self.movetype == MOVETYPE_FLY_WORLDONLY) { // noclipping or flying self.flags &~= FL_ONGROUND; @@ -959,7 +992,7 @@ void SV_PlayerPhysics() if (wishspeed > self.stat_sv_maxspeed*maxspd_mod) wishspeed = self.stat_sv_maxspeed*maxspd_mod; if (time >= self.teleport_time) - PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0); + PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0); } else if (self.waterlevel >= WATERLEVEL_SWIMMING) { @@ -982,21 +1015,28 @@ void SV_PlayerPhysics() self.velocity = self.velocity * (1 - frametime * autocvar_sv_friction); // water acceleration - PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0); + PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0); } else if (time < self.ladder_time) { // on a spawnfunc_func_ladder or swimming in spawnfunc_func_water self.flags &~= FL_ONGROUND; + float g; + g = autocvar_sv_gravity * frametime; + if(self.gravity) + g *= self.gravity; + if(autocvar_sv_gameplayfix_gravityunaffectedbyticrate) + { + g *= 0.5; + self.velocity_z += g; + } + self.velocity = self.velocity * (1 - frametime * autocvar_sv_friction); makevectors(self.v_angle); //wishvel = v_forward * self.movement_x + v_right * self.movement_y + v_up * self.movement_z; wishvel = v_forward * self.movement_x + v_right * self.movement_y + '0 0 1' * self.movement_z; - if (self.gravity) - self.velocity_z = self.velocity_z + self.gravity * autocvar_sv_gravity * frametime; - else - self.velocity_z = self.velocity_z + autocvar_sv_gravity * frametime; + self.velocity_z += g; if (self.ladder_entity.classname == "func_water") { f = vlen(wishvel); @@ -1025,7 +1065,7 @@ void SV_PlayerPhysics() if (time >= self.teleport_time) { // water acceleration - PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0); + PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0); } } else if ((self.items & IT_JETPACK) && self.BUTTON_HOOK && (!autocvar_g_jetpack_fuel || self.ammo_fuel >= 0.01 || self.items & IT_UNLIMITED_WEAPON_AMMO)) @@ -1175,6 +1215,28 @@ void SV_PlayerPhysics() self.velocity = self.velocity * f; else self.velocity = '0 0 0'; + /* + Mathematical analysis time! + + Our goal is to invert this mess. + + For the two cases we get: + v = v0 * (1 - frametime * (autocvar_sv_stopspeed / v0) * autocvar_sv_friction) + = v0 - frametime * autocvar_sv_stopspeed * autocvar_sv_friction + v0 = v + frametime * autocvar_sv_stopspeed * autocvar_sv_friction + and + v = v0 * (1 - frametime * autocvar_sv_friction) + v0 = v / (1 - frametime * autocvar_sv_friction) + + These cases would be chosen ONLY if: + v0 < autocvar_sv_stopspeed + v + frametime * autocvar_sv_stopspeed * autocvar_sv_friction < autocvar_sv_stopspeed + v < autocvar_sv_stopspeed * (1 - frametime * autocvar_sv_friction) + and, respectively: + v0 >= autocvar_sv_stopspeed + v / (1 - frametime * autocvar_sv_friction) >= autocvar_sv_stopspeed + v >= autocvar_sv_stopspeed * (1 - frametime * autocvar_sv_friction) + */ } // acceleration @@ -1185,7 +1247,7 @@ void SV_PlayerPhysics() if (self.crouch) wishspeed = wishspeed * 0.5; if (time >= self.teleport_time) - PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0); + PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0); } else { @@ -1256,7 +1318,7 @@ void SV_PlayerPhysics() if(autocvar_sv_warsowbunny_turnaccel && accelerating && self.movement_y == 0 && self.movement_x != 0) PM_AirAccelerate(wishdir, wishspeed); else - PM_Accelerate(wishdir, wishspeed, wishspeed0, airaccel, airaccelqw, autocvar_sv_airaccel_sideways_friction / maxairspd, self.stat_sv_airspeedlimit_nonqw); + PM_Accelerate(wishdir, wishspeed, wishspeed0, airaccel, airaccelqw, autocvar_sv_airaccel_qw_stretchfactor, autocvar_sv_airaccel_sideways_friction / maxairspd, self.stat_sv_airspeedlimit_nonqw); if(autocvar_sv_aircontrol) CPM_PM_Aircontrol(wishdir, wishspeed2); @@ -1303,6 +1365,10 @@ void SV_PlayerPhysics() if(self.flags & FL_ONGROUND) self.lastground = time; + // conveyors: then break velocity again + if(self.conveyor.state) + self.velocity += self.conveyor.movedir; + self.lastflags = self.flags; self.lastclassname = self.classname; -}; +} diff --git a/qcsrc/server/cl_player.qc b/qcsrc/server/cl_player.qc index 342cbbc3d6..8065d7f4db 100644 --- a/qcsrc/server/cl_player.qc +++ b/qcsrc/server/cl_player.qc @@ -1,70 +1,93 @@ +.entity accuracy; +.float accuracy_frags[WEP_MAXCOUNT]; + float weaponstats_buffer; void WeaponStats_Init() { - if(autocvar_sv_weaponstats_killfile != "" || autocvar_sv_weaponstats_damagefile != "") + if(autocvar_sv_weaponstats_file != "") weaponstats_buffer = buf_create(); else weaponstats_buffer = -1; } -#define WEAPONSTATS_GETINDEX(awep,vwep) ((vwep) + (awep) * (WEP_LAST - WEP_FIRST + 1) - (WEP_FIRST + WEP_FIRST * (WEP_LAST - WEP_FIRST + 1))) +#define WEAPONSTATS_GETINDEX(awep,abot,vwep,vbot) (((vwep) + (awep) * (WEP_LAST - WEP_FIRST + 1) - (WEP_FIRST + WEP_FIRST * (WEP_LAST - WEP_FIRST + 1))) * 4 + (abot) * 2 + (vbot)) + +void WeaponStats_ready(entity fh, entity pass, float status) +{ + float i, j, n, ibot, jbot, idx; + vector v; + string prefix, s; + switch(status) + { + case URL_READY_CANWRITE: + // we can write + prefix = strcat(autocvar_hostname, "\t", GetGametype(), "_", GetMapname(), "\t"); + url_fputs(fh, "#begin statsfile\n"); + url_fputs(fh, strcat("#date ", strftime(TRUE, "%a %b %e %H:%M:%S %Z %Y"), "\n")); +#ifdef WATERMARK + url_fputs(fh, strcat("#version ", WATERMARK(), "\n")); +#endif + url_fputs(fh, strcat("#config ", ftos(crc16(FALSE, cvar_purechanges)), "\n")); + url_fputs(fh, strcat("#cvar_purechanges ", ftos(cvar_purechanges_count), "\n")); + n = tokenizebyseparator(cvar_purechanges, "\n"); + for(i = 0; i < n; ++i) + url_fputs(fh, strcat("#cvar_purechange ", argv(i), "\n")); + for(i = WEP_FIRST; i <= WEP_LAST; ++i) for(ibot = 0; ibot <= 1; ++ibot) + for(j = WEP_FIRST; j <= WEP_LAST; ++j) for(jbot = 0; jbot <= 1; ++jbot) + { + idx = WEAPONSTATS_GETINDEX(i, ibot, j, jbot); + v = stov(bufstr_get(weaponstats_buffer, idx)); + if(v != '0 0 0') + { + //vector is: kills hits damage + url_fputs(fh, sprintf("%s%d %d\t%d %d\t", prefix, i, ibot, j, jbot)); + url_fputs(fh, sprintf("%d %d %g\n", v_x, v_y, v_z)); + } + } + url_fputs(fh, "#end\n\n"); + url_fclose(fh); + break; + case URL_READY_CANREAD: + // url_fclose is processing, we got a response for writing the data + // this must come from HTTP + print("Got response from weapon stats server:\n"); + while((s = url_fgets(fh))) + print(" ", s, "\n"); + print("End of response.\n"); + url_fclose(fh); + break; + case URL_READY_CLOSED: + // url_fclose has finished + print("Weapon stats written\n"); + buf_del(weaponstats_buffer); + weaponstats_buffer = -1; + break; + case URL_READY_ERROR: + default: + print("Weapon stats writing failed: ", ftos(status), "\n"); + buf_del(weaponstats_buffer); + weaponstats_buffer = -1; + break; + } +} void WeaponStats_Shutdown() { - float i, j, idx, f; - float fh; - string prefix; if(weaponstats_buffer < 0) return; - prefix = strcat(autocvar_hostname, "\t", GetGametype(), "_", GetMapname(), "\t"); - if(autocvar_sv_weaponstats_killfile != "") + if(autocvar_sv_weaponstats_file != "") { - fh = fopen(autocvar_sv_weaponstats_killfile, FILE_APPEND); - if(fh >= 0) - { - fputs(fh, "#begin killfile\n"); - fputs(fh, strcat("#date ", strftime(TRUE, "%a %b %e %H:%M:%S %Z %Y"), "\n")); - fputs(fh, strcat("#config ", ftos(crc16(FALSE, cvar_changes)), "\n")); - for(i = WEP_FIRST; i <= WEP_LAST; ++i) - for(j = WEP_FIRST; j <= WEP_LAST; ++j) - { - idx = WEAPONSTATS_GETINDEX(i, j); - f = stov(bufstr_get(weaponstats_buffer, idx)) * '0 1 0'; - if(f != 0) - fputs(fh, strcat(prefix, ftos(i), "\t", ftos(j), "\t", ftos(f), "\n")); - } - fputs(fh, "#end\n\n"); - fclose(fh); - print("Weapon kill stats written\n"); - } + url_multi_fopen(autocvar_sv_weaponstats_file, FILE_APPEND, WeaponStats_ready, world); } - if(autocvar_sv_weaponstats_damagefile != "") + else { - fh = fopen(autocvar_sv_weaponstats_damagefile, FILE_APPEND); - if(fh >= 0) - { - fputs(fh, "#begin damagefile\n"); - fputs(fh, strcat("#date ", strftime(TRUE, "%a %b %e %H:%M:%S %Z %Y"), "\n")); - fputs(fh, strcat("#config ", ftos(crc16(FALSE, cvar_changes)), "\n")); - for(i = WEP_FIRST; i <= WEP_LAST; ++i) - for(j = WEP_FIRST; j <= WEP_LAST; ++j) - { - idx = WEAPONSTATS_GETINDEX(i, j); - f = stov(bufstr_get(weaponstats_buffer, idx)) * '1 0 0'; - if(f != 0) - fputs(fh, strcat(prefix, ftos(i), "\t", ftos(j), "\t", ftos(f), "\n")); - } - fputs(fh, "#end\n\n"); - fclose(fh); - print("Weapon damage stats written\n"); - } + buf_del(weaponstats_buffer); + weaponstats_buffer = -1; } - buf_del(weaponstats_buffer); - weaponstats_buffer = -1; } -void WeaponStats_LogItem(float awep, float vwep, vector item) +void WeaponStats_LogItem(float awep, float abot, float vwep, float vbot, vector item) { float idx; if(weaponstats_buffer < 0) @@ -73,18 +96,18 @@ void WeaponStats_LogItem(float awep, float vwep, vector item) return; if(awep > WEP_LAST || vwep > WEP_LAST) return; - idx = WEAPONSTATS_GETINDEX(awep,vwep); + idx = WEAPONSTATS_GETINDEX(awep,abot,vwep,vbot); bufstr_set(weaponstats_buffer, idx, vtos(stov(bufstr_get(weaponstats_buffer, idx)) + item)); } -void WeaponStats_LogDamage(float awep, float vwep, float damage) +void WeaponStats_LogDamage(float awep, float abot, float vwep, float vbot, float damage) { if(damage < 0) error("negative damage?"); - WeaponStats_LogItem(awep, vwep, '1 0 0' * damage); + WeaponStats_LogItem(awep, abot, vwep, vbot, '0 0 1' * damage + '0 1 0'); } -void WeaponStats_LogKill(float awep, float vwep) +void WeaponStats_LogKill(float awep, float abot, float vwep, float vbot) { - WeaponStats_LogItem(awep, vwep, '0 1 0'); + WeaponStats_LogItem(awep, abot, vwep, vbot, '1 0 0'); } // changes by LordHavoc on 03/29/04 and 03/30/04 at Vermeulen's request @@ -101,9 +124,25 @@ void WeaponStats_LogKill(float awep, float vwep) .entity pusher; .float pushltime; +.float CopyBody_nextthink; +.void(void) CopyBody_think; +void CopyBody_Think(void) +{ + if(self.CopyBody_nextthink && time > self.CopyBody_nextthink) + { + self.CopyBody_think(); + if(wasfreed(self)) + return; + self.CopyBody_nextthink = self.nextthink; + self.CopyBody_think = self.think; + self.think = CopyBody_Think; + } + CSQCMODEL_AUTOUPDATE(); + self.nextthink = time; +} void CopyBody(float keepvelocity) { - local entity oldself; + entity oldself; if (self.effects & EF_NODRAW) return; oldself = self; @@ -111,13 +150,14 @@ void CopyBody(float keepvelocity) self.enemy = oldself; self.lip = oldself.lip; self.colormap = oldself.colormap; - self.glowmod = oldself.glowmod; self.iscreature = oldself.iscreature; + self.damagedbycontents = oldself.damagedbycontents; self.angles = oldself.angles; self.avelocity = oldself.avelocity; self.classname = "body"; self.damageforcescale = oldself.damageforcescale; self.effects = oldself.effects; + self.glowmod = oldself.glowmod; self.event_damage = oldself.event_damage; self.animstate_startframe = oldself.animstate_startframe; self.animstate_numframes = oldself.animstate_numframes; @@ -126,32 +166,28 @@ void CopyBody(float keepvelocity) self.animstate_endtime = oldself.animstate_endtime; self.animstate_override = oldself.animstate_override; self.animstate_looping = oldself.animstate_looping; + self.dphitcontentsmask = oldself.dphitcontentsmask; + self.death_time = oldself.death_time; self.frame = oldself.frame; - self.dead_frame = oldself.dead_frame; self.pain_finished = oldself.pain_finished; self.health = oldself.health; self.armorvalue = oldself.armorvalue; self.armortype = oldself.armortype; self.model = oldself.model; self.modelindex = oldself.modelindex; - self.modelindex_lod0 = oldself.modelindex_lod0; - self.modelindex_lod0_from_xonotic = oldself.modelindex_lod0_from_xonotic; - self.modelindex_lod1 = oldself.modelindex_lod1; - self.modelindex_lod2 = oldself.modelindex_lod2; - self.skinindex = oldself.skinindex; + self.skin = oldself.skin; self.species = oldself.species; self.movetype = oldself.movetype; - self.nextthink = oldself.nextthink; self.solid = oldself.solid; self.ballistics_density = oldself.ballistics_density; self.takedamage = oldself.takedamage; - self.think = oldself.think; self.customizeentityforclient = oldself.customizeentityforclient; self.uncustomizeentityforclient = oldself.uncustomizeentityforclient; self.uncustomizeentityforclient_set = oldself.uncustomizeentityforclient_set; if (keepvelocity == 1) self.velocity = oldself.velocity; self.oldvelocity = self.velocity; + self.alpha = oldself.alpha; self.fade_time = oldself.fade_time; self.fade_rate = oldself.fade_rate; //self.weapon = oldself.weapon; @@ -162,13 +198,22 @@ void CopyBody(float keepvelocity) Drag_MoveDrag(oldself, self); + if(self.colormap <= maxclients && self.colormap > 0) + self.colormap = 1024 + oldself.clientcolors; + + CSQCMODEL_AUTOINIT(); + self.CopyBody_nextthink = oldself.nextthink; + self.CopyBody_think = oldself.think; + self.nextthink = time; + self.think = CopyBody_Think; + self = oldself; } float player_getspecies() { float s; - get_model_parameters(self.model, self.skinindex); + get_model_parameters(self.model, self.skin); s = get_model_parameters_species; get_model_parameters(string_null, 0); if(s < 0) @@ -178,72 +223,42 @@ float player_getspecies() void player_setupanimsformodel() { - local string animfilename; - local float animfile; // defaults for legacy .zym models without animinfo files - self.anim_die1 = '0 1 0.5'; // 2 seconds - self.anim_die2 = '1 1 0.5'; // 2 seconds - self.anim_draw = '2 1 3'; // TODO: analyze models and set framerate - self.anim_duck = '3 1 100'; // this anim seems bogus in most models, so make it play VERY briefly! - self.anim_duckwalk = '4 1 1'; - self.anim_duckjump = '5 1 100'; // zym anims keep playing until changed, so this only has to start the anim, landing will end it - self.anim_duckidle = '6 1 1'; - self.anim_idle = '7 1 1'; - self.anim_jump = '8 1 100'; // zym anims keep playing until changed, so this only has to start the anim, landing will end it - self.anim_pain1 = '9 1 2'; // 0.5 seconds - self.anim_pain2 = '10 1 2'; // 0.5 seconds - self.anim_shoot = '11 1 5'; // TODO: analyze models and set framerate - self.anim_taunt = '12 1 0.33'; // FIXME? there is no code using this anim - self.anim_run = '13 1 1'; - self.anim_runbackwards = '14 1 1'; - self.anim_strafeleft = '15 1 1'; - self.anim_straferight = '16 1 1'; - self.anim_dead1 = '17 1 1'; - self.anim_dead2 = '18 1 1'; - self.anim_forwardright = '19 1 1'; - self.anim_forwardleft = '20 1 1'; - self.anim_backright = '21 1 1'; - self.anim_backleft = '22 1 1'; - animparseerror = FALSE; - animfilename = strcat(self.model, ".animinfo"); - animfile = fopen(animfilename, FILE_READ); - if (animfile >= 0) - { - self.anim_die1 = animparseline(animfile); - self.anim_die2 = animparseline(animfile); - self.anim_draw = animparseline(animfile); - self.anim_duck = animparseline(animfile); - self.anim_duckwalk = animparseline(animfile); - self.anim_duckjump = animparseline(animfile); - self.anim_duckidle = animparseline(animfile); - self.anim_idle = animparseline(animfile); - self.anim_jump = animparseline(animfile); - self.anim_pain1 = animparseline(animfile); - self.anim_pain2 = animparseline(animfile); - self.anim_shoot = animparseline(animfile); - self.anim_taunt = animparseline(animfile); - self.anim_run = animparseline(animfile); - self.anim_runbackwards = animparseline(animfile); - self.anim_strafeleft = animparseline(animfile); - self.anim_straferight = animparseline(animfile); - self.anim_forwardright = animparseline(animfile); - self.anim_forwardleft = animparseline(animfile); - self.anim_backright = animparseline(animfile); - self.anim_backleft = animparseline(animfile); - fclose(animfile); - - // derived anims - self.anim_dead1 = '0 1 1' + '1 0 0' * (self.anim_die1_x + self.anim_die1_y - 1); - self.anim_dead2 = '0 1 1' + '1 0 0' * (self.anim_die2_x + self.anim_die2_y - 1); - - if (animparseerror) - print("Parse error in ", animfilename, ", some player animations are broken\n"); - } - else - dprint("File ", animfilename, " not found, assuming legacy .zym model animation timings\n"); + self.anim_die1 = animfixfps(self, '0 1 0.5'); // 2 seconds + self.anim_die2 = animfixfps(self, '1 1 0.5'); // 2 seconds + self.anim_draw = animfixfps(self, '2 1 3'); + // self.anim_duck = '3 1 100'; // This anim is broken, use slot 3 as a new free slot in the future ;) + self.anim_duckwalk = animfixfps(self, '4 1 1'); + self.anim_duckjump = '5 1 100'; // NOTE: zym anims keep playing until changed, so this only has to start the anim, landing will end it + self.anim_duckidle = animfixfps(self, '6 1 1'); + self.anim_idle = animfixfps(self, '7 1 1'); + self.anim_jump = '8 1 100'; // NOTE: zym anims keep playing until changed, so this only has to start the anim, landing will end it + self.anim_pain1 = animfixfps(self, '9 1 2'); // 0.5 seconds + self.anim_pain2 = animfixfps(self, '10 1 2'); // 0.5 seconds + self.anim_shoot = animfixfps(self, '11 1 5'); // analyze models and set framerate + self.anim_taunt = animfixfps(self, '12 1 0.33'); + self.anim_run = animfixfps(self, '13 1 1'); + self.anim_runbackwards = animfixfps(self, '14 1 1'); + self.anim_strafeleft = animfixfps(self, '15 1 1'); + self.anim_straferight = animfixfps(self, '16 1 1'); + //self.anim_dead1 = animfixfps(self, '17 1 1'); + //self.anim_dead2 = animfixfps(self, '18 1 1'); + self.anim_forwardright = animfixfps(self, '19 1 1'); + self.anim_forwardleft = animfixfps(self, '20 1 1'); + self.anim_backright = animfixfps(self, '21 1 1'); + self.anim_backleft = animfixfps(self, '22 1 1'); + self.anim_melee = animfixfps(self, '23 1 1'); + self.anim_duckwalkbackwards = animfixfps(self, '24 1 1'); + self.anim_duckwalkstrafeleft = animfixfps(self, '25 1 1'); + self.anim_duckwalkstraferight = animfixfps(self, '26 1 1'); + self.anim_duckwalkforwardright = animfixfps(self, '27 1 1'); + self.anim_duckwalkforwardleft = animfixfps(self, '28 1 1'); + self.anim_duckwalkbackright = animfixfps(self, '29 1 1'); + self.anim_duckwalkbackleft = animfixfps(self, '30 1 1'); + // TODO introspect models for finding right "fps" value (1/duration) // reset animstate now setanim(self, self.anim_idle, TRUE, FALSE, TRUE); -}; +} void player_anim (void) { @@ -252,33 +267,55 @@ void player_anim (void) updateanim(self.weaponentity); if (self.deadflag != DEAD_NO) - { - if (time > self.animstate_endtime) - { - if (self.maxs_z > 5) - { - self.maxs_z = 5; - setsize(self, self.mins, self.maxs); - } - self.frame = self.dead_frame; - } return; - } if (!self.animstate_override) { - if (!(self.flags & FL_ONGROUND)) + if (!(self.flags & FL_ONGROUND) || self.BUTTON_JUMP) { if (self.crouch) - setanim(self, self.anim_duckjump, FALSE, TRUE, self.restart_jump); + { + if (self.animstate_startframe != self.anim_duckjump_x) // don't perform another trace if already playing the crouch jump anim + { + traceline(self.origin + '0 0 1' * PL_CROUCH_MIN_z, self.origin + '0 0 1' * (PL_CROUCH_MIN_z - autocvar_sv_player_jumpanim_minfall), TRUE, self); + if(!trace_startsolid && trace_fraction == 1 || !(self.animstate_startframe == self.anim_duckwalk_x || self.animstate_startframe == self.anim_duckidle_x)) // don't get stuck on non-crouch anims + { + setanim(self, self.anim_duckjump, FALSE, TRUE, self.restart_jump); + self.restart_jump = FALSE; + } + } + } else - setanim(self, self.anim_jump, FALSE, TRUE, self.restart_jump); - self.restart_jump = FALSE; + { + if (self.animstate_startframe != self.anim_jump_x) // don't perform another trace if already playing the jump anim + { + traceline(self.origin + '0 0 1' * PL_MIN_z, self.origin + '0 0 1' * (PL_MIN_z - autocvar_sv_player_jumpanim_minfall), TRUE, self); + if(!trace_startsolid && trace_fraction == 1 || self.animstate_startframe == self.anim_idle_x || (self.animstate_startframe == self.anim_melee_x && time - self.animstate_starttime >= 21/20)) // don't get stuck on idle animation in midair, nor melee after it finished + { + setanim(self, self.anim_jump, FALSE, TRUE, self.restart_jump); + self.restart_jump = FALSE; + } + } + } } else if (self.crouch) { - if (self.movement_x * self.movement_x + self.movement_y * self.movement_y > 20) + if (self.movement_x > 0 && self.movement_y == 0) setanim(self, self.anim_duckwalk, TRUE, FALSE, FALSE); + else if (self.movement_x < 0 && self.movement_y == 0) + setanim(self, self.anim_duckwalkbackwards, TRUE, FALSE, FALSE); + else if (self.movement_x == 0 && self.movement_y > 0) + setanim(self, self.anim_duckwalkstraferight, TRUE, FALSE, FALSE); + else if (self.movement_x == 0 && self.movement_y < 0) + setanim(self, self.anim_duckwalkstrafeleft, TRUE, FALSE, FALSE); + else if (self.movement_x > 0 && self.movement_y > 0) + setanim(self, self.anim_duckwalkforwardright, TRUE, FALSE, FALSE); + else if (self.movement_x > 0 && self.movement_y < 0) + setanim(self, self.anim_duckwalkforwardleft, TRUE, FALSE, FALSE); + else if (self.movement_x < 0 && self.movement_y > 0) + setanim(self, self.anim_duckwalkbackright, TRUE, FALSE, FALSE); + else if (self.movement_x < 0 && self.movement_y < 0) + setanim(self, self.anim_duckwalkbackleft, TRUE, FALSE, FALSE); else setanim(self, self.anim_duckidle, TRUE, FALSE, FALSE); } @@ -325,16 +362,19 @@ void SpawnThrownWeapon (vector org, float w) { if(self.weapons & W_WeaponBit(j)) if(W_IsWeaponThrowable(j)) - W_ThrowNewWeapon(self, j, FALSE, self.origin, randomvec() * 175 + '0 0 325'); + W_ThrowNewWeapon(self, j, FALSE, org, randomvec() * 175 + '0 0 325'); } } else - W_ThrowWeapon(randomvec() * 125 + '0 0 200', org - self.origin, FALSE); + { + if(W_IsWeaponThrowable(self.weapon)) + W_ThrowNewWeapon(self, self.weapon, FALSE, org, randomvec() * 125 + '0 0 200'); + } } void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) { - local float take, save; + float take, save; vector v; Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker); @@ -348,11 +388,11 @@ void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, float if(sound_allowed(MSG_BROADCAST, attacker)) { if (save > 10) - sound (self, CHAN_PROJECTILE, "misc/armorimpact.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_SHOTS, "misc/armorimpact.wav", VOL_BASE, ATTN_NORM); else if (take > 30) - sound (self, CHAN_PROJECTILE, "misc/bodyimpact2.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_SHOTS, "misc/bodyimpact2.wav", VOL_BASE, ATTN_NORM); else if (take > 10) - sound (self, CHAN_PROJECTILE, "misc/bodyimpact1.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_SHOTS, "misc/bodyimpact1.wav", VOL_BASE, ATTN_NORM); } if (take > 50) @@ -371,29 +411,31 @@ void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, float self.dmg_take = self.dmg_take + take;//max(take - 10, 0); self.dmg_inflictor = inflictor; - if (self.health <= -100 && self.modelindex != 0) + if (self.health <= -autocvar_sv_gibhealth && self.alpha >= 0) { // don't use any animations as a gib self.frame = 0; - self.dead_frame = 0; // view just above the floor self.view_ofs = '0 0 4'; Violence_GibSplash(self, 1, 1, attacker); - self.modelindex = 0; // restore later + self.alpha = -1; self.solid = SOLID_NOT; // restore later } } void ClientKill_Now_TeamChange(); void freezetag_CheckWinner(); -void freezetag_Unfreeze(); void PlayerDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) { - local float take, save, waves, sdelay, dh, da, j; + float take, save, waves, sdelay, dh, da, j; vector v; float valid_damage_for_weaponstats; + float excess; + + if((g_arena && numspawned < 2) || (g_ca && !ca_teams_ok) && !inWarmupStage) + return; dh = max(self.health, 0); da = max(self.armorvalue, 0); @@ -436,9 +478,6 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht else Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker); - if((g_arena && numspawned < 2) || (g_ca && ca_players < required_ca_players) && !inWarmupStage) - return; - if (!g_minstagib) { v = healtharmor_applydamage(self.armorvalue, autocvar_g_balance_armor_blockpercent, damage); @@ -460,15 +499,16 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht MUTATOR_CALLHOOK(PlayerDamage_SplitHealthArmor); take = bound(0, damage_take, self.health); save = bound(0, damage_save, self.armorvalue); + excess = max(0, damage - take - save); if(sound_allowed(MSG_BROADCAST, attacker)) { if (save > 10) - sound (self, CHAN_PROJECTILE, "misc/armorimpact.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_SHOTS, "misc/armorimpact.wav", VOL_BASE, ATTN_NORM); else if (take > 30) - sound (self, CHAN_PROJECTILE, "misc/bodyimpact2.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_SHOTS, "misc/bodyimpact2.wav", VOL_BASE, ATTN_NORM); else if (take > 10) - sound (self, CHAN_PROJECTILE, "misc/bodyimpact1.wav", VOL_BASE, ATTN_NORM); // FIXME possibly remove them? + sound (self, CH_SHOTS, "misc/bodyimpact1.wav", VOL_BASE, ATTN_NORM); // FIXME possibly remove them? } if (take > 50) @@ -483,7 +523,8 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht self.armorvalue = self.armorvalue - save; self.health = self.health - take; // pause regeneration for 5 seconds - self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_pause_health_regen); + if(take) + self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_pause_health_regen); if (time > self.pain_finished) //Don't switch pain sequences like crazy { @@ -492,10 +533,13 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht if(sv_gentle < 1) { if(self.classname != "body") // pain anim is BORKED on our ZYMs, FIXME remove this once we have good models { - if (random() > 0.5) - setanim(self, self.anim_pain1, FALSE, TRUE, TRUE); - else - setanim(self, self.anim_pain2, FALSE, TRUE, TRUE); + if (!self.animstate_override) + { + if (random() > 0.5) + setanim(self, self.anim_pain1, FALSE, TRUE, TRUE); + else + setanim(self, self.anim_pain2, FALSE, TRUE, TRUE); + } } if(sound_allowed(MSG_BROADCAST, attacker)) @@ -504,20 +548,20 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht // exclude pain sounds for laserjumps as long as you aren't REALLY low on health and would die of the next two { if(deathtype == DEATH_FALL) - PlayerSound(playersound_fall, CHAN_PAIN, VOICETYPE_PLAYERSOUND); + PlayerSound(playersound_fall, CH_PAIN, VOICETYPE_PLAYERSOUND); else if(self.health > 75) // TODO make a "gentle" version? - PlayerSound(playersound_pain100, CHAN_PAIN, VOICETYPE_PLAYERSOUND); + PlayerSound(playersound_pain100, CH_PAIN, VOICETYPE_PLAYERSOUND); else if(self.health > 50) - PlayerSound(playersound_pain75, CHAN_PAIN, VOICETYPE_PLAYERSOUND); + PlayerSound(playersound_pain75, CH_PAIN, VOICETYPE_PLAYERSOUND); else if(self.health > 25) - PlayerSound(playersound_pain50, CHAN_PAIN, VOICETYPE_PLAYERSOUND); + PlayerSound(playersound_pain50, CH_PAIN, VOICETYPE_PLAYERSOUND); else - PlayerSound(playersound_pain25, CHAN_PAIN, VOICETYPE_PLAYERSOUND); + PlayerSound(playersound_pain25, CH_PAIN, VOICETYPE_PLAYERSOUND); } } // throw off bot aim temporarily - local float shake; + float shake; shake = damage * 5 / (bound(0,skill,100) + 1); self.v_angle_x = self.v_angle_x + (random() * 2 - 1) * shake; self.v_angle_y = self.v_angle_y + (random() * 2 - 1) * shake; @@ -536,7 +580,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht // escape a lava pit or similar //self.pushltime = 0; } - else if(attacker.classname == "player" || attacker.classname == "gib") + else if(attacker.classname == "player") { self.pusher = attacker; self.pushltime = time + autocvar_g_maxpushtime; @@ -549,19 +593,28 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht else self.pushltime = 0; + float abot, vbot, awep; + abot = (clienttype(attacker) == CLIENTTYPE_BOT); + vbot = (clienttype(self) == CLIENTTYPE_BOT); + valid_damage_for_weaponstats = 0; - if(clienttype(self) == CLIENTTYPE_REAL) - if(clienttype(attacker) == CLIENTTYPE_REAL) - if(self != attacker) - if(!DEATH_ISSPECIAL(deathtype)) + if(vbot || clienttype(self) == CLIENTTYPE_REAL) + if(abot || clienttype(attacker) == CLIENTTYPE_REAL) + if(attacker && self != attacker) if(IsDifferentTeam(self, attacker)) + { + if(DEATH_ISSPECIAL(deathtype)) + awep = attacker.weapon; + else + awep = DEATH_WEAPONOF(deathtype); valid_damage_for_weaponstats = 1; - + } + if(valid_damage_for_weaponstats) { dh = dh - max(self.health, 0); da = da - max(self.armorvalue, 0); - WeaponStats_LogDamage(DEATH_WEAPONOF(deathtype), self.weapon, dh + da); + WeaponStats_LogDamage(awep, abot, self.weapon, vbot, dh + da); } if (self.health < 1) @@ -576,15 +629,15 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht } if(valid_damage_for_weaponstats) - WeaponStats_LogKill(DEATH_WEAPONOF(deathtype), self.weapon); + WeaponStats_LogKill(awep, abot, self.weapon, vbot); if(sv_gentle < 1) // TODO make a "gentle" version? if(sound_allowed(MSG_BROADCAST, attacker)) { if(deathtype == DEATH_DROWN) - PlayerSound(playersound_drown, CHAN_PAIN, VOICETYPE_PLAYERSOUND); + PlayerSound(playersound_drown, CH_PAIN, VOICETYPE_PLAYERSOUND); else - PlayerSound(playersound_death, CHAN_PAIN, VOICETYPE_PLAYERSOUND); + PlayerSound(playersound_death, CH_PAIN, VOICETYPE_PLAYERSOUND); } // get rid of kill indicator @@ -606,9 +659,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht if(!g_freezetag) { // become fully visible - self.alpha = 1; - // clear selected player display - ClearSelectedPlayer(); + self.alpha = default_player_alpha; // throw a weapon SpawnThrownWeapon (self.origin + (self.mins + self.maxs) * 0.5, self.switchweapon); } @@ -618,6 +669,13 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht race_PreDie(); DropAllRunes(self); + // increment frag counter for used weapon type + float w; + w = DEATH_WEAPONOF(deathtype); + if(WEP_VALID(w)) + if(accuracy_isgooddamage(attacker, self)) + attacker.accuracy.(accuracy_frags[w-1]) += 1; + if(deathtype == DEATH_HURTTRIGGER && g_freezetag) { PutClientInServer(); @@ -630,13 +688,13 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht frag_inflictor = inflictor; frag_target = self; MUTATOR_CALLHOOK(PlayerDies); + weapon_action(self.weapon, WR_PLAYERDEATH); - if(g_freezetag) - return; + RemoveGrapplingHook(self); if(self.flagcarried) { - if(attacker.classname != "player" && attacker.classname != "gib") + if(attacker.classname != "player") DropFlag(self.flagcarried, self, attacker); // penalty for flag loss by suicide else if(attacker.team == self.team) DropFlag(self.flagcarried, attacker, attacker); // penalty for flag loss by suicide/teamkill @@ -646,8 +704,31 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht if(self.ballcarried && g_nexball) DropBall(self.ballcarried, self.origin, self.velocity); Portal_ClearAllLater(self); - // clear waypoints + + if(clienttype(self) == CLIENTTYPE_REAL) + { + stuffcmd(self, "-zoom\n"); + self.fixangle = TRUE; + //msg_entity = self; + //WriteByte (MSG_ONE, SVC_SETANGLE); + //WriteAngle (MSG_ONE, self.v_angle_x); + //WriteAngle (MSG_ONE, self.v_angle_y); + //WriteAngle (MSG_ONE, 80); + } + + if(defer_ClientKill_Now_TeamChange) // TODO does this work with FreezeTag? + ClientKill_Now_TeamChange(); + + if(g_arena) + Spawnqueue_Unmark(self); + + if(g_freezetag) + return; + + // when we get here, player actually dies + // clear waypoints (do this AFTER FreezeTag) WaypointSprite_PlayerDead(); + // make the corpse upright (not tilted) self.angles_x = 0; self.angles_z = 0; @@ -669,218 +750,54 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht waves = 0; sdelay = cvar(strcat("g_", GetGametype(), "_respawn_delay")); if(!sdelay) - { - if(g_cts) - sdelay = 0; // no respawn delay in CTS - else - sdelay = autocvar_g_respawn_delay; - } + { + if(g_cts) + sdelay = 0; // no respawn delay in CTS + else + sdelay = autocvar_g_respawn_delay; + } waves = cvar(strcat("g_", GetGametype(), "_respawn_waves")); if(!waves) waves = autocvar_g_respawn_waves; if(waves) - self.death_time = ceil((time + sdelay) / waves) * waves; + self.respawn_time = ceil((time + sdelay) / waves) * waves; else - self.death_time = time + sdelay; - if((sdelay + waves >= 5.0) && (self.death_time - time > 1.75)) + self.respawn_time = time + sdelay; + if((sdelay + waves >= 5.0) && (self.respawn_time - time > 1.75)) self.respawn_countdown = 10; // first number to count down from is 10 else self.respawn_countdown = -1; // do not count down + self.death_time = time; if (random() < 0.5) - { setanim(self, self.anim_die1, FALSE, TRUE, TRUE); - self.dead_frame = self.anim_dead1_x; - } else - { setanim(self, self.anim_die2, FALSE, TRUE, TRUE); - self.dead_frame = self.anim_dead2_x; + if (self.maxs_z > 5) + { + self.maxs_z = 5; + setsize(self, self.mins, self.maxs); } // set damage function to corpse damage self.event_damage = PlayerCorpseDamage; // call the corpse damage function just in case it wants to gib - self.event_damage(inflictor, attacker, 0, deathtype, hitloc, force); + self.event_damage(inflictor, attacker, excess, deathtype, hitloc, force); // set up to fade out later SUB_SetFade (self, time + 6 + random (), 1); - if(clienttype(self) == CLIENTTYPE_REAL) - { - self.fixangle = TRUE; - //msg_entity = self; - //WriteByte (MSG_ONE, SVC_SETANGLE); - //WriteAngle (MSG_ONE, self.v_angle_x); - //WriteAngle (MSG_ONE, self.v_angle_y); - //WriteAngle (MSG_ONE, 80); - } - - if(g_arena) - Spawnqueue_Unmark(self); - - if(defer_ClientKill_Now_TeamChange) - ClientKill_Now_TeamChange(); - if(sv_gentle > 0 || autocvar_ekg) { // remove corpse - PlayerCorpseDamage (inflictor, attacker, 100.0, deathtype, hitloc, force); + PlayerCorpseDamage (inflictor, attacker, autocvar_sv_gibhealth+1.0, deathtype, hitloc, force); } // reset fields the weapons may use just in case - for (j = WEP_FIRST; j <= WEP_LAST; ++j) + for (j = WEP_FIRST; j <= WEP_LAST; ++j) { - weapon_action(j, WR_RESETPLAYER); + weapon_action(j, WR_RESETPLAYER); ATTACK_FINISHED_FOR(self, j) = 0; } } } -float UpdateSelectedPlayer_countvalue(float v) -{ - return max(0, (v - 1.0) / 0.5); -} - -// returns: -2 if no hit, otherwise cos of the angle -// uses the global v_angle -float UpdateSelectedPlayer_canSee(entity p, float mincosangle, float maxdist) -{ - vector so, d; - float c; - - if(p == self) - return -2; - - if(p.deadflag) - return -2; - - so = self.origin + self.view_ofs; - d = p.origin - so; - - // misaimed? - if(dist_point_line(d, '0 0 0', v_forward) > maxdist) - return -2; - - // now find the cos of the angle... - c = normalize(d) * v_forward; - - if(c <= mincosangle) - return -2; - - // not visible in any way? forget it - if(!checkpvs(so, p)) - return -2; - - traceline(so, p.origin, MOVE_NOMONSTERS, self); - if(trace_fraction < 1) - return -2; - - return c; -} - -void ClearSelectedPlayer() -{ - if(self.selected_player) - { - centerprint_expire(self, CENTERPRIO_POINT); - self.selected_player = world; - self.selected_player_display_needs_update = FALSE; - } -} - -void UpdateSelectedPlayer() -{ - entity selected; - float selected_score; - selected = world; - selected_score = 0.95; // 18 degrees - - if(!autocvar_sv_allow_shownames) - return; - - if(clienttype(self) != CLIENTTYPE_REAL) - return; - - if(self.cvar_cl_shownames == 0) - return; - - if(self.cvar_cl_shownames == 1 && !teams_matter) - return; - - makevectors(self.v_angle); // sets v_forward - - // 1. cursor trace is always right - WarpZone_crosshair_trace(self); - if(trace_ent && trace_ent.classname == "player" && !trace_ent.deadflag) - { - selected = trace_ent; - } - else - { - // 2. if we don't have a cursor trace, find the player which is least - // mis-aimed at - entity p; - FOR_EACH_PLAYER(p) - { - float c; - c = UpdateSelectedPlayer_canSee(p, selected_score, 100); // 100 = 2.5 meters - if(c >= -1) - { - selected = p; - selected_score = c; - } - } - } - - if(selected) - { - self.selected_player_display_timeout = time + self.cvar_scr_centertime; - } - else - { - if(time < self.selected_player_display_timeout) - if(UpdateSelectedPlayer_canSee(self.selected_player, 0.7, 200) >= -1) // 5 meters, 45 degrees - selected = self.selected_player; - } - - if(selected) - { - if(selected == self.selected_player) - { - float save; - save = UpdateSelectedPlayer_countvalue(self.selected_player_count); - self.selected_player_count = self.selected_player_count + frametime; - if(save != UpdateSelectedPlayer_countvalue(self.selected_player_count)) - { - string namestr, healthstr; - namestr = playername(selected); - if(teams_matter) - { - healthstr = ftos(floor(selected.health)); - if(self.team == selected.team) - { - namestr = strcat(namestr, " (", healthstr, "%)"); - self.selected_player_display_needs_update = TRUE; - } - } - centerprint_atprio(self, CENTERPRIO_POINT, namestr); - } - } - else - { - ClearSelectedPlayer(); - self.selected_player = selected; - self.selected_player_time = time; - self.selected_player_count = 0; - self.selected_player_display_needs_update = FALSE; - } - } - else - { - ClearSelectedPlayer(); - } - - if(self.selected_player) - self.last_selected_player = self.selected_player; -} - .float muted; // to be used by prvm_edictset server playernumber muted 1 float Say(entity source, float teamsay, entity privatesay, string msgin, float floodcontrol) // message "": do not say, just test flood control @@ -906,7 +823,7 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f if(source.classname != "player") colorstr = "^0"; // black for spectators - else if(teams_matter) + else if(teamplay) colorstr = Team_ColorCode(source.team); else teamsay = FALSE; @@ -1035,7 +952,7 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f flood = 1; } - if (timeoutStatus == 2) //when game is paused, no flood protection + if (timeout_status == TIMEOUT_ACTIVE) // when game is paused, no flood protection source.flood_field = flood = 0; } @@ -1258,18 +1175,19 @@ float LoadPlayerSounds(string f, float first) } .float modelindex_for_playersound; -.float skinindex_for_playersound; +.float skin_for_playersound; void UpdatePlayerSounds() { if(self.modelindex == self.modelindex_for_playersound) - if(self.skinindex == self.skinindex_for_playersound) + if(self.skin == self.skin_for_playersound) return; self.modelindex_for_playersound = self.modelindex; - self.skinindex_for_playersound = self.skinindex; + self.skin_for_playersound = self.skin; ClearPlayerSounds(); LoadPlayerSounds("sound/player/default.sounds", 1); - if(!LoadPlayerSounds(get_model_datafilename(self.model, self.skinindex, "sounds"), 0)) - LoadPlayerSounds(get_model_datafilename(self.model, 0, "sounds"), 0); + if(!autocvar_g_debug_defaultsounds) + if(!LoadPlayerSounds(get_model_datafilename(self.model, self.skin, "sounds"), 0)) + LoadPlayerSounds(get_model_datafilename(self.model, 0, "sounds"), 0); } void FakeGlobalSound(string sample, float chan, float voicetype) @@ -1395,7 +1313,7 @@ void GlobalSound(string sample, float chan, float voicetype) break; case VOICETYPE_TEAMRADIO: FOR_EACH_REALCLIENT(msg_entity) - if(!teams_matter || msg_entity.team == self.team) + if(!teamplay || msg_entity.team == self.team) { if(msg_entity.cvar_cl_voice_directional == 1) soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_MIN); @@ -1469,9 +1387,9 @@ void VoiceMessage(string type, string msg) flood = Say(self, ownteam, world, msg, 1); if (flood > 0) - GlobalSound(self.sample, CHAN_VOICE, voicetype); + GlobalSound(self.sample, CH_VOICE, voicetype); else if (flood < 0) - FakeGlobalSound(self.sample, CHAN_VOICE, voicetype); + FakeGlobalSound(self.sample, CH_VOICE, voicetype); } void MoveToTeam(entity client, float team_colour, float type, float show_message) diff --git a/qcsrc/server/cl_weapons.qc b/qcsrc/server/cl_weapons.qc index 6de63b9377..b1f6aabba1 100644 --- a/qcsrc/server/cl_weapons.qc +++ b/qcsrc/server/cl_weapons.qc @@ -1,8 +1,6 @@ -void W_Reload() +void W_TriggerReload() { - if(self.switchweapon == self.weapon) - if(self.weaponentity.state == WS_READY) - weapon_action(self.weapon, WR_RELOAD); + weapon_action(self.weapon, WR_RELOAD); } // switch between weapons @@ -17,9 +15,9 @@ void W_SwitchWeapon(float imp) } else { - W_Reload(); + W_TriggerReload(); } -}; +} .float weaponcomplainindex; float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, float complain, float skipmissing) @@ -139,17 +137,26 @@ void W_PreviousWeapon(float list) W_CycleWeapon(self.cvar_cl_weaponpriority, +1); } +// previously used if exists and has ammo, (second) best otherwise +void W_LastWeapon() +{ + if(client_hasweapon(self, self.cnt, TRUE, FALSE)) + W_SwitchWeapon(self.cnt); + else + W_SwitchToOtherWeapon(self); +} + float w_getbestweapon(entity e) { return W_GetCycleWeapon(e, e.cvar_cl_weaponpriority, 0, -1, FALSE, TRUE); -}; +} // generic weapons table // TODO should they be macros instead? float weapon_action(float wpn, float wrequest) { return (get_weaponinfo(wpn)).weapon_func(wrequest); -}; +} string W_Name(float weaponid) { @@ -199,6 +206,7 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto self = oldself; if(startitem_failed) return string_null; + wep.glowmod = own.weaponentity_glowmod; wep.think = thrown_wep_think; wep.nextthink = time + 0.5; return ""; @@ -212,7 +220,25 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto self = oldself; if(startitem_failed) return string_null; - if(doreduce) + if(doreduce && g_weapon_stay == 2) + { + for(i = 0, j = 1; i < 24; ++i, j *= 2) + { + if(wa & j) + { + ammofield = Item_CounterField(j); + wep.ammofield = 0; + + // if our weapon is loaded, give its load back to the player + if(self.(weapon_load[self.weapon]) > 0) + { + own.ammofield += self.(weapon_load[self.weapon]); + self.(weapon_load[self.weapon]) = -1; // schedule the weapon for reloading + } + } + } + } + else if(doreduce) { for(i = 0, j = 1; i < 24; ++i, j *= 2) { @@ -223,12 +249,21 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto wep.ammofield = thisammo; own.ammofield -= thisammo; s = strcat(s, " and ", ftos(thisammo), " ", Item_CounterFieldName(j)); + + // if our weapon is loaded, give its load back to the player + if(self.(weapon_load[self.weapon]) > 0) + { + own.ammofield += self.(weapon_load[self.weapon]); + self.(weapon_load[self.weapon]) = -1; // schedule the weapon for reloading + } } } s = substring(s, 5, -1); } + wep.glowmod = own.weaponentity_glowmod; wep.think = thrown_wep_think; wep.nextthink = time + 0.5; + wep.pickup_anyway = TRUE; // these are ALWAYS pickable return s; } } @@ -236,6 +271,20 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto float W_IsWeaponThrowable(float w) { float wb, wa; + + if (!autocvar_g_pickup_items) + return 0; + if (g_weaponarena) + return 0; + if (g_lms) + return 0; + if (g_ca) + return 0; + if (g_cts) + return 0; + if (g_nexball && w == WEP_GRENADE_LAUNCHER) + return 0; + wb = W_WeaponBit(w); if(!wb) return 0; @@ -257,7 +306,7 @@ float W_IsWeaponThrowable(float w) // toss current weapon void W_ThrowWeapon(vector velo, vector delta, float doreduce) { - local float w, wb; + float w, wb; string a; w = self.weapon; @@ -265,26 +314,12 @@ void W_ThrowWeapon(vector velo, vector delta, float doreduce) return; // just in case if(MUTATOR_CALLHOOK(ForbidThrowCurrentWeapon)) return; - if (g_weaponarena) - return; - if (g_lms) - return; - if (g_nexball && w == WEP_GRENADE_LAUNCHER) - return; - if (!autocvar_g_pickup_items) - return; - if (g_ca) - return; - if (g_cts) - return; if(!autocvar_g_weapon_throwable) return; - if(autocvar_g_weapon_stay == 1) + if(self.weaponentity.state != WS_READY) return; if(!W_IsWeaponThrowable(w)) return; - if(self.deadflag == DEAD_NO && self.weaponentity.state != WS_READY) - return; wb = W_WeaponBit(w); if(self.weapons & wb != wb) @@ -295,14 +330,11 @@ void W_ThrowWeapon(vector velo, vector delta, float doreduce) a = W_ThrowNewWeapon(self, w, doreduce, self.origin + delta, velo); if not(a) return; - if(self.health >= 1) - { - if(a == "") - sprint(self, strcat("You dropped the ^2", W_Name(w), "\n")); - else - sprint(self, strcat("You dropped the ^2", W_Name(w), " with ", a, "\n")); - } -}; + if(a == "") + sprint(self, strcat("You dropped the ^2", W_Name(w), "\n")); + else + sprint(self, strcat("You dropped the ^2", W_Name(w), " with ", a, "\n")); +} // Bringed back weapon frame void W_WeaponFrame() @@ -315,7 +347,7 @@ void W_WeaponFrame() if(((arena_roundbased || g_ca || g_freezetag) && time < warmup) || ((time < game_starttime) && !autocvar_sv_ready_restart_after_countdown)) return; - if(g_freezetag && self.freezetag_frozen == 1) + if(self.freezetag_frozen == 1) return; if (!self.weaponentity || self.health < 1) @@ -324,6 +356,7 @@ void W_WeaponFrame() if(!self.switchweapon) { self.weapon = 0; + self.switchingweapon = 0; self.weaponentity.state = WS_CLEAR; self.weaponname = ""; self.items &~= IT_AMMO; @@ -340,22 +373,44 @@ void W_WeaponFrame() { if (self.weaponentity.state == WS_CLEAR) { - setanim(self, self.anim_draw, FALSE, TRUE, TRUE); + // end switching! + self.switchingweapon = self.switchweapon; + + //setanim(self, self.anim_draw, FALSE, TRUE, TRUE); self.weaponentity.state = WS_RAISE; weapon_action(self.switchweapon, WR_SETUP); + + // set our clip load to the load of the weapon we switched to, if it's reloadable + entity e; + e = get_weaponinfo(self.switchweapon); + if(e.spawnflags & WEP_FLAG_RELOADABLE && cvar(strcat("g_balance_", e.netname, "_reload_ammo"))) // prevent accessing undefined cvars + { + self.clip_load = self.(weapon_load[self.switchweapon]); + self.clip_size = cvar(strcat("g_balance_", e.netname, "_reload_ammo")); + } + else + self.clip_load = self.clip_size = 0; + // VorteX: add player model weapon select frame here // setcustomframe(PlayerWeaponRaise); weapon_thinkf(WFRAME_IDLE, autocvar_g_balance_weaponswitchdelay, w_ready); weapon_boblayer1(PLAYER_WEAPONSELECTION_SPEED, '0 0 0'); } + else if (self.weaponentity.state == WS_DROP) + { + // in dropping phase we can switch at any time + self.switchingweapon = self.switchweapon; + } else if (self.weaponentity.state == WS_READY) { + // start switching! + self.switchingweapon = self.switchweapon; + #ifndef INDEPENDENT_ATTACK_FINISHED if(ATTACK_FINISHED(self) <= time + self.weapon_frametime * 0.5) { #endif - // UGLY WORKAROUND: play this on CHAN_WEAPON2 so it can't cut off fire sounds - sound (self, CHAN_WEAPON2, "weapons/weapon_switch.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_WEAPON_SINGLE, "weapons/weapon_switch.wav", VOL_BASE, ATTN_NORM); self.weaponentity.state = WS_DROP; // set up weapon switch think in the future, and start drop anim weapon_thinkf(WFRAME_DONTCHANGE, autocvar_g_balance_weaponswitchdelay, w_clear); @@ -376,24 +431,27 @@ void W_WeaponFrame() // call the think code which may fire the weapon // and do so multiple times to resolve framerate dependency issues if the // server framerate is very low and the weapon fire rate very high - local float c; + float c; c = 0; while (c < W_TICSPERFRAME) { c = c + 1; if(wb && ((self.weapons & wb) == 0)) { - W_SwitchWeapon_Force(self, w_getbestweapon(self)); + if(self.weapon == self.switchweapon) + W_SwitchWeapon_Force(self, w_getbestweapon(self)); wb = 0; } + + v_forward = fo; + v_right = ri; + v_up = up; + if(wb) - { - v_forward = fo; - v_right = ri; - v_up = up; - self.weaponentity_glowmod = '0 0 0'; // reset glowmod, weapon think function only *might* set it weapon_action(self.weapon, WR_THINK); - } + else + weapon_action(self.weapon, WR_GONETHINK); + if (time + self.weapon_frametime * 0.5 >= self.weapon_nextthink) { if(self.weapon_think) @@ -428,4 +486,4 @@ void W_WeaponFrame() else self.currentammo = 1; #endif -}; +} diff --git a/qcsrc/server/cl_weaponsystem.qc b/qcsrc/server/cl_weaponsystem.qc index 4f5e760444..3b69e13eb0 100644 --- a/qcsrc/server/cl_weaponsystem.qc +++ b/qcsrc/server/cl_weaponsystem.qc @@ -127,18 +127,31 @@ vector w_shotorg; vector w_shotdir; vector w_shotend; +.float prevstrengthsound; +.float prevstrengthsoundattempt; +void W_PlayStrengthSound(entity player) // void W_PlayStrengthSound +{ + if((!g_minstagib) + && (player.items & IT_STRENGTH) + && ((time > player.prevstrengthsound + autocvar_sv_strengthsound_antispam_time) // prevent insane sound spam + || (time > player.prevstrengthsoundattempt + autocvar_sv_strengthsound_antispam_refire_threshold))) + { + sound(player, CH_TRIGGER, "weapons/strength_fire.wav", VOL_BASE, ATTN_NORM); + player.prevstrengthsound = time; + } + player.prevstrengthsoundattempt = time; +} + // this function calculates w_shotorg and w_shotdir based on the weapon model // offset, trueaim and antilag, and won't put w_shotorg inside a wall. // make sure you call makevectors first (FIXME?) -.float prevstrengthsound; -.float prevstrengthsoundattempt; void W_SetupShot_Dir_ProjectileSize_Range(entity ent, vector s_forward, vector mi, vector ma, float antilag, float recoil, string snd, float chan, float maxdamage, float range) { float nudge = 1; // added to traceline target and subtracted from result - local float oldsolid; + float oldsolid; vector vecs, dv; oldsolid = ent.dphitcontentsmask; - if(ent.weapon == WEP_CAMPINGRIFLE) + if(ent.weapon == WEP_RIFLE) ent.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_CORPSE; else ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE; @@ -158,6 +171,10 @@ void W_SetupShot_Dir_ProjectileSize_Range(entity ent, vector s_forward, vector m v_right = vr; v_up = vu; + // un-adjust trueaim if shotend is too close + if(vlen(w_shotend - (ent.origin + ent.view_ofs)) < autocvar_g_trueaim_minrange) + w_shotend = ent.origin + ent.view_ofs + s_forward * autocvar_g_trueaim_minrange; + // track max damage if(accuracy_canbegooddamage(ent)) accuracy_add(ent, ent.weapon, maxdamage, 0); @@ -168,8 +185,6 @@ void W_SetupShot_Dir_ProjectileSize_Range(entity ent, vector s_forward, vector m vecs = ent.weaponentity.movedir; else vecs = '0 0 0'; - if(debug_shotorg != '0 0 0') - vecs = debug_shotorg; dv = v_right * -vecs_y + v_up * vecs_z; w_shotorg = ent.origin + ent.view_ofs + dv; @@ -237,24 +252,14 @@ void W_SetupShot_Dir_ProjectileSize_Range(entity ent, vector s_forward, vector m ent.punchangle_x = recoil * -1; if (snd != "") - sound (ent, chan, snd, VOL_BASE, ATTN_NORM); - - if(ent.items & IT_STRENGTH) - if(!g_minstagib) - if( - (time > ent.prevstrengthsound + autocvar_sv_strengthsound_antispam_time) - || - (time > ent.prevstrengthsoundattempt + autocvar_sv_strengthsound_antispam_refire_threshold) - ) // prevent insane sound spam { - sound(ent, CHAN_AUTO, "weapons/strength_fire.wav", VOL_BASE, ATTN_NORM); - ent.prevstrengthsound = time; + sound (ent, chan, snd, VOL_BASE, ATTN_NORM); + W_PlayStrengthSound(ent); } - ent.prevstrengthsoundattempt = time; // nudge w_shotend so a trace to w_shotend hits w_shotend = w_shotend + normalize(w_shotend - w_shotorg) * nudge; -}; +} #define W_SetupShot_Dir_ProjectileSize(ent,s_forward,mi,ma,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize_Range(ent, s_forward, mi, ma, antilag, recoil, snd, chan, maxdamage, MAX_SHOT_DISTANCE) #define W_SetupShot_ProjectileSize(ent,mi,ma,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize(ent, v_forward, mi, ma, antilag, recoil, snd, chan, maxdamage) @@ -271,27 +276,6 @@ float CL_Weaponentity_CustomizeEntityForClient() return TRUE; } -float qcweaponanimation; -vector weapon_offset = '0 -10 0'; -vector weapon_adjust = '10 0 -15'; -.vector weapon_morph0origin; -.vector weapon_morph0angles; -.float weapon_morph0time; -.vector weapon_morph1origin; -.vector weapon_morph1angles; -.float weapon_morph1time; -.vector weapon_morph2origin; -.vector weapon_morph2angles; -.float weapon_morph2time; -.vector weapon_morph3origin; -.vector weapon_morph3angles; -.float weapon_morph3time; -.vector weapon_morph4origin; -.vector weapon_morph4angles; -.float weapon_morph4time; -.string weaponname; -#define QCWEAPONANIMATION_ORIGIN(e) ((weapon_offset_x + e.view_ofs_x) * v_forward - (weapon_offset_y + e.view_ofs_y) * v_right + (weapon_offset_z + e.view_ofs_z) * v_up + weapon_adjust) - /* * supported formats: * @@ -345,8 +329,6 @@ vector weapon_adjust = '10 0 -15'; // remove the ent void CL_WeaponEntity_SetModel(string name) { - string animfilename; - float animfile; float v_shot_idx; if (name != "") { @@ -358,140 +340,115 @@ void CL_WeaponEntity_SetModel(string name) if(!v_shot_idx) v_shot_idx = gettagindex(self, "tag_shot"); - if(qcweaponanimation) + setmodel(self, strcat("models/weapons/h_", name, ".iqm")); // precision set below + // preset some defaults that work great for renamed zym files (which don't need an animinfo) + self.anim_fire1 = animfixfps(self, '0 1 0.01'); + self.anim_fire2 = animfixfps(self, '1 1 0.01'); + self.anim_idle = animfixfps(self, '2 1 0.01'); + self.anim_reload = animfixfps(self, '3 1 0.01'); + + // if we have a "weapon" tag, let's attach the v_ model to it ("invisible hand" style model) + // if we don't, this is a "real" animated model + if(gettagindex(self, "weapon")) + { + if (!self.weaponentity) + self.weaponentity = spawn(); + setmodel(self.weaponentity, strcat("models/weapons/v_", name, ".md3")); // precision does not matter + setattachment(self.weaponentity, self, "weapon"); + } + else if(gettagindex(self, "tag_weapon")) { - self.angles = '0 0 0'; - makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0' + self.angles_z * '0 0 1'); - self.movedir = weapon_offset_x * v_forward - weapon_offset_y * v_right + weapon_offset_z * v_up + weapon_adjust; - self.movedir_x += 32; - self.spawnorigin = self.movedir; - // oldorigin - not calculated here + if (!self.weaponentity) + self.weaponentity = spawn(); + setmodel(self.weaponentity, strcat("models/weapons/v_", name, ".md3")); // precision does not matter + setattachment(self.weaponentity, self, "tag_weapon"); } else { - setmodel(self, strcat("models/weapons/h_", name, ".iqm")); // precision set below - animfilename = strcat("models/weapons/h_", name, ".iqm.animinfo"); - animfile = fopen(animfilename, FILE_READ); - // preset some defaults that work great for renamed zym files (which don't need an animinfo) - self.anim_fire1 = '0 1 0.01'; - self.anim_fire2 = '1 1 0.01'; - self.anim_idle = '2 1 0.01'; - self.anim_reload = '3 1 0.01'; - if (animfile >= 0) - { - animparseerror = FALSE; - self.anim_fire1 = animparseline(animfile); - self.anim_fire2 = animparseline(animfile); - self.anim_idle = animparseline(animfile); - self.anim_reload = animparseline(animfile); - fclose(animfile); - if (animparseerror) - print("Parse error in ", animfilename, ", some player animations are broken\n"); - } - - // if we have a "weapon" tag, let's attach the v_ model to it ("invisible hand" style model) - // if we don't, this is a "real" animated model - if(gettagindex(self, "weapon")) - { - if (!self.weaponentity) - self.weaponentity = spawn(); - setmodel(self.weaponentity, strcat("models/weapons/v_", name, ".md3")); // precision does not matter - setattachment(self.weaponentity, self, "weapon"); - } - else if(gettagindex(self, "tag_weapon")) - { - if (!self.weaponentity) - self.weaponentity = spawn(); - setmodel(self.weaponentity, strcat("models/weapons/v_", name, ".md3")); // precision does not matter - setattachment(self.weaponentity, self, "tag_weapon"); - } - else - { - if(self.weaponentity) - remove(self.weaponentity); - self.weaponentity = world; - } + if(self.weaponentity) + remove(self.weaponentity); + self.weaponentity = world; + } - setorigin(self,'0 0 0'); - self.angles = '0 0 0'; - self.frame = 0; - self.viewmodelforclient = world; + setorigin(self,'0 0 0'); + self.angles = '0 0 0'; + self.frame = 0; + self.viewmodelforclient = world; - float idx; + float idx; - if(v_shot_idx) // v_ model attached to invisible h_ model + if(v_shot_idx) // v_ model attached to invisible h_ model + { + self.movedir = gettaginfo(self.weaponentity, v_shot_idx); + } + else + { + idx = gettagindex(self, "shot"); + if(!idx) + idx = gettagindex(self, "tag_shot"); + if(idx) + self.movedir = gettaginfo(self, idx); + else { - self.movedir = gettaginfo(self.weaponentity, v_shot_idx); + print("WARNING: weapon model ", self.model, " does not support the 'shot' tag, will display shots TOTALLY wrong\n"); + self.movedir = '0 0 0'; } + } + + if(self.weaponentity) // v_ model attached to invisible h_ model + { + idx = gettagindex(self.weaponentity, "shell"); + if(!idx) + idx = gettagindex(self.weaponentity, "tag_shell"); + if(idx) + self.spawnorigin = gettaginfo(self.weaponentity, idx); + } + else + idx = 0; + if(!idx) + { + idx = gettagindex(self, "shell"); + if(!idx) + idx = gettagindex(self, "tag_shell"); + if(idx) + self.spawnorigin = gettaginfo(self, idx); else { - idx = gettagindex(self, "shot"); - if(!idx) - idx = gettagindex(self, "tag_shot"); - if(idx) - self.movedir = gettaginfo(self, idx); - else - { - print("WARNING: weapon model ", self.model, " does not support the 'shot' tag, will display shots TOTALLY wrong\n"); - self.movedir = '0 0 0'; - } + print("WARNING: weapon model ", self.model, " does not support the 'shell' tag, will display casings wrong\n"); + self.spawnorigin = self.movedir; } + } - if(self.weaponentity) // v_ model attached to invisible h_ model + if(v_shot_idx) + { + self.oldorigin = '0 0 0'; // use regular attachment + } + else + { + if(self.weaponentity) { - idx = gettagindex(self.weaponentity, "shell"); + idx = gettagindex(self, "weapon"); if(!idx) - idx = gettagindex(self.weaponentity, "tag_shell"); - if(idx) - self.spawnorigin = gettaginfo(self.weaponentity, idx); + idx = gettagindex(self, "tag_weapon"); } else - idx = 0; - if(!idx) { - idx = gettagindex(self, "shell"); + idx = gettagindex(self, "handle"); if(!idx) - idx = gettagindex(self, "tag_shell"); - if(idx) - self.spawnorigin = gettaginfo(self, idx); - else - { - print("WARNING: weapon model ", self.model, " does not support the 'shell' tag, will display casings wrong\n"); - self.spawnorigin = self.movedir; - } + idx = gettagindex(self, "tag_handle"); } - - if(v_shot_idx) + if(idx) { - self.oldorigin = '0 0 0'; // use regular attachment + self.oldorigin = self.movedir - gettaginfo(self, idx); } else { - if(self.weaponentity) - { - idx = gettagindex(self, "weapon"); - if(!idx) - idx = gettagindex(self, "tag_weapon"); - } - else - { - idx = gettagindex(self, "handle"); - if(!idx) - idx = gettagindex(self, "tag_handle"); - } - if(idx) - { - self.oldorigin = self.movedir - gettaginfo(self, idx); - } - else - { - print("WARNING: weapon model ", self.model, " does not support the 'handle' tag and neither does the v_ model support the 'shot' tag, will display muzzle flashes TOTALLY wrong\n"); - self.oldorigin = '0 0 0'; // there is no way to recover from this - } + print("WARNING: weapon model ", self.model, " does not support the 'handle' tag and neither does the v_ model support the 'shot' tag, will display muzzle flashes TOTALLY wrong\n"); + self.oldorigin = '0 0 0'; // there is no way to recover from this } - - self.viewmodelforclient = self.owner; } + + self.viewmodelforclient = self.owner; } else { @@ -523,24 +480,9 @@ void CL_WeaponEntity_SetModel(string name) self.spawnorigin += self.view_ofs; // offset the casings origin by the same amount // check if an instant weapon switch occurred - if (qcweaponanimation) - { - if (self.state == WS_READY) - { - self.angles = '0 0 0'; - makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0' + self.angles_z * '0 0 1'); - setorigin(self, QCWEAPONANIMATION_ORIGIN(self)); - } - } - else - setorigin(self, self.view_ofs); + setorigin(self, self.view_ofs); // reset animstate now self.wframe = WFRAME_IDLE; - self.weapon_morph0time = 0; - self.weapon_morph1time = 0; - self.weapon_morph2time = 0; - self.weapon_morph3time = 0; - self.weapon_morph4time = 0; setanim(self, self.anim_idle, TRUE, FALSE, TRUE); } @@ -579,9 +521,9 @@ void CL_Weaponentity_Think() self.weaponentity.model = ""; return; } - if (self.cnt != self.owner.weapon || self.dmg != self.owner.modelindex || self.deadflag != self.owner.deadflag) + if (self.weaponname != self.owner.weaponname || self.dmg != self.owner.modelindex || self.deadflag != self.owner.deadflag) { - self.cnt = self.owner.weapon; + self.weaponname = self.owner.weaponname; self.dmg = self.owner.modelindex; self.deadflag = self.owner.deadflag; @@ -614,161 +556,24 @@ void CL_Weaponentity_Think() } self.angles = '0 0 0'; - local float f; + float f; f = 0; if (self.state == WS_RAISE && !intermission_running) { f = (self.owner.weapon_nextthink - time) * g_weaponratefactor / autocvar_g_balance_weaponswitchdelay; self.angles_x = -90 * f * f; - if (qcweaponanimation) - { - makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0' + self.angles_z * '0 0 1'); - setorigin(self, QCWEAPONANIMATION_ORIGIN(self)); - } } else if (self.state == WS_DROP && !intermission_running) { f = 1 - (self.owner.weapon_nextthink - time) * g_weaponratefactor / autocvar_g_balance_weaponswitchdelay; self.angles_x = -90 * f * f; - if (qcweaponanimation) - { - makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0' + self.angles_z * '0 0 1'); - setorigin(self, QCWEAPONANIMATION_ORIGIN(self)); - } } else if (self.state == WS_CLEAR) { f = 1; self.angles_x = -90 * f * f; - if (qcweaponanimation) - { - makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0' + self.angles_z * '0 0 1'); - setorigin(self, QCWEAPONANIMATION_ORIGIN(self)); - } - } - else if (qcweaponanimation && time < self.owner.weapon_morph1time) - { - f = (time - self.owner.weapon_morph0time) / (self.owner.weapon_morph1time - self.owner.weapon_morph0time); - f = 1 - pow(1 - f, 3); - self.angles = self.owner.weapon_morph0angles * (1 - f) + self.owner.weapon_morph1angles * f; - setorigin(self, self.owner.weapon_morph0origin * (1 - f) + self.owner.weapon_morph1origin * f); - } - else if (qcweaponanimation && time < self.owner.weapon_morph2time) - { - f = (time - self.owner.weapon_morph1time) / (self.owner.weapon_morph2time - self.owner.weapon_morph1time); - f = 1 - pow(1 - f, 3); - self.angles = self.owner.weapon_morph1angles * (1 - f) + self.owner.weapon_morph2angles * f; - setorigin(self, self.owner.weapon_morph1origin * (1 - f) + self.owner.weapon_morph2origin * f); - } - else if (qcweaponanimation && time < self.owner.weapon_morph3time) - { - f = (time - self.owner.weapon_morph2time) / (self.owner.weapon_morph3time - self.owner.weapon_morph2time); - f = 1 - pow(1 - f, 3); - self.angles = self.owner.weapon_morph2angles * (1 - f) + self.owner.weapon_morph3angles * f; - setorigin(self, self.owner.weapon_morph2origin * (1 - f) + self.owner.weapon_morph3origin * f); - } - else if (qcweaponanimation && time < self.owner.weapon_morph4time) - { - f = (time - self.owner.weapon_morph3time) / (self.owner.weapon_morph4time - self.owner.weapon_morph3time); - f = 1 - pow(1 - f, 3); - self.angles = self.owner.weapon_morph3angles * (1 - f) + self.owner.weapon_morph4angles * f; - setorigin(self, self.owner.weapon_morph3origin * (1 - f) + self.owner.weapon_morph4origin * f); - } - else if (qcweaponanimation) - { - // begin a new idle morph - self.owner.weapon_morph0time = time; - self.owner.weapon_morph0angles = self.angles; - self.owner.weapon_morph0origin = self.origin; - - float r; - float t; - - r = random(); - if (r < 0.1) - { - // turn gun to the left to look at it - t = 2; - self.owner.weapon_morph1time = time + t * 0.2; - self.owner.weapon_morph1angles = randomvec() * 3 + '-5 30 0'; - makevectors(self.owner.weapon_morph1angles_x * '-1 0 0' + self.owner.weapon_morph1angles_y * '0 1 0' + self.owner.weapon_morph1angles_z * '0 0 1'); - self.owner.weapon_morph1origin = QCWEAPONANIMATION_ORIGIN(self); - - self.owner.weapon_morph2time = time + t * 0.6; - self.owner.weapon_morph2angles = randomvec() * 3 + '-5 30 0'; - makevectors(self.owner.weapon_morph2angles_x * '-1 0 0' + self.owner.weapon_morph2angles_y * '0 1 0' + self.owner.weapon_morph2angles_z * '0 0 1'); - self.owner.weapon_morph2origin = QCWEAPONANIMATION_ORIGIN(self); - - self.owner.weapon_morph3time = time + t; - self.owner.weapon_morph3angles = '0 0 0'; - makevectors(self.owner.weapon_morph3angles_x * '-1 0 0' + self.owner.weapon_morph3angles_y * '0 1 0' + self.owner.weapon_morph3angles_z * '0 0 1'); - self.owner.weapon_morph3origin = QCWEAPONANIMATION_ORIGIN(self); - } - else if (r < 0.2) - { - // raise the gun a bit - t = 2; - self.owner.weapon_morph1time = time + t * 0.2; - self.owner.weapon_morph1angles = randomvec() * 3 + '30 -10 0'; - makevectors(self.owner.weapon_morph1angles_x * '-1 0 0' + self.owner.weapon_morph1angles_y * '0 1 0' + self.owner.weapon_morph1angles_z * '0 0 1'); - self.owner.weapon_morph1origin = QCWEAPONANIMATION_ORIGIN(self); - - self.owner.weapon_morph2time = time + t * 0.5; - self.owner.weapon_morph2angles = randomvec() * 3 + '30 -10 5'; - makevectors(self.owner.weapon_morph2angles_x * '-1 0 0' + self.owner.weapon_morph2angles_y * '0 1 0' + self.owner.weapon_morph2angles_z * '0 0 1'); - self.owner.weapon_morph2origin = QCWEAPONANIMATION_ORIGIN(self); - - self.owner.weapon_morph3time = time + t; - self.owner.weapon_morph3angles = '0 0 0'; - makevectors(self.owner.weapon_morph3angles_x * '-1 0 0' + self.owner.weapon_morph3angles_y * '0 1 0' + self.owner.weapon_morph3angles_z * '0 0 1'); - self.owner.weapon_morph3origin = QCWEAPONANIMATION_ORIGIN(self); - } - else if (r < 0.3) - { - // tweak it a bit - t = 5; - self.owner.weapon_morph1time = time + t * 0.3; - self.owner.weapon_morph1angles = randomvec() * 6; - makevectors(self.owner.weapon_morph1angles_x * '-1 0 0' + self.owner.weapon_morph1angles_y * '0 1 0' + self.owner.weapon_morph1angles_z * '0 0 1'); - self.owner.weapon_morph1origin = QCWEAPONANIMATION_ORIGIN(self); - - self.owner.weapon_morph2time = time + t * 0.7; - self.owner.weapon_morph2angles = randomvec() * 6; - makevectors(self.owner.weapon_morph2angles_x * '-1 0 0' + self.owner.weapon_morph2angles_y * '0 1 0' + self.owner.weapon_morph2angles_z * '0 0 1'); - self.owner.weapon_morph2origin = QCWEAPONANIMATION_ORIGIN(self); - - self.owner.weapon_morph3time = time + t; - self.owner.weapon_morph3angles = '0 0 0'; - makevectors(self.owner.weapon_morph3angles_x * '-1 0 0' + self.owner.weapon_morph3angles_y * '0 1 0' + self.owner.weapon_morph3angles_z * '0 0 1'); - self.owner.weapon_morph3origin = QCWEAPONANIMATION_ORIGIN(self); - } - else - { - // hold it mostly steady - t = random() * 6 + 4; - self.owner.weapon_morph1time = time + t * 0.2; - self.owner.weapon_morph1angles = randomvec() * 1; - makevectors(self.owner.weapon_morph1angles_x * '-1 0 0' + self.owner.weapon_morph1angles_y * '0 1 0' + self.owner.weapon_morph1angles_z * '0 0 1'); - self.owner.weapon_morph1origin = QCWEAPONANIMATION_ORIGIN(self); - - self.owner.weapon_morph2time = time + t * 0.5; - self.owner.weapon_morph2angles = randomvec() * 1; - makevectors(self.owner.weapon_morph2angles_x * '-1 0 0' + self.owner.weapon_morph2angles_y * '0 1 0' + self.owner.weapon_morph2angles_z * '0 0 1'); - self.owner.weapon_morph2origin = QCWEAPONANIMATION_ORIGIN(self); - - self.owner.weapon_morph3time = time + t * 0.7; - self.owner.weapon_morph3angles = randomvec() * 1; - makevectors(self.owner.weapon_morph3angles_x * '-1 0 0' + self.owner.weapon_morph3angles_y * '0 1 0' + self.owner.weapon_morph3angles_z * '0 0 1'); - self.owner.weapon_morph3origin = QCWEAPONANIMATION_ORIGIN(self); - } - - self.owner.weapon_morph4time = time + t; - self.owner.weapon_morph4angles = '0 0 0'; - makevectors(self.owner.weapon_morph4angles_x * '-1 0 0' + self.owner.weapon_morph4angles_y * '0 1 0' + self.owner.weapon_morph4angles_z * '0 0 1'); - self.owner.weapon_morph4origin = QCWEAPONANIMATION_ORIGIN(self); - } -}; +} void CL_ExteriorWeaponentity_Think() { @@ -785,9 +590,9 @@ void CL_ExteriorWeaponentity_Think() self.model = ""; return; } - if (self.cnt != self.owner.weapon || self.dmg != self.owner.modelindex || self.deadflag != self.owner.deadflag) + if (self.weaponname != self.owner.weaponname || self.dmg != self.owner.modelindex || self.deadflag != self.owner.deadflag) { - self.cnt = self.owner.weapon; + self.weaponname = self.owner.weaponname; self.dmg = self.owner.modelindex; self.deadflag = self.owner.deadflag; if (self.owner.weaponname != "") @@ -802,10 +607,6 @@ void CL_ExteriorWeaponentity_Think() } else setattachment(self, self.owner, "bip01 r hand"); - - // if that didn't find a tag, hide the exterior weapon model - if (!self.tag_index) - self.model = ""; } self.effects = self.owner.effects; if(sv_pitch_min == sv_pitch_max) @@ -820,38 +621,63 @@ void CL_ExteriorWeaponentity_Think() else self.alpha = 1; - ang_x = bound(sv_pitch_min, self.owner.v_angle_x, sv_pitch_max); - ang_y = 0; - ang_z = 0; - - if(sv_pitch_fixyaw) // workaround for stupid player models that don't aim forward + if (!intermission_running) { - ang_y = self.owner.v_angle_y; - makevectors(ang); - var vector v = v_forward; - var float t = self.tag_entity.frame1time; - var float f = self.tag_entity.frame; - self.tag_entity.frame1time = time; - self.tag_entity.frame = self.tag_entity.anim_idle_x; - gettaginfo(self.tag_entity, self.tag_index); - self.tag_entity.frame1time = t; - self.tag_entity.frame = f; - // untransform v according to this coordinate space - vector w; - w_x = v_forward * v; - w_y = -v_right * v; - w_z = v_up * v; - self.angles = vectoangles(w); - } - else - { - ang_x = -/* don't ask */ang_x; - self.angles = ang; + ang_x = bound(sv_pitch_min, self.owner.v_angle_x, sv_pitch_max); + ang_y = 0; + ang_z = 0; + + if(sv_pitch_fixyaw) // workaround for stupid player models that don't aim forward + { + ang_y = self.owner.v_angle_y; + makevectors(ang); + var vector v = v_forward; + var float t = self.tag_entity.frame1time; + var float f = self.tag_entity.frame; + self.tag_entity.frame1time = time; + self.tag_entity.frame = self.tag_entity.anim_idle_x; + gettaginfo(self.tag_entity, self.tag_index); + self.tag_entity.frame1time = t; + self.tag_entity.frame = f; + // untransform v according to this coordinate space + vector w; + w_x = v_forward * v; + w_y = -v_right * v; + w_z = v_up * v; + self.angles = vectoangles(w); + } + else + { + ang_x = -/* don't ask */ang_x; + self.angles = ang; + } + + if(autocvar_g_loituma) + { + vector modangles; + float t; + + t = time * autocvar_g_loituma; + + modangles_x = t * 360; + modangles_y = 90; + modangles_z = 0; + + self.angles = + AnglesTransform_ToAngles( + AnglesTransform_Multiply( + AnglesTransform_FromAngles(self.angles), + AnglesTransform_FromAngles(modangles) + ) + ); + } } self.glowmod = self.owner.weaponentity_glowmod; self.colormap = self.owner.colormap; -}; + + CSQCMODEL_AUTOUPDATE(); +} // spawning weaponentity for client void CL_SpawnWeaponentity() @@ -878,7 +704,14 @@ void CL_SpawnWeaponentity() self.exteriorweaponentity.angles = '0 0 0'; self.exteriorweaponentity.think = CL_ExteriorWeaponentity_Think; self.exteriorweaponentity.nextthink = time; -}; + + { + entity oldself = self; + self = self.exteriorweaponentity; + CSQCMODEL_AUTOINIT(); + self = oldself; + } +} void Send_WeaponComplain (entity e, float wpn, string wpnname, float type) { @@ -894,8 +727,8 @@ void Send_WeaponComplain (entity e, float wpn, string wpnname, float type) float client_hasweapon(entity cl, float wpn, float andammo, float complain) { - local float weaponbit, f; - local entity oldself; + float weaponbit, f; + entity oldself; if(time < self.hasweapon_complain_spam) complain = 0; @@ -925,7 +758,7 @@ float client_hasweapon(entity cl, float wpn, float andammo, float complain) f = f + weapon_action(wpn, WR_CHECKAMMO2); // always allow selecting the Mine Layer if we placed mines, so that we can detonate them - local entity mine; + entity mine; if(wpn == WEP_MINE_LAYER) for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self) f = 1; @@ -975,7 +808,8 @@ float client_hasweapon(entity cl, float wpn, float andammo, float complain) world, e.origin, self, 0, world, enemy, - 0 + 0, + RADARICON_NONE, '0 0 0' ); } } @@ -989,41 +823,44 @@ float client_hasweapon(entity cl, float wpn, float andammo, float complain) play2(cl, "weapons/unavailable.wav"); } return FALSE; -}; +} // Weapon subs void w_clear() { if (self.weapon != -1) + { self.weapon = 0; + self.switchingweapon = 0; + } if (self.weaponentity) { self.weaponentity.state = WS_CLEAR; self.weaponentity.effects = 0; } -}; +} void w_ready() { if (self.weaponentity) self.weaponentity.state = WS_READY; weapon_thinkf(WFRAME_IDLE, 1000000, w_ready); -}; +} // Setup weapon for client (after this raise frame will be launched) void weapon_setup(float windex) { entity e; - qcweaponanimation = autocvar_sv_qcweaponanimation; e = get_weaponinfo(windex); self.items &~= IT_AMMO; self.items = self.items | e.items; // the two weapon entities will notice this has changed and update their models self.weapon = windex; + self.switchingweapon = windex; // to make sure self.weaponname = e.mdl; self.bulletcounter = 0; -}; +} // perform weapon to attack (weaponstate and attack_finished check is here) void W_SwitchToOtherWeapon(entity pl) @@ -1037,25 +874,47 @@ void W_SwitchToOtherWeapon(entity pl) if(ww) W_SwitchWeapon_Force(pl, ww); } + +string PrimaryOrSecondary(float secondary) +{ + if(secondary) + return "secondary"; + else + return "primary"; +} + .float prevdryfire; +.float prevwarntime; float weapon_prepareattack_checkammo(float secondary) { if not(self.items & IT_UNLIMITED_WEAPON_AMMO) if (!weapon_action(self.weapon, WR_CHECKAMMO1 + secondary)) { // always keep the Mine Layer if we placed mines, so that we can detonate them - local entity mine; + entity mine; if(self.weapon == WEP_MINE_LAYER) for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self) return FALSE; if(self.weapon == self.switchweapon && time - self.prevdryfire > 1) // only play once BEFORE starting to switch weapons { - sound (self, CHAN_AUTO, "weapons/dryfire.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_WEAPON_A, "weapons/dryfire.wav", VOL_BASE, ATTN_NORM); self.prevdryfire = time; } - W_SwitchToOtherWeapon(self); + if(weapon_action(self.weapon, WR_CHECKAMMO2 - secondary)) // check if the other firing mode has enough ammo + { + if(time - self.prevwarntime > 1) + { + sprint(self, strcat("^2", W_Name(self.weapon), " ", PrimaryOrSecondary(secondary), "^7 is unable to fire, but its ^2", PrimaryOrSecondary(1 - secondary), "^7 can.\n")); + } + self.prevwarntime = time; + } + else // this weapon is totally unable to fire, switch to another one + { + W_SwitchToOtherWeapon(self); + } + return FALSE; } return TRUE; @@ -1072,7 +931,7 @@ float weapon_prepareattack_check(float secondary, float attacktime) return FALSE; } - if (timeoutStatus == 2) //don't allow the player to shoot while game is paused + if (timeout_status == TIMEOUT_ACTIVE) //don't allow the player to shoot while game is paused return FALSE; // do not even think about shooting if switching @@ -1145,82 +1004,16 @@ void weapon_thinkf(float fr, float t, void() func) if (self.weaponentity) { self.weaponentity.wframe = fr; - if (qcweaponanimation) - { - if (fr != WFRAME_IDLE) - { - self.weapon_morph0time = time; - self.weapon_morph0angles = self.weaponentity.angles; - self.weapon_morph0origin = self.weaponentity.origin; - - self.weapon_morph1angles = '0 0 0'; - self.weapon_morph1time = time + t; - makevectors(self.weapon_morph1angles_x * '-1 0 0' + self.weapon_morph1angles_y * '0 1 0' + self.weapon_morph1angles_z * '0 0 1'); - self.weapon_morph1origin = QCWEAPONANIMATION_ORIGIN(self.weaponentity); - - self.weapon_morph2angles = '0 0 0'; - self.weapon_morph2time = time + t; - makevectors(self.weapon_morph2angles_x * '-1 0 0' + self.weapon_morph2angles_y * '0 1 0' + self.weapon_morph2angles_z * '0 0 1'); - self.weapon_morph2origin = QCWEAPONANIMATION_ORIGIN(self.weaponentity); - - self.weapon_morph3angles = '0 0 0'; - self.weapon_morph3time = time + t; - makevectors(self.weapon_morph3angles_x * '-1 0 0' + self.weapon_morph3angles_y * '0 1 0' + self.weapon_morph3angles_z * '0 0 1'); - self.weapon_morph3origin = QCWEAPONANIMATION_ORIGIN(self.weaponentity); - - self.weapon_morph4angles = '0 0 0'; - self.weapon_morph4time = time + t; - makevectors(self.weapon_morph4angles_x * '-1 0 0' + self.weapon_morph4angles_y * '0 1 0' + self.weapon_morph4angles_z * '0 0 1'); - self.weapon_morph4origin = QCWEAPONANIMATION_ORIGIN(self.weaponentity); - - if (fr == WFRAME_FIRE1) - { - self.weapon_morph1angles = '5 0 0'; - self.weapon_morph1time = time + t * 0.1; - makevectors(self.weapon_morph1angles_x * '-1 0 0' + self.weapon_morph1angles_y * '0 1 0' + self.weapon_morph1angles_z * '0 0 1'); - self.weapon_morph1origin = QCWEAPONANIMATION_ORIGIN(self.weaponentity); - self.weapon_morph4time = time + t + 1; // delay idle effect - } - else if (fr == WFRAME_FIRE2) - { - self.weapon_morph1angles = '10 0 0'; - self.weapon_morph1time = time + t * 0.1; - makevectors(self.weapon_morph1angles_x * '-1 0 0' + self.weapon_morph1angles_y * '0 1 0' + self.weapon_morph1angles_z * '0 0 1'); - self.weapon_morph1origin = QCWEAPONANIMATION_ORIGIN(self.weaponentity); - self.weapon_morph4time = time + t + 1; // delay idle effect - } - else if (fr == WFRAME_RELOAD) - { - self.weapon_morph1time = time + t * 0.05; - self.weapon_morph1angles = '-10 40 0'; - makevectors(self.weapon_morph1angles_x * '-1 0 0' + self.weapon_morph1angles_y * '0 1 0' + self.weapon_morph1angles_z * '0 0 1'); - self.weapon_morph1origin = QCWEAPONANIMATION_ORIGIN(self.weaponentity); - - self.weapon_morph2time = time + t * 0.15; - self.weapon_morph2angles = '-10 40 5'; - makevectors(self.weapon_morph2angles_x * '-1 0 0' + self.weapon_morph2angles_y * '0 1 0' + self.weapon_morph2angles_z * '0 0 1'); - self.weapon_morph2origin = QCWEAPONANIMATION_ORIGIN(self.weaponentity); - - self.weapon_morph3time = time + t * 0.25; - self.weapon_morph3angles = '-10 40 0'; - makevectors(self.weapon_morph3angles_x * '-1 0 0' + self.weapon_morph3angles_y * '0 1 0' + self.weapon_morph3angles_z * '0 0 1'); - self.weapon_morph3origin = QCWEAPONANIMATION_ORIGIN(self.weaponentity); - } - } - } - else - { - if (fr == WFRAME_IDLE) - a = self.weaponentity.anim_idle; - else if (fr == WFRAME_FIRE1) - a = self.weaponentity.anim_fire1; - else if (fr == WFRAME_FIRE2) - a = self.weaponentity.anim_fire2; - else if (fr == WFRAME_RELOAD) - a = self.weaponentity.anim_reload; - a_z *= g_weaponratefactor; - setanim(self.weaponentity, a, restartanim == FALSE, restartanim, restartanim); - } + if (fr == WFRAME_IDLE) + a = self.weaponentity.anim_idle; + else if (fr == WFRAME_FIRE1) + a = self.weaponentity.anim_fire1; + else if (fr == WFRAME_FIRE2) + a = self.weaponentity.anim_fire2; + else if (fr == WFRAME_RELOAD) + a = self.weaponentity.anim_reload; + a_z *= g_weaponratefactor; + setanim(self.weaponentity, a, restartanim == FALSE, restartanim, restartanim); } v_forward = of; @@ -1249,21 +1042,32 @@ void weapon_thinkf(float fr, float t, void() func) self.weapon_think = func; //dprint("next ", ftos(self.weapon_nextthink), "\n"); + // The shoot animation looks TERRIBLE without animation blending! Yay for moonwalking while shooting! + //anim = self.anim_shoot; if (restartanim) if (t) if (!self.crouch) // shoot anim stands up, this looks bad { - local vector anim; - anim = self.anim_shoot; - anim_z = anim_y / (t + sys_frametime); - setanim(self, anim, FALSE, TRUE, TRUE); + vector anim; + if(self.weapon == WEP_SHOTGUN && self.BUTTON_ATCK2) + { + anim = self.anim_melee; + anim_z = anim_y / (t + sys_frametime); + setanim(self, anim, FALSE, TRUE, TRUE); + } + else if (self.animstate_startframe == self.anim_idle_x) // only allow shoot anim to override idle animation until we have animation blending + { + anim = self.anim_shoot; + anim_z = anim_y / (t + sys_frametime); + setanim(self, anim, FALSE, TRUE, TRUE); + } } -}; +} void weapon_boblayer1(float spd, vector org) { // VorteX: haste can be added here -}; +} vector W_CalculateProjectileVelocity(vector pvelocity, vector mvelocity, float forceAbsolute) { @@ -1342,38 +1146,30 @@ void W_AttachToShotorg(entity flash, vector offset) entity xflash; flash.owner = self; flash.angles_z = random() * 360; - if(qcweaponanimation) - { - setorigin(flash, w_shotorg + w_shotdir * 50); - flash.angles = vectoangles(w_shotdir); - flash.angles_z = random() * 360; - } + + if(gettagindex(self.weaponentity, "shot")) + setattachment(flash, self.weaponentity, "shot"); else - { - if(gettagindex(self.weaponentity, "shot")) - setattachment(flash, self.weaponentity, "shot"); - else - setattachment(flash, self.weaponentity, "tag_shot"); - setorigin(flash, offset); + setattachment(flash, self.weaponentity, "tag_shot"); + setorigin(flash, offset); - xflash = spawn(); - copyentity(flash, xflash); + xflash = spawn(); + copyentity(flash, xflash); - flash.viewmodelforclient = self; + flash.viewmodelforclient = self; - if(self.weaponentity.oldorigin_x > 0) - { - setattachment(xflash, self.exteriorweaponentity, ""); - setorigin(xflash, self.weaponentity.oldorigin + offset); - } + if(self.weaponentity.oldorigin_x > 0) + { + setattachment(xflash, self.exteriorweaponentity, ""); + setorigin(xflash, self.weaponentity.oldorigin + offset); + } + else + { + if(gettagindex(self.exteriorweaponentity, "shot")) + setattachment(xflash, self.exteriorweaponentity, "shot"); else - { - if(gettagindex(self.exteriorweaponentity, "shot")) - setattachment(xflash, self.exteriorweaponentity, "shot"); - else - setattachment(xflash, self.exteriorweaponentity, "tag_shot"); - setorigin(xflash, offset); - } + setattachment(xflash, self.exteriorweaponentity, "tag_shot"); + setorigin(xflash, offset); } } @@ -1607,3 +1403,127 @@ void W_SetupProjectileVelocity(entity missile, float pSpeed, float spread) #define W_SETUPPROJECTILEVELOCITY_UP(m,s) W_SetupProjectileVelocityEx(m, w_shotdir, v_up, cvar(#s "_speed"), cvar(#s "_speed_up"), cvar(#s "_speed_z"), cvar(#s "_spread"), FALSE) #define W_SETUPPROJECTILEVELOCITY(m,s) W_SetupProjectileVelocityEx(m, w_shotdir, v_up, cvar(#s "_speed"), 0, 0, cvar(#s "_spread"), FALSE) + +void W_DecreaseAmmo(.float ammo_type, float ammo_use, float ammo_reload) +{ + if((self.items & IT_UNLIMITED_WEAPON_AMMO) && !ammo_reload) + return; + + // if this weapon is reloadable, decrease its load. Else decrease the player's ammo + if(ammo_reload) + { + self.clip_load -= ammo_use; + self.(weapon_load[self.weapon]) = self.clip_load; + } + else + self.(self.current_ammo) -= ammo_use; +} + +// weapon reloading code + +.float reload_ammo_amount, reload_ammo_min, reload_time; +.float reload_complain; +.string reload_sound; + +void W_ReloadedAndReady() +{ + // finish the reloading process, and do the ammo transfer + + self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading + + // if the gun uses no ammo, max out weapon load, else decrease ammo as we increase weapon load + if(!self.reload_ammo_min || self.items & IT_UNLIMITED_WEAPON_AMMO) + self.clip_load = self.reload_ammo_amount; + else + { + while(self.clip_load < self.reload_ammo_amount && self.(self.current_ammo)) // make sure we don't add more ammo than we have + { + self.clip_load += 1; + self.(self.current_ammo) -= 1; + } + } + self.(weapon_load[self.weapon]) = self.clip_load; + + // do not set ATTACK_FINISHED in reload code any more. This causes annoying delays if eg: You start reloading a weapon, + // then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there, + // so your weapon is disabled for a few seconds without reason + + //ATTACK_FINISHED(self) -= self.reload_time - 1; + + w_ready(); +} + +void W_Reload(float sent_ammo_min, float sent_ammo_amount, float sent_time, string sent_sound) +{ + // set global values to work with + + self.reload_ammo_min = sent_ammo_min; + self.reload_ammo_amount = sent_ammo_amount; + self.reload_time = sent_time; + self.reload_sound = sent_sound; + + // check if we meet the necessary conditions to reload + + entity e; + e = get_weaponinfo(self.weapon); + + // don't reload weapons that don't have the RELOADABLE flag + if not(e.spawnflags & WEP_FLAG_RELOADABLE) + { + dprint("Warning: Attempted to reload a weapon that does not have the WEP_FLAG_RELOADABLE flag. Fix your code!\n"); + return; + } + + // return if reloading is disabled for this weapon + if(!self.reload_ammo_amount) + return; + + // our weapon is fully loaded, no need to reload + if (self.clip_load >= self.reload_ammo_amount) + return; + + // no ammo, so nothing to load + if(!self.(self.current_ammo) && self.reload_ammo_min) + if not(self.items & IT_UNLIMITED_WEAPON_AMMO) + { + if(clienttype(self) == CLIENTTYPE_REAL && self.reload_complain < time) + { + play2(self, "weapons/unavailable.wav"); + sprint(self, strcat("You don't have enough ammo to reload the ^2", W_Name(self.weapon), "\n")); + self.reload_complain = time + 1; + } + // switch away if the amount of ammo is not enough to keep using this weapon + if not(weapon_action(self.weapon, WR_CHECKAMMO1) + weapon_action(self.weapon, WR_CHECKAMMO2)) + { + self.clip_load = -1; // reload later + W_SwitchToOtherWeapon(self); + } + return; + } + + if (self.weaponentity) + { + if (self.weaponentity.wframe == WFRAME_RELOAD) + return; + + // allow switching away while reloading, but this will cause a new reload! + self.weaponentity.state = WS_READY; + } + + // now begin the reloading process + + sound (self, CH_WEAPON_B, self.reload_sound, VOL_BASE, ATTN_NORM); + + // do not set ATTACK_FINISHED in reload code any more. This causes annoying delays if eg: You start reloading a weapon, + // then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there, + // so your weapon is disabled for a few seconds without reason + + //ATTACK_FINISHED(self) = max(time, ATTACK_FINISHED(self)) + self.reload_time + 1; + + weapon_thinkf(WFRAME_RELOAD, self.reload_time, W_ReloadedAndReady); + + if(self.clip_load < 0) + self.clip_load = 0; + self.old_clip_load = self.clip_load; + self.clip_load = self.(weapon_load[self.weapon]) = -1; +} diff --git a/qcsrc/server/clientcommands.qc b/qcsrc/server/clientcommands.qc deleted file mode 100644 index 9203d87a1a..0000000000 --- a/qcsrc/server/clientcommands.qc +++ /dev/null @@ -1,607 +0,0 @@ -entity nagger; -float readycount; -float Nagger_SendEntity(entity to, float sendflags) -{ - float nags, i, f, b; - entity e; - WriteByte(MSG_ENTITY, ENT_CLIENT_NAGGER); - - nags = 0; - if(readycount) - { - nags |= 1; - if(to.ready == 0) - nags |= 2; - } - if(votecalled) - { - nags |= 4; - if(to.vote_vote == 0) - nags |= 8; - } - if(inWarmupStage) - nags |= 16; - - if(sendflags & 128) - nags |= 128; - - WriteByte(MSG_ENTITY, nags); - - if(nags & 128) - { - WriteString(MSG_ENTITY, votecalledvote_display); - } - - if(nags & 1) - { - for(i = 1; i <= maxclients; i += 8) - { - for(f = 0, e = edict_num(i), b = 1; b < 256; b *= 2, e = nextent(e)) - if(clienttype(e) != CLIENTTYPE_REAL || e.ready) - f |= b; - WriteByte(MSG_ENTITY, f); - } - } - - return TRUE; -} -void Nagger_Init() -{ - Net_LinkEntity(nagger = spawn(), FALSE, 0, Nagger_SendEntity); -} -void Nagger_VoteChanged() -{ - if(nagger) - nagger.SendFlags |= 128; -} -void Nagger_VoteCountChanged() -{ - if(nagger) - nagger.SendFlags |= 1; -} -void Nagger_ReadyCounted() -{ - if(nagger) - nagger.SendFlags |= 1; -} - -void ReadyCount(); -string MapVote_Suggest(string m); - -entity GetPlayer(string name) -{ - float num; - entity e; - string ns; - - if(substring(name, 0, 1) == "#") { - num = stof(substring(name, 1, 999)); - if(num >= 1 && num <= maxclients) { - for((e = world); num > 0; --num, (e = nextent(e))) - ; - //if(clienttype(e) == CLIENTTYPE_REAL) - if(e.classname == "player") - return e; - } - } else { - ns = strdecolorize(name); - FOR_EACH_REALPLAYER(e) { - if(!strcasecmp(strdecolorize(e.netname), ns)) { - return e; - } - } - } - return world; -} - -//float ctf_clientcommand(); -float readyrestart_happened; -.float lms_spectate_warning; -void spawnfunc_func_breakable(); - -.float cmd_floodtime; -.float cmd_floodcount; -float cmd_floodcheck() -{ - if (timeoutStatus != 2) - { - if(time == self.cmd_floodtime) - { - self.cmd_floodcount += 1; - if(self.cmd_floodcount > 8) - return TRUE; - } - else - { - self.cmd_floodtime = time; - self.cmd_floodcount = 1; - } - } - return FALSE; -} - -void SV_ParseClientCommand(string s) { - string cmd; - float tokens; - float i; - entity e; - - tokens = tokenize_console(s); - - cmd = argv(0); - if(cmd != "reportcvar") - if(cmd != "sentcvar") - if(cmd != "pause") - if(cmd != "prespawn") - if(cmd != "spawn") - if(cmd != "begin") - { - if(cmd_floodcheck()) - return; - } - - if(GameCommand_Vote(s, self)) { - return; - } else if(GameCommand_MapVote(argv(0))) { - return; - } else if(cmd == "autoswitch") { - // be backwards compatible with older clients (enabled) - self.autoswitch = ("0" != argv(1)); - local string autoswitchmsg; - if (self.autoswitch) { - autoswitchmsg = "on"; - } else { - autoswitchmsg = "off"; - } - sprint(self, strcat("^1autoswitch turned ", autoswitchmsg, "\n")); - } else if(cmd == "clientversion") { - if not(self.flags & FL_CLIENT) - return; - if (argv(1) == "$gameversion") { - //versionmsg = "^1client is too old to get versioninfo.\nUPDATE!!! (http://www.xonotic.com)^8"; - // either that or someone wants to be funny - self.version = 1; - } else { - self.version = stof(argv(1)); - } - if(self.version < autocvar_gameversion_min || self.version > autocvar_gameversion_max) - { - self.version_mismatch = 1; - ClientKill_TeamChange(-2); // observe - } else if(autocvar_g_campaign || autocvar_g_balance_teams || autocvar_g_balance_teams_force) { - //JoinBestTeam(self, FALSE, TRUE); - } else if(teams_matter && !autocvar_sv_spectate && !(self.team_forced > 0)) { - self.classname = "observer"; - stuffcmd(self,"menu_showteamselect\n"); - } - } else if(cmd == "reportcvar") { // old system - if(substring(argv(2), 0, 1) == "$") // undefined cvar: use the default value on the server then - { - s = strcat(substring(s, argv_start_index(0), argv_end_index(1) - argv_start_index(0)), " \"", cvar_defstring(argv(1)), "\""); - tokens = tokenize_console(s); - } - GetCvars(1); - } else if(cmd == "sentcvar") { // new system - if(tokens == 2) // undefined cvar: use the default value on the server then - { - s = strcat(substring(s, argv_start_index(0), argv_end_index(1) - argv_start_index(0)), " \"", cvar_defstring(argv(1)), "\""); - tokens = tokenize_console(s); - } - GetCvars(1); - } else if(cmd == "spectate") { - if(cmd_floodcheck()) - return; - if not(self.flags & FL_CLIENT) - return; - if(g_arena) - return; - if(g_lms) - { - if(self.lms_spectate_warning) - { - // mark player as spectator - PlayerScore_Add(self, SP_LMS_RANK, 666 - PlayerScore_Add(self, SP_LMS_RANK, 0)); - } - else - { - self.lms_spectate_warning = 1; - sprint(self, "WARNING: you won't be able to enter the game again after spectating in LMS. Use the same command again to spectate anyway.\n"); - return; - } - } - if(self.classname == "player" && autocvar_sv_spectate == 1) { - ClientKill_TeamChange(-2); // observe - } - } else if(cmd == "join") { - if not(self.flags & FL_CLIENT) - return; - if(!g_arena) - if (self.classname != "player" && !lockteams) - { - if(isJoinAllowed()) { - self.classname = "player"; - if(g_ca) - self.caplayer = 1; - PlayerScore_Clear(self); - bprint ("^4", self.netname, "^4 is playing now\n"); - PutClientInServer(); - if(autocvar_g_campaign) - campaign_bots_may_start = 1; - } - else { - //player may not join because of g_maxplayers is set - centerprint_atprio(self, CENTERPRIO_MAPVOTE, PREVENT_JOIN_TEXT); - } - } - } else if( cmd == "selectteam" ) { - if not(self.flags & FL_CLIENT) - return; - if( !teams_matter ) { - sprint( self, "selectteam can only be used in teamgames\n"); - } else if(autocvar_g_campaign) { - //JoinBestTeam(self, 0); - } else if(self.team_forced > 0) { - sprint( self, "selectteam can not be used as your team is forced\n"); - } else if(lockteams) { - sprint( self, "^7The game has already begun, you must wait until the next map to be able to join a team.\n"); - } else if( argv(1) == "red" ) { - ClientKill_TeamChange(COLOR_TEAM1); - } else if( argv(1) == "blue" ) { - ClientKill_TeamChange(COLOR_TEAM2); - } else if( argv(1) == "yellow" ) { - ClientKill_TeamChange(COLOR_TEAM3); - } else if( argv(1) == "pink" ) { - ClientKill_TeamChange(COLOR_TEAM4); - } else if( argv(1) == "auto" ) { - ClientKill_TeamChange(-1); - } else { - sprint( self, strcat( "selectteam none/red/blue/yellow/pink/auto - \"", argv(1), "\" not recognised\n" ) ); - } - } else if(cmd == "ready") { - if not(self.flags & FL_CLIENT) - return; - - if((inWarmupStage) - || autocvar_sv_ready_restart || g_race_qualifying == 2) - { - if(!readyrestart_happened || autocvar_sv_ready_restart_repeatable) - { - if (self.ready) // toggle - { - self.ready = FALSE; - bprint(self.netname, "^2 is ^1NOT^2 ready\n"); - } - else - { - self.ready = TRUE; - bprint(self.netname, "^2 is ready\n"); - } - - // cannot reset the game while a timeout is active! - if(!timeoutStatus) - ReadyCount(); - } else { - sprint(self, "^1Game has already been restarted\n"); - } - } - } else if(cmd == "maplist") { - sprint(self, maplist_reply); - } else if(cmd == "lsmaps") { - sprint(self, lsmaps_reply); - } else if(cmd == "lsnewmaps") { - sprint(self, lsnewmaps_reply); - } else if(cmd == "records") { - for(i = 0; i < 10; ++i) - sprint(self, records_reply[i]); - } else if(cmd == "ladder") { - sprint(self, ladder_reply); - } else if(cmd == "rankings") { - sprint(self, rankings_reply); - } else if(cmd == "voice") { - if(tokens >= 3) - VoiceMessage(argv(1), substring(s, argv_start_index(2), argv_end_index(-1) - argv_start_index(2))); - else - VoiceMessage(argv(1), ""); - } else if(cmd == "say") { - if(tokens >= 2) - Say(self, FALSE, world, substring(s, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)), 1); - //clientcommand(self, formatmessage(s)); - } else if(cmd == "say_team") { - if(tokens >= 2) - Say(self, TRUE, world, substring(s, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)), 1); - //clientcommand(self, formatmessage(s)); - } else if(cmd == "tell") { - e = GetCommandPlayerSlotTargetFromTokenizedCommand(tokens, 1); - if(e && tokens > ParseCommandPlayerSlotTarget_firsttoken) - { - Say(self, FALSE, e, substring(s, argv_start_index(ParseCommandPlayerSlotTarget_firsttoken), argv_end_index(-1) - argv_start_index(ParseCommandPlayerSlotTarget_firsttoken)), TRUE); - } - else - { - if(tokens > ParseCommandPlayerSlotTarget_firsttoken) - trigger_magicear_processmessage_forallears(self, -1, world, substring(s, argv_start_index(ParseCommandPlayerSlotTarget_firsttoken), argv_end_index(-1) - argv_start_index(ParseCommandPlayerSlotTarget_firsttoken))); - sprint(self, "ERROR: usage: tell # playerid text...\n"); - } - //clientcommand(self, formatmessage(s)); - } else if(cmd == "info") { - cmd = cvar_string_builtin(strcat("sv_info_", argv(1))); // This needed fixed for the cvar check - if(cmd == "") - sprint(self, "ERROR: unsupported info command\n"); - else - wordwrap_sprint(cmd, 1111); - } else if(cmd == "suggestmap") { - sprint(self, strcat(MapVote_Suggest(argv(1)), "\n")); - } else if(cmd == "timeout") { - if not(self.flags & FL_CLIENT) - return; - if(autocvar_sv_timeout) { - if(self.classname == "player") { - if(votecalled) - sprint(self, "^7Error: you can not call a timeout while a vote is active!\n"); - else - evaluateTimeout(); - } - else - sprint(self, "^7Error: only players can call a timeout!\n"); - } - } else if(cmd == "timein") { - if not(self.flags & FL_CLIENT) - return; - if(autocvar_sv_timeout) { - evaluateTimein(); - } - } else if(cmd == "teamstatus") { - Score_NicePrint(self); - } else if(cmd == "cvar_changes") { - sprint(self, cvar_changes); - } else if(cmd == "cvar_purechanges") { - sprint(self, cvar_purechanges); - } else if(CheatCommand(tokens)) { - } else { - //if(ctf_clientcommand()) - // return; - // grep for Cmd_AddCommand_WithClientCommand to find them all - if(cmd != "status") - //if(cmd != "say") // handled above - //if(cmd != "say_team") // handled above - if(cmd != "kill") - if(cmd != "pause") - if(cmd != "ping") - if(cmd != "name") - if(cmd != "color") - if(cmd != "rate") - if(cmd != "pmodel") - if(cmd != "playermodel") - if(cmd != "playerskin") - if(cmd != "prespawn") - if(cmd != "spawn") - if(cmd != "begin") - if(cmd != "pings") - if(cmd != "sv_startdownload") - if(cmd != "download") - { - print("WARNING: Invalid clientcommand by ", self.netname, ": ", s, "\n"); - return; - } - - if(self.jointime > 0 && time > self.jointime + 10 && time > self.nickspamtime) // allow any changes in the first 10 seconds since joining - if(cmd == "name" || cmd == "playermodel") // TODO also playerskin and color? - { - if(self.nickspamtime == 0 || time > self.nickspamtime + autocvar_g_nick_flood_timeout) - // good, no serious flood - self.nickspamcount = 1; - else - self.nickspamcount += 1; - self.nickspamtime = time + autocvar_g_nick_flood_penalty; - - if (timeoutStatus == 2) //when game is paused, no flood protection - self.nickspamcount = self.nickspamtime = 0; - } - - clientcommand(self,s); - } -} - -void ReadyRestartForce() -{ - local entity e; - - bprint("^1Server is restarting...\n"); - - VoteReset(); - - // clear overtime - if (checkrules_overtimesadded > 0 && g_race_qualifying != 2) { - //we have to decrease timelimit to its original value again!! - float newTL; - newTL = autocvar_timelimit; - newTL -= checkrules_overtimesadded * autocvar_timelimit_overtime; - cvar_set("timelimit", ftos(newTL)); - } - - checkrules_suddendeathend = checkrules_overtimesadded = checkrules_suddendeathwarning = 0; - - - readyrestart_happened = 1; - game_starttime = time; - if(!g_ca && !g_arena) - game_starttime += RESTART_COUNTDOWN; - restart_mapalreadyrestarted = 0; //reset this var, needed when cvar sv_ready_restart_repeatable is in use - - inWarmupStage = 0; //once the game is restarted the game is in match stage - - //reset the .ready status of all players (also spectators) - FOR_EACH_CLIENTSLOT(e) - e.ready = 0; - readycount = 0; - Nagger_ReadyCounted(); // NOTE: this causes a resend of that entity, and will also turn off warmup state on the client - - if(autocvar_teamplay_lockonrestart && teams_matter) { - lockteams = 1; - bprint("^1The teams are now locked.\n"); - } - - //initiate the restart-countdown-announcer entity - if(autocvar_sv_ready_restart_after_countdown && !g_ca && !g_arena) - { - restartTimer = spawn(); - restartTimer.think = restartTimer_Think; - restartTimer.nextthink = game_starttime; - } - - //after a restart every players number of allowed timeouts gets reset, too - if(autocvar_sv_timeout) - { - FOR_EACH_REALPLAYER(e) - e.allowedTimeouts = autocvar_sv_timeout_number; - } - - //reset map immediately if this cvar is not set - if (!autocvar_sv_ready_restart_after_countdown) - reset_map(TRUE); - - if(autocvar_sv_eventlog) - GameLogEcho(":restart"); -} - -void ReadyRestart() -{ - // no arena, assault support yet... - if(g_arena | g_assault | gameover | intermission_running | race_completing) - localcmd("restart\n"); - else - localcmd("\nsv_hook_gamerestart\n"); - - ReadyRestartForce(); - - // reset ALL scores, but only do that at the beginning - //of the countdown if sv_ready_restart_after_countdown is off! - //Otherwise scores could be manipulated during the countdown! - if (!autocvar_sv_ready_restart_after_countdown) - Score_ClearAll(); -} - -/** - * Counts how many players are ready. If not enough players are ready, the function - * does nothing. If all players are ready, the timelimit will be extended and the - * restart_countdown variable is set to allow other functions like PlayerPostThink - * to detect that the countdown is now active. If the cvar sv_ready_restart_after_countdown - * is not set the map will be resetted. - * - * Function is called after the server receives a 'ready' sign from a player. - */ -void ReadyCount() -{ - local entity e; - local float r, p; - - r = p = 0; - - FOR_EACH_REALPLAYER(e) - { - p += 1; - if(e.ready) - r += 1; - } - - readycount = r; - - Nagger_ReadyCounted(); - - if(r) // at least one is ready - if(r == p) // and, everyone is ready - ReadyRestart(); -} - -/** - * Restarts the map after the countdown is over (and cvar sv_ready_restart_after_countdown - * is set) - */ -void restartTimer_Think() { - restart_mapalreadyrestarted = 1; - reset_map(TRUE); - Score_ClearAll(); - remove(self); - return; -} - -/** - * Checks whether the player who calls the timeout is allowed to do so. - * If so, it initializes the timeout countdown. It also checks whether another - * timeout was already running at this time and reacts correspondingly. - * - * affected globals/fields: .allowedTimeouts, remainingTimeoutTime, remainingLeadTime, - * timeoutInitiator, timeoutStatus, timeoutHandler - * - * This function is called when a player issues the calltimeout command. - */ -void evaluateTimeout() { - if (inWarmupStage && !g_warmup_allow_timeout) - return sprint(self, "^7Error: You can not call a timeout in warmup-stage!\n"); - if (time < game_starttime ) - return sprint(self, "^7Error: You can not call a timeout while the map is being restarted!\n"); - if (timeoutStatus != 2) { - //if the map uses a timelimit make sure that timeout cannot be called right before the map ends - if (autocvar_timelimit) { - //a timelimit was used - local float myTl; - myTl = autocvar_timelimit; - - local float lastPossibleTimeout; - lastPossibleTimeout = (myTl*60) - autocvar_sv_timeout_leadtime - 1; - - if (lastPossibleTimeout < time - game_starttime) - return sprint(self, "^7Error: It is too late to call a timeout now!\n"); - } - } - //player may not call a timeout if he has no calls left - if (self.allowedTimeouts < 1) - return sprint(self, "^7Error: You already used all your timeout calls for this map!\n"); - //now all required checks are passed - self.allowedTimeouts -= 1; - bprint(self.netname, " ^7called a timeout (", ftos(self.allowedTimeouts), " timeouts left)!\n"); //write a bprint who started the timeout (and how many he has left) - remainingTimeoutTime = autocvar_sv_timeout_length; - remainingLeadTime = autocvar_sv_timeout_leadtime; - timeoutInitiator = self; - if (timeoutStatus == 0) { //if another timeout was already active, don't change its status (which was 1 or 2) to 1, only change it to 1 if no timeout was active yet - timeoutStatus = 1; - //create the timeout indicator which centerprints the information to all players and takes care of pausing/unpausing - timeoutHandler = spawn(); - timeoutHandler.think = timeoutHandler_Think; - } - timeoutHandler.nextthink = time; //always let the entity think asap - - //inform all connected clients about the timeout call - Announce("timeoutcalled"); -} - -/** - * Checks whether a player is allowed to resume the game. If he is allowed to do it, - * and the lead time for the timeout is still active, this countdown just will be aborted (the - * game will never be paused). Otherwise the remainingTimeoutTime will be set to the corresponding - * value of the cvar sv_timeout_resumetime. - * - * This function is called when a player issues the resumegame command. - */ -void evaluateTimein() { - if (!timeoutStatus) - return sprint(self, "^7Error: There is no active timeout which could be aborted!\n"); - if (self != timeoutInitiator) - return sprint(self, "^7Error: You may not abort the active timeout. Only the player who called it can do that!\n"); - if (timeoutStatus == 1) { - remainingTimeoutTime = timeoutStatus = 0; - timeoutHandler.nextthink = time; //timeoutHandler has to take care of it immediately - bprint(strcat("^7The timeout was aborted by ", self.netname, " !\n")); - } - else if (timeoutStatus == 2) { - //only shorten the remainingTimeoutTime if it makes sense - if( remainingTimeoutTime > (autocvar_sv_timeout_resumetime + 1) ) { - bprint(strcat("^1Attention: ^7", self.netname, " resumed the game! Prepare for battle!\n")); - remainingTimeoutTime = autocvar_sv_timeout_resumetime; - timeoutHandler.nextthink = time; //timeoutHandler has to take care of it immediately - } - else - sprint(self, "^7Error: Your resumegame call was discarded!\n"); - - } -} diff --git a/qcsrc/server/command/banning.qc b/qcsrc/server/command/banning.qc new file mode 100644 index 0000000000..ab58a4aee3 --- /dev/null +++ b/qcsrc/server/command/banning.qc @@ -0,0 +1,231 @@ +// ===================================================== +// Banning and kicking command code, written by Samual +// Last updated: December 29th, 2011 +// ===================================================== + +void BanCommand_ban(float request, float argc, string command) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argc >= 2) + { + string ip = argv(1); + float reason_arg, bantime; + string reason; + + reason_arg = 2; + + GET_BAN_ARG(bantime, autocvar_g_ban_default_bantime); + GET_BAN_REASON(reason, "No reason provided"); + + Ban_Insert(ip, bantime, reason, 1); + return; + } + } + + default: + print("Incorrect parameters for ^2ban^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd ban address [bantime] [reason]\n"); + print(" 'address' is the IP address or range of the player to ban,\n"); + print(" 'bantime' is the amount of time that the ban is active (default if not provided),\n"); + print(" and 'reason' is the string to label the ban with as reason for banning.\n"); + print("See also: ^2banlist, kickban, unban^7\n"); + return; + } + } +} + +void BanCommand_banlist(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + Ban_View(); + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd banlist\n"); + print(" No arguments required.\n"); + print("See also: ^2ban, kickban, unban^7\n"); + return; + } + } +} + +void BanCommand_kickban(float request, float argc, string command) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argc >= 2) + { + entity client = GetIndexedEntity(argc, 1); + float accepted = VerifyClientEntity(client, TRUE, FALSE); + float reason_arg, bantime, masksize; + string reason; + + if(accepted > 0) + { + reason_arg = next_token; + + GET_BAN_ARG(bantime, autocvar_g_ban_default_bantime); + GET_BAN_ARG(masksize, autocvar_g_ban_default_masksize); + GET_BAN_REASON(reason, "No reason provided"); + + Ban_KickBanClient(client, bantime, masksize, reason); + + return; + } + else + { + print("kickban: ", GetClientErrorString(accepted, argv(1)), ".\n"); + } + } + } + + default: + print("Incorrect parameters for ^2kickban^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd kickban client [bantime] [masksize] [reason]\n"); + print(" 'client' is the entity number or name of the player to ban,\n"); + print(" 'bantime' is the amount of time that the ban is active (default if not provided),\n"); + print(" 'masksize' is the range of the IP address (1-thru-4, default if not provided),\n"); + print(" and 'reason' is the string to label the ban with as reason for banning.\n"); + print("See also: ^2ban, banlist, unban^7\n"); + return; + } + } +} + +void BanCommand_unban(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argv(1)) + { + Ban_Delete(stof(argv(1))); + return; + } + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd unban banid\n"); + print(" Where 'banid' is the ID of the ban of which to remove.\n"); + print("See also: ^2ban, banlist, kickban^7\n"); + return; + } + } +} + +/* use this when creating a new command, making sure to place it in alphabetical order... also, +** ADD ALL NEW COMMANDS TO commands.cfg WITH PROPER ALIASES IN THE SAME FASHION! +void BanCommand_(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd \n"); + print(" No arguments required.\n"); + return; + } + } +} +*/ + + +// ================================== +// Macro system for server commands +// ================================== + +// Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;) +// but for 0.5 compat, we need "bans" here as it was replaced... REMOVE IT AFTER 0.6 RELEASE!!!! +#define BAN_COMMANDS(request,arguments,command) \ + BAN_COMMAND("ban", BanCommand_ban(request, arguments, command), "Ban an IP address or a range of addresses (like 1.2.3)") \ + BAN_COMMAND("banlist", BanCommand_banlist(request), "List all existing bans") \ + BAN_COMMAND("bans", BanCommand_banlist(request), "") \ + BAN_COMMAND("kickban", BanCommand_kickban(request, arguments, command), "Disconnect a client and ban it at the same time") \ + BAN_COMMAND("unban", BanCommand_unban(request, arguments), "Remove an existing ban") \ + /* nothing */ + +void BanCommand_macro_help() +{ + #define BAN_COMMAND(name,function,description) \ + { if(strtolower(description) != "") { print(" ^2", name, "^7: ", description, "\n"); } } + + BAN_COMMANDS(0, 0, "") + #undef BAN_COMMAND + + return; +} + +float BanCommand_macro_command(float argc, string command) +{ + #define BAN_COMMAND(name,function,description) \ + { if(name == strtolower(argv(0))) { function; return TRUE; } } + + BAN_COMMANDS(CMD_REQUEST_COMMAND, argc, command) + #undef BAN_COMMAND + + return FALSE; +} + +float BanCommand_macro_usage(float argc) +{ + #define BAN_COMMAND(name,function,description) \ + { if(name == strtolower(argv(1))) { function; return TRUE; } } + + BAN_COMMANDS(CMD_REQUEST_USAGE, argc, "") + #undef BAN_COMMAND + + return FALSE; +} + +void BanCommand_macro_write_aliases(float fh) +{ + #define BAN_COMMAND(name,function,description) \ + { if(strtolower(description) != "") { CMD_Write_Alias("qc_cmd_sv", name, description); } } + + BAN_COMMANDS(0, 0, "") + #undef BAN_COMMAND + + return; +} + +float BanCommand(string command) +{ + float argc = tokenize_console(command); + + // Guide for working with argc arguments by example: + // argc: 1 - 2 - 3 - 4 + // argv: 0 - 1 - 2 - 3 + // cmd vote - master - login - password + + if(BanCommand_macro_command(argc, command)) // continue as usual and scan for normal commands + { + return TRUE; // handled by one of the above GenericCommand_* functions + } + + return FALSE; +} \ No newline at end of file diff --git a/qcsrc/server/command/banning.qh b/qcsrc/server/command/banning.qh new file mode 100644 index 0000000000..7a6138283f --- /dev/null +++ b/qcsrc/server/command/banning.qh @@ -0,0 +1,15 @@ +// ==================================== +// Declarations for kick/ban commands +// Last updated: December 29th, 2011 +// ===================================== + +#define GET_BAN_ARG(v,d) if((argc > reason_arg) && ((v = stof(argv(reason_arg))) != 0)) ++reason_arg; else v = d +#define GET_BAN_REASON(v,d) if(argc > reason_arg) v = substring(command, argv_start_index(reason_arg), strlen(command) - argv_start_index(reason_arg)); else v = d + +void Ban_KickBanClient(entity client, float bantime, float masksize, string reason); +void Ban_View(); +float Ban_Insert(string ip, float bantime, string reason, float dosync); +float Ban_Delete(float i); + +// used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file +void BanCommand_macro_write_aliases(float fh) \ No newline at end of file diff --git a/qcsrc/server/command/cmd.qc b/qcsrc/server/command/cmd.qc new file mode 100644 index 0000000000..e8a6207314 --- /dev/null +++ b/qcsrc/server/command/cmd.qc @@ -0,0 +1,730 @@ +// ========================================================= +// Server side networked commands code, reworked by Samual +// Last updated: December 28th, 2011 +// ========================================================= + +float SV_ParseClientCommand_floodcheck() +{ + if not(timeout_status) // not while paused + { + if(time <= (self.cmd_floodtime + autocvar_sv_clientcommand_antispam_time)) + { + self.cmd_floodcount += 1; + if(self.cmd_floodcount > autocvar_sv_clientcommand_antispam_count) { return FALSE; } // too much spam, halt + } + else + { + self.cmd_floodtime = time; + self.cmd_floodcount = 1; + } + } + return TRUE; // continue, as we're not flooding yet +} + + +// ======================= +// Command Sub-Functions +// ======================= + +void ClientCommand_autoswitch(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argv(1) != "") + { + self.autoswitch = InterpretBoolean(argv(1)); + sprint(self, strcat("^1autoswitch is currently turned ", (self.autoswitch ? "on" : "off"), ".\n")); + return; + } + } + + default: + sprint(self, "Incorrect parameters for ^2autoswitch^7\n"); + case CMD_REQUEST_USAGE: + { + sprint(self, "\nUsage:^3 cmd autoswitch selection\n"); + sprint(self, " Where 'selection' controls if autoswitch is on or off.\n"); + return; + } + } +} + +void ClientCommand_checkfail(float request, string command) // internal command, used only by code +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + print(sprintf("CHECKFAIL: %s (%s) epically failed check %s\n", self.netname, self.netaddress, substring(command, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)))); + self.checkfail = 1; + return; // never fall through to usage + } + + default: + sprint(self, "Incorrect parameters for ^2checkfail^7\n"); + case CMD_REQUEST_USAGE: + { + sprint(self, "\nUsage:^3 cmd checkfail <message>\n"); + sprint(self, " Where 'message' is the message reported by client about the fail.\n"); + return; + } + } +} + +void ClientCommand_clientversion(float request, float argc) // internal command, used only by code +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argv(1) != "") + { + if(self.flags & FL_CLIENT) + { + self.version = ((argv(1) == "$gameversion") ? 1 : stof(argv(1))); + + if(self.version < autocvar_gameversion_min || self.version > autocvar_gameversion_max) + { + self.version_mismatch = 1; + ClientKill_TeamChange(-2); // observe + } + else if(autocvar_g_campaign || autocvar_g_balance_teams || autocvar_g_balance_teams_force) + { + //JoinBestTeam(self, FALSE, TRUE); + } + else if(teamplay && !autocvar_sv_spectate && !(self.team_forced > 0)) + { + self.classname = "observer"; // really? + stuffcmd(self, "menu_showteamselect\n"); + } + } + + return; + } + } + + default: + sprint(self, "Incorrect parameters for ^2clientversion^7\n"); + case CMD_REQUEST_USAGE: + { + sprint(self, "\nUsage:^3 cmd clientversion version\n"); + sprint(self, " Where 'version' is the game version reported by self.\n"); + return; + } + } +} + +void ClientCommand_mv_getpicture(float request, float argc) // internal command, used only by code +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argv(1) != "") + { + if(intermission_running) + MapVote_SendPicture(stof(argv(1))); + + return; + } + } + + default: + sprint(self, "Incorrect parameters for ^2mv_getpicture^7\n"); + case CMD_REQUEST_USAGE: + { + sprint(self, "\nUsage:^3 cmd mv_getpicture mapid\n"); + sprint(self, " Where 'mapid' is the id number of the map to request an image of on the map vote selection menu.\n"); + return; + } + } +} + +void ClientCommand_join(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(self.flags & FL_CLIENT) + { + if(self.classname != "player" && !lockteams && !g_arena) + { + if(nJoinAllowed(1)) + { + if(g_ca) { self.caplayer = 1; } + if(autocvar_g_campaign) { campaign_bots_may_start = 1; } + + self.classname = "player"; + PlayerScore_Clear(self); + bprint ("^4", self.netname, "^4 is playing now\n"); + PutClientInServer(); + } + else + { + //player may not join because of g_maxplayers is set + centerprint(self, PREVENT_JOIN_TEXT); + } + } + } + return; // never fall through to usage + } + + default: + case CMD_REQUEST_USAGE: + { + sprint(self, "\nUsage:^3 cmd join\n"); + sprint(self, " No arguments required.\n"); + return; + } + } +} + +void ClientCommand_ready(float request) // todo: anti-spam for toggling readyness +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(self.flags & FL_CLIENT) + { + if(inWarmupStage || autocvar_sv_ready_restart || g_race_qualifying == 2) + { + if(!readyrestart_happened || autocvar_sv_ready_restart_repeatable) + { + if (self.ready) // toggle + { + self.ready = FALSE; + bprint(self.netname, "^2 is ^1NOT^2 ready\n"); + } + else + { + self.ready = TRUE; + bprint(self.netname, "^2 is ready\n"); + } + + // cannot reset the game while a timeout is active! + if not(timeout_status) + ReadyCount(); + } else { + sprint(self, "^1Game has already been restarted\n"); + } + } + } + return; // never fall through to usage + } + + default: + case CMD_REQUEST_USAGE: + { + sprint(self, "\nUsage:^3 cmd ready\n"); + sprint(self, " No arguments required.\n"); + return; + } + } +} + +void ClientCommand_reportcvar(float request, float argc, string command) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argv(1) != "") + { + float tokens; + string s; + + if(substring(argv(2), 0, 1) == "$") // undefined cvar: use the default value on the server then + { + s = strcat(substring(command, argv_start_index(0), argv_end_index(1) - argv_start_index(0)), " \"", cvar_defstring(argv(1)), "\""); + tokens = tokenize_console(s); + } + + GetCvars(1); + + return; + } + } + + default: + sprint(self, "Incorrect parameters for ^2reportcvar^7\n"); + case CMD_REQUEST_USAGE: + { + sprint(self, "\nUsage:^3 cmd reportcvar <cvar>\n"); + sprint(self, " Where 'cvar' is the cvar plus arguments to send to the server.\n"); + return; + } + } +} + +void ClientCommand_say(float request, float argc, string command) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argc >= 2) { Say(self, FALSE, world, substring(command, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)), 1); } + return; // never fall through to usage + } + + default: + case CMD_REQUEST_USAGE: + { + sprint(self, "\nUsage:^3 cmd say <message>\n"); + sprint(self, " Where 'message' is the string of text to say.\n"); + return; + } + } +} + +void ClientCommand_say_team(float request, float argc, string command) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argc >= 2) { Say(self, TRUE, world, substring(command, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)), 1); } + return; // never fall through to usage + } + + default: + case CMD_REQUEST_USAGE: + { + sprint(self, "\nUsage:^3 cmd say_team <message>\n"); + sprint(self, " Where 'message' is the string of text to say.\n"); + return; + } + } +} + +void ClientCommand_selectteam(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argv(1) != "") + { + if(self.flags & FL_CLIENT) + { + if(teamplay) + if not(self.team_forced > 0) + if not(lockteams) + { + float selection; + + switch(argv(1)) + { + case "red": selection = COLOR_TEAM1; break; + case "blue": selection = COLOR_TEAM2; break; + case "yellow": selection = COLOR_TEAM3; break; + case "pink": selection = COLOR_TEAM4; break; + case "auto": selection = (-1); break; + + default: break; + } + + if(selection) + { + if(self.team == selection && self.deadflag == DEAD_NO) + sprint(self, "^7You already are on that team.\n"); + else if(self.wasplayer && autocvar_g_changeteam_banned) + sprint(self, "^1You cannot change team, forbidden by the server.\n"); + else + ClientKill_TeamChange(selection); + } + } + else + sprint(self, "^7The game has already begun, you must wait until the next map to be able to join a team.\n"); + else + sprint(self, "^7selectteam can not be used as your team is forced\n"); + else + sprint(self, "^7selectteam can only be used in teamgames\n"); + } + return; + } + } + + default: + sprint(self, "Incorrect parameters for ^2selectteam^7\n"); + case CMD_REQUEST_USAGE: + { + sprint(self, "\nUsage:^3 cmd selectteam team\n"); + sprint(self, " Where 'team' is the prefered team to try and join.\n"); + sprint(self, " Full list of options here: \"red, blue, yellow, pink, auto\"\n"); + return; + } + } +} + +void ClientCommand_selfstuff(float request, string command) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argv(1) != "") + { + stuffcmd(self, substring(command, argv_start_index(1), argv_end_index(-1) - argv_start_index(1))); + return; + } + } + + default: + sprint(self, "Incorrect parameters for ^2selectteam^7\n"); + case CMD_REQUEST_USAGE: + { + sprint(self, "\nUsage:^3 cmd selfstuff <command>\n"); + sprint(self, " Where 'command' is the string to be stuffed to your client.\n"); + return; + } + } +} + +void ClientCommand_sentcvar(float request, float argc, string command) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argv(1) != "") + { + float tokens; + string s; + + if(argc == 2) // undefined cvar: use the default value on the server then + { + s = strcat(substring(command, argv_start_index(0), argv_end_index(1) - argv_start_index(0)), " \"", cvar_defstring(argv(1)), "\""); + tokens = tokenize_console(s); + } + + GetCvars(1); + + return; + } + } + + default: + sprint(self, "Incorrect parameters for ^2sentcvar^7\n"); + case CMD_REQUEST_USAGE: + { + sprint(self, "\nUsage:^3 cmd sentcvar <cvar>\n"); + sprint(self, " Where 'cvar' is the cvar plus arguments to send to the server.\n"); + return; + } + } +} + +void ClientCommand_spectate(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(self.flags & FL_CLIENT) + { + if(g_arena) { return; } + if(g_lms) + { + if(self.lms_spectate_warning) + { + // mark player as spectator + PlayerScore_Add(self, SP_LMS_RANK, 666 - PlayerScore_Add(self, SP_LMS_RANK, 0)); + } + else + { + self.lms_spectate_warning = 1; + sprint(self, "WARNING: you won't be able to enter the game again after spectating in LMS. Use the same command again to spectate anyway.\n"); + return; + } + } + + if(self.classname == "player" && autocvar_sv_spectate == 1) + ClientKill_TeamChange(-2); // observe + + // in CA, allow a dead player to move to spectatators (without that, caplayer!=0 will be moved back to the player list) + // note: if arena game mode is ever done properly, this needs to be removed. + if(g_ca && self.caplayer && (self.classname == "spectator" || self.classname == "observer")) + { + sprint(self, "WARNING: you will spectate in the next round.\n"); + self.caplayer = 0; + } + } + return; // never fall through to usage + } + + default: + case CMD_REQUEST_USAGE: + { + sprint(self, "\nUsage:^3 cmd spectate\n"); + sprint(self, " No arguments required.\n"); + return; + } + } +} + +void ClientCommand_suggestmap(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argv(1) != "") + { + sprint(self, strcat(MapVote_Suggest(argv(1)), "\n")); + return; + } + } + + default: + sprint(self, "Incorrect parameters for ^2suggestmap^7\n"); + case CMD_REQUEST_USAGE: + { + sprint(self, "\nUsage:^3 cmd suggestmap map\n"); + sprint(self, " Where 'map' is the name of the map to suggest.\n"); + return; + } + } +} + +void ClientCommand_tell(float request, float argc, string command) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argc >= 3) + { + entity tell_to = GetIndexedEntity(argc, 1); + float tell_accepted = VerifyClientEntity(tell_to, TRUE, FALSE); + + if(tell_accepted > 0) // the target is a real client + { + if(tell_to != self) // and we're allowed to send to them :D + { + Say(self, FALSE, tell_to, substring(command, argv_start_index(next_token), argv_end_index(-1) - argv_start_index(next_token)), TRUE); + return; + } + else { print_to(self, "You can't ^2tell^7 a message to yourself."); return; } + } + else if(argv(1) == "#0") + { + trigger_magicear_processmessage_forallears(self, -1, world, substring(command, argv_start_index(next_token), argv_end_index(-1) - argv_start_index(next_token))); + return; + } + else { print_to(self, strcat("tell: ", GetClientErrorString(tell_accepted, argv(1)), ".")); return; } + } + } + + default: + sprint(self, "Incorrect parameters for ^2tell^7\n"); + case CMD_REQUEST_USAGE: + { + sprint(self, "\nUsage:^3 cmd tell client <message>\n"); + sprint(self, " Where 'client' is the entity number or name of the player to send 'message' to.\n"); + return; + } + } +} + +void ClientCommand_voice(float request, float argc, string command) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argv(1) != "") + { + if(argc >= 3) + VoiceMessage(argv(1), substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2))); + else + VoiceMessage(argv(1), ""); + + return; + } + } + + default: + sprint(self, "Incorrect parameters for ^2voice^7\n"); + case CMD_REQUEST_USAGE: + { + sprint(self, "\nUsage:^3 cmd voice messagetype <soundname>\n"); + sprint(self, " 'messagetype' is the type of broadcast to do, like team only or such,\n"); + sprint(self, " and 'soundname' is the string/filename of the sound/voice message to play.\n"); + return; + } + } +} + +/* use this when creating a new command, making sure to place it in alphabetical order... also, +** ADD ALL NEW COMMANDS TO commands.cfg WITH PROPER ALIASES IN THE SAME FASHION! +void ClientCommand_(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + + return; // never fall through to usage + } + + default: + case CMD_REQUEST_USAGE: + { + sprint(self, "\nUsage:^3 cmd \n"); + sprint(self, " No arguments required.\n"); + return; + } + } +} +*/ + + +// ===================================== +// Macro system for networked commands +// ===================================== + +// Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;) +#define CLIENT_COMMANDS(request,arguments,command) \ + CLIENT_COMMAND("autoswitch", ClientCommand_autoswitch(request, arguments), "Whether or not to switch automatically when getting a better weapon") \ + CLIENT_COMMAND("checkfail", ClientCommand_checkfail(request, command), "Report if a client-side check failed") \ + CLIENT_COMMAND("clientversion", ClientCommand_clientversion(request, arguments), "Release version of the game") \ + CLIENT_COMMAND("mv_getpicture", ClientCommand_mv_getpicture(request, arguments), "Retrieve mapshot picture from the server") \ + CLIENT_COMMAND("join", ClientCommand_join(request), "Become a player in the game") \ + CLIENT_COMMAND("ready", ClientCommand_ready(request), "Qualify as ready to end warmup stage (or restart server if allowed)") \ + CLIENT_COMMAND("reportcvar", ClientCommand_reportcvar(request, arguments, command), "Old system for sending a client cvar to the server") \ + CLIENT_COMMAND("say", ClientCommand_say(request, arguments, command), "Print a message to chat to all players") \ + CLIENT_COMMAND("say_team", ClientCommand_say_team(request, arguments, command), "Print a message to chat to all team mates") \ + CLIENT_COMMAND("selectteam", ClientCommand_selectteam(request, arguments), "Attempt to choose a team to join into") \ + CLIENT_COMMAND("selfstuff", ClientCommand_selfstuff(request, command), "Stuffcmd a command to your own client") \ + CLIENT_COMMAND("sentcvar", ClientCommand_sentcvar(request, arguments, command), "New system for sending a client cvar to the server") \ + CLIENT_COMMAND("spectate", ClientCommand_spectate(request), "Become an observer") \ + CLIENT_COMMAND("suggestmap", ClientCommand_suggestmap(request, arguments), "Suggest a map to the mapvote at match end") \ + CLIENT_COMMAND("tell", ClientCommand_tell(request, arguments, command), "Send a message directly to a player") \ + CLIENT_COMMAND("voice", ClientCommand_voice(request, arguments, command), "Send voice message via sound") \ + /* nothing */ + +void ClientCommand_macro_help() +{ + #define CLIENT_COMMAND(name,function,description) \ + { sprint(self, " ^2", name, "^7: ", description, "\n"); } + + CLIENT_COMMANDS(0, 0, "") + #undef CLIENT_COMMAND + + return; +} + +float ClientCommand_macro_command(float argc, string command) +{ + #define CLIENT_COMMAND(name,function,description) \ + { if(name == strtolower(argv(0))) { function; return TRUE; } } + + CLIENT_COMMANDS(CMD_REQUEST_COMMAND, argc, command) + #undef CLIENT_COMMAND + + return FALSE; +} + +float ClientCommand_macro_usage(float argc) +{ + #define CLIENT_COMMAND(name,function,description) \ + { if(name == strtolower(argv(1))) { function; return TRUE; } } + + CLIENT_COMMANDS(CMD_REQUEST_USAGE, argc, "") + #undef CLIENT_COMMAND + + return FALSE; +} + +void ClientCommand_macro_write_aliases(float fh) +{ + #define CLIENT_COMMAND(name,function,description) \ + { CMD_Write_Alias("qc_cmd_cmd", name, description); } + + CLIENT_COMMANDS(0, 0, "") + #undef CLIENT_COMMAND + + return; +} + +// ====================================== +// Main Function Called By Engine (cmd) +// ====================================== +// If this function exists, server game code parses clientcommand before the engine code gets it. + +void SV_ParseClientCommand(string command) +{ + float argc = tokenize_console(command); + + // Guide for working with argc arguments by example: + // argc: 1 - 2 - 3 - 4 + // argv: 0 - 1 - 2 - 3 + // cmd vote - master - login - password + + // for floodcheck + switch(strtolower(argv(0))) + { + // exempt commands which are not subject to floodcheck + case "begin": break; // handled by engine in host_cmd.c + case "download": break; // handled by engine in cl_parse.c + case "mv_getpicture": break; // handled by server in this file + case "pause": break; // handled by engine in host_cmd.c + case "prespawn": break; // handled by engine in host_cmd.c + case "reportcvar": break; // handled by server in this file + case "sentcvar": break; // handled by server in this file + case "spawn": break; // handled by engine in host_cmd.c + + default: + if(SV_ParseClientCommand_floodcheck()) + break; // "TRUE": continue, as we're not flooding yet + else + return; // "FALSE": not allowed to continue, halt // print("^1ERROR: ^7ANTISPAM CAUGHT: ", command, ".\n"); + } + + /* NOTE: should this be disabled? It can be spammy perhaps, but hopefully it's okay for now */ + if(argv(0) == "help") + { + if(argc == 1) + { + sprint(self, "\nClient networked commands:\n"); + ClientCommand_macro_help(); + + sprint(self, "\nCommon networked commands:\n"); + CommonCommand_macro_help(self); + + sprint(self, "\nUsage:^3 cmd COMMAND...^7, where possible commands are listed above.\n"); + sprint(self, "For help about a specific command, type cmd help COMMAND\n"); + return; + } + else if(CommonCommand_macro_usage(argc, self)) // Instead of trying to call a command, we're going to see detailed information about it + { + return; + } + else if(ClientCommand_macro_usage(argc)) // same, but for normal commands now + { + return; + } + } + else if(MUTATOR_CALLHOOK(SV_ParseClientCommand)) + { + return; // handled by a mutator + } + else if(CheatCommand(argc)) + { + return; // handled by server/cheats.qc + } + else if(CommonCommand_macro_command(argc, self, command)) + { + return; // handled by server/command/common.qc + } + else if(ClientCommand_macro_command(argc, command)) // continue as usual and scan for normal commands + { + return; // handled by one of the above ClientCommand_* functions + } + else + clientcommand(self, command); +} \ No newline at end of file diff --git a/qcsrc/server/command/cmd.qh b/qcsrc/server/command/cmd.qh new file mode 100644 index 0000000000..e64cbc267a --- /dev/null +++ b/qcsrc/server/command/cmd.qh @@ -0,0 +1,14 @@ +// ================================================= +// Declarations for server side networked commands +// Last updated: December 26th, 2011 +// ================================================= + +.float cmd_floodtime; +.float cmd_floodcount; +.float lms_spectate_warning; +.float checkfail; + +string MapVote_Suggest(string m); + +// used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file +void ClientCommand_macro_write_aliases(float fh); \ No newline at end of file diff --git a/qcsrc/server/command/common.qc b/qcsrc/server/command/common.qc new file mode 100644 index 0000000000..3b71e3d701 --- /dev/null +++ b/qcsrc/server/command/common.qc @@ -0,0 +1,762 @@ +// ==================================================== +// Shared code for server commands, written by Samual +// Last updated: December 27th, 2011 +// ==================================================== + +// select the proper prefix for usage and other messages +string GetCommandPrefix(entity caller) +{ + if(caller) + return "cmd"; + else + return "sv_cmd"; +} + +// if client return player nickname, or if server return admin nickname +string GetCallerName(entity caller) +{ + if(caller) + return caller.netname; + else + return admin_name(); //((autocvar_sv_adminnick != "") ? autocvar_sv_adminnick : autocvar_hostname); +} + +// verify that the client provided is acceptable for use +float VerifyClientEntity(entity client, float must_be_real, float must_be_bots) +{ + if not(client.flags & FL_CLIENT) + return CLIENT_DOESNT_EXIST; + else if(must_be_real && (clienttype(client) != CLIENTTYPE_REAL)) + return CLIENT_NOT_REAL; + else if(must_be_bots && (clienttype(client) != CLIENTTYPE_BOT)) + return CLIENT_NOT_BOT; + + return CLIENT_ACCEPTABLE; +} + +// if the client is not acceptable, return a string to be used for error messages +string GetClientErrorString(float clienterror, string original_input) +{ + switch(clienterror) + { + case CLIENT_DOESNT_EXIST: { return strcat("Client '", original_input, "' doesn't exist"); } + case CLIENT_NOT_REAL: { return strcat("Client '", original_input, "' is not real"); } + case CLIENT_NOT_BOT: { return strcat("Client '", original_input, "' is not a bot"); } + default: { return "Incorrect usage of GetClientErrorString"; } + } +} + +// is this entity number even in the possible range of entities? +float VerifyClientNumber(float tmp_number) +{ + if((tmp_number < 1) || (tmp_number > maxclients)) + return FALSE; + else + return TRUE; +} + +entity GetIndexedEntity(float argc, float start_index) +{ + entity tmp_player, selection; + float tmp_number, index; + string tmp_string; + + next_token = -1; + index = start_index; + + if(argc > start_index) + { + if(substring(argv(index), 0, 1) == "#") + { + tmp_string = substring(argv(index), 1, -1); + ++index; + + if(tmp_string != "") // is it all one token? like #1 + { + tmp_number = stof(tmp_string); + } + else if(argc > index) // no, it's two tokens? # 1 + { + tmp_number = stof(argv(index)); + ++index; + } + } + else // maybe it's ONLY a number? + { + tmp_number = stof(argv(index)); + ++index; + } + + if(VerifyClientNumber(tmp_number)) + { + selection = edict_num(tmp_number); // yes, it was a number + } + else // no, maybe it's a name? + { + FOR_EACH_CLIENT(tmp_player) + if (strdecolorize(tmp_player.netname) == strdecolorize(argv(start_index))) + selection = tmp_player; + + index = (start_index + 1); + } + } + + next_token = index; + print(strcat("start_index: ", ftos(start_index), ", next_token: ", ftos(next_token), ", edict: ", ftos(num_for_edict(selection)), ".\n")); + return selection; +} + +// find a player which matches the input string, and return their entity +entity GetFilteredEntity(string input) +{ + entity tmp_player, selection; + float tmp_number; + + if(substring(input, 0, 1) == "#") + tmp_number = stof(substring(input, 1, -1)); + else + tmp_number = stof(input); + + if(VerifyClientNumber(tmp_number)) + { + selection = edict_num(tmp_number); + } + else + { + FOR_EACH_CLIENT(tmp_player) + if (strdecolorize(tmp_player.netname) == strdecolorize(input)) + selection = tmp_player; + } + + return selection; +} + +// same thing, but instead return their edict number +float GetFilteredNumber(string input) +{ + entity selection = GetFilteredEntity(input); + float output; + + if(selection) { output = num_for_edict(selection); } + + return output; +} + +// switch between sprint and print depending on whether the reciever is the server or a player +void print_to(entity to, string input) +{ + if(to) + sprint(to, strcat(input, "\n")); + else + print(input, "\n"); +} + +// ========================================== +// Supporting functions for common commands +// ========================================== + +// used by CommonCommand_timeout() and CommonCommand_timein() to handle game pausing and messaging and such. +void timeout_handler_reset() +{ + entity tmp_player; + + timeout_caller = world; + timeout_time = 0; + timeout_leadtime = 0; + + FOR_EACH_REALPLAYER(tmp_player) + Send_CSQC_Centerprint_Generic_Expire(tmp_player, CPID_TIMEOUT_COUNTDOWN); + + remove(self); +} + +void timeout_handler_think() +{ + entity tmp_player; + + switch(timeout_status) + { + case TIMEOUT_ACTIVE: + { + if(timeout_time > 0) // countdown is still going + { + FOR_EACH_REALPLAYER(tmp_player) + Send_CSQC_Centerprint_Generic(tmp_player, CPID_TIMEOUT_COUNTDOWN, "Timeout ends in %d seconds!", 1, timeout_time); + + if(timeout_time == autocvar_sv_timeout_resumetime) // play a warning sound when only <sv_timeout_resumetime> seconds are left + Announce("prepareforbattle"); + + self.nextthink = time + TIMEOUT_SLOWMO_VALUE; // think again in one second + timeout_time -= 1; // decrease the time counter + } + else // time to end the timeout + { + timeout_status = TIMEOUT_INACTIVE; + + // reset the slowmo value back to normal + cvar_set("slowmo", ftos(orig_slowmo)); + + // unlock the view for players so they can move around again + FOR_EACH_REALPLAYER(tmp_player) + tmp_player.fixangle = FALSE; + + timeout_handler_reset(); + } + + return; + } + + case TIMEOUT_LEADTIME: + { + if(timeout_leadtime > 0) // countdown is still going + { + // centerprint the information to every player + FOR_EACH_REALPLAYER(tmp_player) + Send_CSQC_Centerprint_Generic(tmp_player, CPID_TIMEOUT_COUNTDOWN, "Timeout begins in %d seconds!", 1, timeout_leadtime); + + self.nextthink = time + 1; // think again in one second + timeout_leadtime -= 1; // decrease the time counter + } + else // time to begin the timeout + { + timeout_status = TIMEOUT_ACTIVE; + + // set the slowmo value to the timeout default slowmo value + cvar_set("slowmo", ftos(TIMEOUT_SLOWMO_VALUE)); + + // reset all the flood variables + FOR_EACH_CLIENT(tmp_player) + tmp_player.nickspamcount = tmp_player.nickspamtime = tmp_player.floodcontrol_chat = + tmp_player.floodcontrol_chatteam = tmp_player.floodcontrol_chattell = + tmp_player.floodcontrol_voice = tmp_player.floodcontrol_voiceteam = 0; + + // copy .v_angle to .lastV_angle for every player in order to fix their view during pause (see PlayerPreThink) + FOR_EACH_REALPLAYER(tmp_player) + tmp_player.lastV_angle = tmp_player.v_angle; + + self.nextthink = time; // think again next frame to handle it under TIMEOUT_ACTIVE code + } + + return; + } + + + case TIMEOUT_INACTIVE: + default: + { + timeout_handler_reset(); + return; + } + } +} + + + +// =================================================== +// Common commands used in both sv_cmd.qc and cmd.qc +// =================================================== + +void CommonCommand_cvar_changes(float request, entity caller) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + print_to(caller, cvar_changes); + return; // never fall through to usage + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " cvar_changes")); + print_to(caller, " No arguments required."); + print_to(caller, "See also: ^2cvar_purechanges^7"); + return; + } + } +} + +void CommonCommand_cvar_purechanges(float request, entity caller) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + print_to(caller, cvar_purechanges); + return; // never fall through to usage + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " cvar_purechanges")); + print_to(caller, " No arguments required."); + print_to(caller, "See also: ^2cvar_changes^7"); + return; + } + } +} + +void CommonCommand_info(float request, entity caller, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + string command = builtin_cvar_string(strcat("sv_info_", argv(1))); + + if(command) + wordwrap_sprint(command, 1000); + else + print_to(caller, "ERROR: unsupported info command"); + + return; // never fall through to usage + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " info request")); + print_to(caller, " Where 'request' is the suffixed string appended onto the request for cvar."); + return; + } + } +} + +void CommonCommand_ladder(float request, entity caller) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + print_to(caller, ladder_reply); + return; // never fall through to usage + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " ladder")); + print_to(caller, " No arguments required."); + return; + } + } +} + +void CommonCommand_lsmaps(float request, entity caller) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + print_to(caller, lsmaps_reply); + return; // never fall through to usage + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " lsmaps")); + print_to(caller, " No arguments required."); + return; + } + } +} + +void CommonCommand_lsnewmaps(float request, entity caller) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + print_to(caller, lsnewmaps_reply); + return; // never fall through to usage + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " lsnewmaps")); + print_to(caller, " No arguments required."); + return; + } + } +} + +void CommonCommand_printmaplist(float request, entity caller) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + print_to(caller, maplist_reply); + return; // never fall through to usage + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " printmaplist")); + print_to(caller, " No arguments required."); + return; + } + } +} + +void CommonCommand_rankings(float request, entity caller) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + print_to(caller, rankings_reply); + return; // never fall through to usage + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " rankings")); + print_to(caller, " No arguments required."); + return; + } + } +} + +void CommonCommand_records(float request, entity caller) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + float i; + + for(i = 0; i < 10; ++i) + if(records_reply[i]) + print_to(caller, records_reply[i]); + + return; // never fall through to usage + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " records")); + print_to(caller, " No arguments required."); + return; + } + } +} + +void CommonCommand_teamstatus(float request, entity caller) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + Score_NicePrint(caller); + return; // never fall through to usage + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " teamstatus")); + print_to(caller, " No arguments required."); + return; + } + } +} + +void CommonCommand_time(float request, entity caller) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + print_to(caller, strcat("time = ", ftos(time))); + print_to(caller, strcat("frame start = ", ftos(gettime(GETTIME_FRAMESTART)))); + print_to(caller, strcat("realtime = ", ftos(gettime(GETTIME_REALTIME)))); + print_to(caller, strcat("hires = ", ftos(gettime(GETTIME_HIRES)))); + print_to(caller, strcat("uptime = ", ftos(gettime(GETTIME_UPTIME)))); + print_to(caller, strcat("localtime = ", strftime(TRUE, "%a %b %e %H:%M:%S %Z %Y"))); + print_to(caller, strcat("gmtime = ", strftime(FALSE, "%a %b %e %H:%M:%S %Z %Y"))); + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " time")); + print_to(caller, " No arguments required."); + return; + } + } +} + +void CommonCommand_timein(float request, entity caller) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(!caller || autocvar_sv_timeout) + { + if not(timeout_status) { print_to(caller, "^7Error: There is no active timeout called."); } + else if(caller && (caller != timeout_caller)) { print_to(caller, "^7Error: You are not allowed to stop the active timeout."); } + + else // everything should be okay, continue aborting timeout + { + switch(timeout_status) + { + case TIMEOUT_LEADTIME: + { + timeout_status = TIMEOUT_INACTIVE; + timeout_time = 0; + timeout_handler.nextthink = time; // timeout_handler has to take care of it immediately + bprint(strcat("^7The timeout was aborted by ", GetCallerName(caller), " !\n")); + return; + } + + case TIMEOUT_ACTIVE: + { + timeout_time = autocvar_sv_timeout_resumetime; + timeout_handler.nextthink = time; // timeout_handler has to take care of it immediately + bprint(strcat("^1Attention: ^7", GetCallerName(caller), " resumed the game! Prepare for battle!\n")); + return; + } + + default: dprint("timeout status was inactive, but this code was executed anyway?"); return; + } + } + } + else { print_to(caller, "^1Timeins are not allowed to be called, enable them with sv_timeout 1.\n"); } + + return; // never fall through to usage + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " timein")); + print_to(caller, " No arguments required."); + return; + } + } +} + +void CommonCommand_timeout(float request, entity caller) // DEAR GOD THIS COMMAND IS TERRIBLE. +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(!caller || autocvar_sv_timeout) + { + float last_possible_timeout = ((autocvar_timelimit * 60) - autocvar_sv_timeout_leadtime - 1); + + if(timeout_status) { print_to(caller, "^7Error: A timeout is already active."); } + else if(vote_called) { print_to(caller, "^7Error: You can not call a timeout while a vote is active."); } + else if(inWarmupStage && !g_warmup_allow_timeout) { print_to(caller, "^7Error: You can not call a timeout in warmup-stage."); } + else if(time < game_starttime) { print_to(caller, "^7Error: You can not call a timeout while the map is being restarted."); } + else if(caller && (caller.allowed_timeouts < 1)) { print_to(caller, "^7Error: You already used all your timeout calls for this map."); } + else if(caller && (caller.classname != "player")) { print_to(caller, "^7Error: You must be a player to call a timeout."); } + else if((autocvar_timelimit) && (last_possible_timeout < time - game_starttime)) { print_to(caller, "^7Error: It is too late to call a timeout now!"); } + + else // everything should be okay, proceed with starting the timeout + { + if(caller) { caller.allowed_timeouts -= 1; } + + bprint(GetCallerName(caller), " ^7called a timeout", (caller ? strcat(" (", ftos(caller.allowed_timeouts), " timeout(s) left)") : string_null), "!\n"); // write a bprint who started the timeout (and how many they have left) + + timeout_status = TIMEOUT_LEADTIME; + timeout_caller = caller; + timeout_time = autocvar_sv_timeout_length; + timeout_leadtime = autocvar_sv_timeout_leadtime; + + timeout_handler = spawn(); + timeout_handler.think = timeout_handler_think; + timeout_handler.nextthink = time; // always let the entity think asap + + Announce("timeoutcalled"); + } + } + else { print_to(caller, "^1Timeouts are not allowed to be called, enable them with sv_timeout 1.\n"); } + + return; // never fall through to usage + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " timeout")); + print_to(caller, " No arguments required."); + return; + } + } +} + +void CommonCommand_who(float request, entity caller, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + float total_listed_players, tmp_hours, tmp_minutes, tmp_seconds, is_bot; + entity tmp_player; + + float privacy = (caller && autocvar_sv_status_privacy); + string separator = strreplace("%", " ", strcat((argv(1) ? argv(1) : " "), "^7")); + string tmp_netaddress, tmp_crypto_idfp; + + print_to(caller, strcat("List of client information", (privacy ? " (some data is hidden for privacy)" : string_null), ":")); + print_to(caller, sprintf(strreplace(" ", separator, " %-4s %-20s %-5s %-3s %-9s %-16s %s "), + "ent", "nickname", "ping", "pl", "time", "ip", "crypto_id")); + + FOR_EACH_CLIENT(tmp_player) + { + is_bot = (clienttype(tmp_player) == CLIENTTYPE_BOT); + + if(is_bot) + { + tmp_netaddress = "null/botclient"; + tmp_crypto_idfp = "null/botclient"; + } + else if(privacy) + { + tmp_netaddress = "hidden"; + tmp_crypto_idfp = "hidden"; + } + else + { + tmp_netaddress = tmp_player.netaddress; + tmp_crypto_idfp = tmp_player.crypto_idfp; + } + + tmp_hours = tmp_minutes = tmp_seconds = 0; + + tmp_seconds = floor(time - tmp_player.jointime); + tmp_minutes = floor(tmp_seconds / 60); + tmp_hours = floor(tmp_minutes / 60); + + if(tmp_minutes) { tmp_seconds -= (tmp_minutes * 60); } + if(tmp_hours) { tmp_minutes -= (tmp_hours * 60); } + + print_to(caller, sprintf(strreplace(" ", separator, " #%-3d %-20.20s %-5d %-3d %-9s %-16s %s "), + num_for_edict(tmp_player), + tmp_player.netname, + tmp_player.ping, + tmp_player.ping_packetloss, + sprintf("%02d:%02d:%02d", tmp_hours, tmp_minutes, tmp_seconds), + tmp_netaddress, + tmp_crypto_idfp)); + + ++total_listed_players; + } + + print_to(caller, strcat("Finished listing ", ftos(total_listed_players), " client(s) out of ", ftos(maxclients), " slots.")); + + return; // never fall through to usage + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " who [separator]")); + print_to(caller, " Where 'separator' is the optional string to separate the values with, default is a space."); + return; + } + } +} + +/* use this when creating a new command, making sure to place it in alphabetical order... also, +** ADD ALL NEW COMMANDS TO commands.cfg WITH PROPER ALIASES IN THE SAME FASHION! +void CommonCommand_(float request, entity caller) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + + return; // never fall through to usage + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " ")); + print_to(caller, " No arguments required."); + return; + } + } +} +*/ + + +// ================================== +// Macro system for common commands +// ================================== + +// Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;) +#define COMMON_COMMANDS(request,caller,arguments,command) \ + COMMON_COMMAND("cvar_changes", CommonCommand_cvar_changes(request, caller), "Prints a list of all changed server cvars") \ + COMMON_COMMAND("cvar_purechanges", CommonCommand_cvar_purechanges(request, caller), "Prints a list of all changed gameplay cvars") \ + COMMON_COMMAND("info", CommonCommand_info(request, caller, arguments), "Request for unique server information set up by admin") \ + COMMON_COMMAND("ladder", CommonCommand_ladder(request, caller), "Get information about top players if supported") \ + COMMON_COMMAND("lsmaps", CommonCommand_lsmaps(request, caller), "List maps which can be used with the current game mode") \ + COMMON_COMMAND("lsnewmaps", CommonCommand_lsnewmaps(request, caller), "List maps which have no records or are seemingly unplayed yet") \ + COMMON_COMMAND("printmaplist", CommonCommand_printmaplist(request, caller), "Display full server maplist reply") \ + COMMON_COMMAND("rankings", CommonCommand_rankings(request, caller), "Print information about rankings") \ + COMMON_COMMAND("records", CommonCommand_records(request, caller), "List top 10 records for the current map") \ + COMMON_COMMAND("teamstatus", CommonCommand_teamstatus(request, caller), "Show information about player and team scores") \ + COMMON_COMMAND("time", CommonCommand_time(request, caller), "Print different formats/readouts of time") \ + COMMON_COMMAND("timein", CommonCommand_timein(request, caller), "Resume the game from being paused with a timeout") \ + COMMON_COMMAND("timeout", CommonCommand_timeout(request, caller), "Call a timeout which pauses the game for certain amount of time unless unpaused") \ + COMMON_COMMAND("vote", VoteCommand(request, caller, arguments, command), "Request an action to be voted upon by players") \ + COMMON_COMMAND("who", CommonCommand_who(request, caller, arguments), "Display detailed client information about all players") \ + /* nothing */ + +void CommonCommand_macro_help(entity caller) +{ + #define COMMON_COMMAND(name,function,description) \ + { print_to(caller, strcat(" ^2", name, "^7: ", description)); } + + COMMON_COMMANDS(0, caller, 0, "") + #undef COMMON_COMMAND + + return; +} + +float CommonCommand_macro_command(float argc, entity caller, string command) +{ + #define COMMON_COMMAND(name,function,description) \ + { if(name == strtolower(argv(0))) { function; return TRUE; } } + + COMMON_COMMANDS(CMD_REQUEST_COMMAND, caller, argc, command) + #undef COMMON_COMMAND + + return FALSE; +} + +float CommonCommand_macro_usage(float argc, entity caller) +{ + #define COMMON_COMMAND(name,function,description) \ + { if(name == strtolower(argv(1))) { function; return TRUE; } } + + COMMON_COMMANDS(CMD_REQUEST_USAGE, caller, argc, "") + #undef COMMON_COMMAND + + return FALSE; +} + +void CommonCommand_macro_write_aliases(float fh) +{ + #define COMMON_COMMAND(name,function,description) \ + { CMD_Write_Alias("qc_cmd_svcmd", name, description); } + + COMMON_COMMANDS(0, world, 0, "") + #undef COMMON_COMMAND + + return; +} \ No newline at end of file diff --git a/qcsrc/server/command/common.qh b/qcsrc/server/command/common.qh new file mode 100644 index 0000000000..589388bbad --- /dev/null +++ b/qcsrc/server/command/common.qh @@ -0,0 +1,38 @@ +// ============================================================ +// Shared declarations for server commands, written by Samual +// Last updated: December 30th, 2011 +// ============================================================ + +// client verification results +#define CLIENT_ACCEPTABLE 1 +#define CLIENT_DOESNT_EXIST -1 +#define CLIENT_NOT_REAL -2 +#define CLIENT_NOT_BOT -3 + +// definitions for timeouts +#define TIMEOUT_INACTIVE 0 +#define TIMEOUT_LEADTIME 1 +#define TIMEOUT_ACTIVE 2 + +// timeout which pauses the game by setting the slowmo value extremely low. +#define TIMEOUT_SLOWMO_VALUE 0.0001 + +// global timeout information declarations +entity timeout_caller; // contains the entity of the player who started the last timeout +entity timeout_handler; // responsible for centerprinting the timeout countdowns and playing sounds +float sys_frametime; // gets initialised in worldspawn, saves the value from autocvar_sys_ticrate +float orig_slowmo; // contains the value of autocvar_slowmo so that, after timeout finished, it isn't set to slowmo 1 necessarily +float timeout_time; // contains the time in seconds that the active timeout has left +float timeout_leadtime; // contains the number of seconds left of the leadtime (before the timeout starts) +float timeout_status; // (values: 0, 1, 2) contains whether a timeout is not active (0), was called but still at leadtime (1) or is active (2) +.float allowed_timeouts; // contains the number of allowed timeouts for each player +.vector lastV_angle; //used when pausing the game in order to force the player to keep his old view angle fixed + +// allow functions to be used in other code like g_world.qc and teamplay.qc +void timeout_handler_think(); + +// used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file +void CommonCommand_macro_write_aliases(float fh); + +// keep track of the next token to use for argc +float next_token; \ No newline at end of file diff --git a/qcsrc/server/command/getreplies.qc b/qcsrc/server/command/getreplies.qc new file mode 100644 index 0000000000..29b707b93d --- /dev/null +++ b/qcsrc/server/command/getreplies.qc @@ -0,0 +1,284 @@ +// ========================================================= +// Reply messages for common commands, re-worked by Samual +// Last updated: December 30th, 2011 +// ========================================================= + +// These strings are set usually during init in g_world.qc, +// or also by some game modes or other functions manually, +// and their purpose is to output information to clients +// without using any extra processing time. + +// See common.qc for their proper commands + +string getrecords(float page) // 50 records per page +{ + float rec, r, i; + string h, s; + + if (g_ctf) + { + for (i = page * 200; i < MapInfo_count && i < page * 200 + 200; ++i) + { + if (MapInfo_Get_ByID(i)) + { + r = stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, "/captimerecord/time"))); + + if (r == 0) + continue; + + // TODO: uid2name + h = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, "/captimerecord/netname")); + s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-6, ftos_decimals(r, 2)), " ", h, "\n"); + ++rec; + } + } + } + + if (g_race) + { + for (i = page * 200; i < MapInfo_count && i < page * 200 + 200; ++i) + { + if (MapInfo_Get_ByID(i)) + { + r = race_readTime(MapInfo_Map_bspname, 1); + + if (r == 0) + continue; + + h = race_readName(MapInfo_Map_bspname, 1); + s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-8, TIME_ENCODED_TOSTRING(r)), " ", h, "\n"); + ++rec; + } + } + } + + if (g_cts) + { + for (i = page * 200; i < MapInfo_count && i < page * 200 + 200; ++i) + { + if (MapInfo_Get_ByID(i)) + { + r = race_readTime(MapInfo_Map_bspname, 1); + + if (r == 0) + continue; + + h = race_readName(MapInfo_Map_bspname, 1); + s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-8, TIME_ENCODED_TOSTRING(r)), " ", h, "\n"); + ++rec; + } + } + } + + MapInfo_ClearTemps(); + + if (s == "" && page == 0) + return "No records are available on this server.\n"; + else + return s; +} + +string getrankings() +{ + float t, i; + string n, s, p, map; + + map = GetMapname(); + + for (i = 1; i <= RANKINGS_CNT; ++i) + { + t = race_readTime(map, i); + + if (t == 0) + continue; + + n = race_readName(map, i); + p = race_placeName(i); + s = strcat(s, strpad(8, p), " ", strpad(-8, TIME_ENCODED_TOSTRING(t)), " ", n, "\n"); + } + + MapInfo_ClearTemps(); + + if (s == "") + return strcat("No records are available for the map: ", map, "\n"); + else + return strcat("Records for ", map, ":\n", s); +} + +string getladder() +{ + float i, j, k, uidcnt, thiscnt; + string s, temp_s, rr, myuid, thisuid; + + if(g_cts) + rr = CTS_RECORD; + else + rr = RACE_RECORD; + + for(k = 0; k < MapInfo_count; ++k) + { + if(MapInfo_Get_ByID(k)) + { + for(i = 0; i <= LADDER_CNT; ++i) // i = 0 because it is the speed award + { + if(i == 0) // speed award + { + if(stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, rr, "speed/speed"))) == 0) + continue; + + myuid = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, rr, "speed/crypto_idfp")); + } + else // normal record, if it exists (else break) + { + if(race_readTime(MapInfo_Map_bspname, i) == 0) + continue; + + myuid = race_readUID(MapInfo_Map_bspname, i); + } + + // string s contains: + // arg 0 = # of speed recs + // arg 1 = # of 1st place recs + // arg 2 = # of 2nd place recs + // ... etc + // LADDER_CNT+1 = total points + + temp_s = db_get(TemporaryDB, strcat("ladder", myuid)); + + if(temp_s == "") + { + db_put(TemporaryDB, strcat("uid", ftos(uidcnt)), myuid); + ++uidcnt; + + for(j = 0; j <= LADDER_CNT + 1; ++j) + { + if(j != LADDER_CNT + 1) + temp_s = strcat(temp_s, "0 "); + else + temp_s = strcat(temp_s, "0"); + } + } + + tokenize_console(temp_s); + s = ""; + + if(i == 0) // speed award + { + for(j = 0; j <= LADDER_CNT; ++j) // loop over each arg in the string + { + if(j == 0) // speed award + s = strcat(s, ftos(stof(argv(j)) +1)); // add 1 to speed rec count and write + else + s = strcat(s, " ", argv(j)); // just copy over everything else + } + } + else // record + { + for(j = 0; j <= LADDER_CNT; ++j) // loop over each arg in the string + { + if(j == 0) + s = strcat(s, argv(j)); // speed award, dont prefix with " " + else if(j == i) // wanted rec! + s = strcat(s, " ", ftos(stof(argv(j)) +1)); // update argv(j) + else + s = strcat(s, " ", argv(j)); // just copy over everything else + } + } + + // total points are (by default) calculated like this: + // speedrec = floor(100 / 10) = 10 points + // 1st place = floor(100 / 1) = 100 points + // 2nd place = floor(100 / 2) = 50 points + // 3rd place = floor(100 / 3) = 33 points + // 4th place = floor(100 / 4) = 25 points + // 5th place = floor(100 / 5) = 20 points + // ... etc + + if(i == 0) + s = strcat(s, " ", ftos(stof(argv(LADDER_CNT+1)) + LADDER_FIRSTPOINT / 10)); // speed award, add LADDER_FIRSTPOINT / 10 points + else + s = strcat(s, " ", ftos(stof(argv(LADDER_CNT+1)) + floor(LADDER_FIRSTPOINT / i))); // record, add LADDER_FIRSTPOINT / i points + + db_put(TemporaryDB, strcat("ladder", myuid), s); + } + } + } + + for(i = 0; i <= uidcnt; ++i) // for each known uid + { + thisuid = db_get(TemporaryDB, strcat("uid", ftos(i))); + temp_s = db_get(TemporaryDB, strcat("ladder", thisuid)); + tokenize_console(temp_s); + thiscnt = stof(argv(LADDER_CNT+1)); + + if(thiscnt > top_scores[LADDER_SIZE-1]) + { + for(j = 0; j < LADDER_SIZE; ++j) // for each place in ladder + { + if(thiscnt > top_scores[j]) + { + for(k = LADDER_SIZE-1; k >= j; --k) + { + top_uids[k] = top_uids[k-1]; + top_scores[k] = top_scores[k-1]; + } + + top_uids[j] = thisuid; + top_scores[j] = thiscnt; + break; + } + } + } + } + + s = "^3-----------------------\n\n"; + + s = strcat(s, "Pos ^3|"); + s = strcat(s, " ^7Total ^3|"); + + for(i = 1; i <= LADDER_CNT; ++i) + { s = strcat(s, " ^7", race_placeName(i), " ^3|"); } + + s = strcat(s, " ^7Speed awards ^3| ^7Name"); + s = strcat(s, "\n^3----+--------"); + + for(i = 1; i <= min(9, LADDER_CNT); ++i) + { s = strcat(s, "+-----"); } + + #if LADDER_CNT > 9 + for(i = 1; i <= LADDER_CNT - 9; ++i) + { s = strcat(s, "+------"); } + #endif + + s = strcat(s, "+--------------+--------------------\n"); + + for(i = 0; i < LADDER_SIZE; ++i) + { + temp_s = db_get(TemporaryDB, strcat("ladder", top_uids[i])); + tokenize_console(temp_s); + + if(argv(LADDER_CNT+1) == "") // total is 0, skip + continue; + + s = strcat(s, strpad(4, race_placeName(i+1)), "^3| ^7"); // pos + s = strcat(s, strpad(7, argv(LADDER_CNT+1)), "^3| ^7"); // total + + for(j = 1; j <= min(9, LADDER_CNT); ++j) + { s = strcat(s, strpad(4, argv(j)), "^3| ^7"); } // 1st, 2nd, 3rd etc cnt + + #if LADDER_CNT > 9 + for(j = 10; j <= LADDER_CNT; ++j) + { s = strcat(s, strpad(4, argv(j)), " ^3| ^7"); } // 1st, 2nd, 3rd etc cnt + #endif + + s = strcat(s, strpad(13, argv(0)), "^3| ^7"); // speed award cnt + s = strcat(s, uid2name(top_uids[i]), "\n"); // name + } + + MapInfo_ClearTemps(); + + if(s == "") + return "No ladder on this server!\n"; + else + return strcat("Top ", ftos(LADDER_SIZE), " ladder rankings:\n", s); +} \ No newline at end of file diff --git a/qcsrc/server/command/getreplies.qh b/qcsrc/server/command/getreplies.qh new file mode 100644 index 0000000000..af941a79d2 --- /dev/null +++ b/qcsrc/server/command/getreplies.qh @@ -0,0 +1,17 @@ +// ====================================================== +// Declarations for reply messages, re-worked by Samual +// Last updated: December 30th, 2011 +// ====================================================== + +// ladder bullshit todo +#define LADDER_FIRSTPOINT 100 +#define LADDER_CNT 10 // position X still gives LADDER_FIRSTPOINT/X points +#define LADDER_SIZE 30 // ladder shows the top X players + +string top_uids[LADDER_SIZE]; +float top_scores[LADDER_SIZE]; + +// allow functions to be used in other code like g_world.qc and race.qc +string getrecords(float page); +string getrankings(void); +string getladder(void); \ No newline at end of file diff --git a/qcsrc/server/command/radarmap.qc b/qcsrc/server/command/radarmap.qc new file mode 100644 index 0000000000..16f3212eda --- /dev/null +++ b/qcsrc/server/command/radarmap.qc @@ -0,0 +1,427 @@ +// =============================================== +// Generates radar map images for use in the HUD +// =============================================== + +float FullTraceFraction(vector a, vector mi, vector ma, vector b) +{ + vector c; + float white, black; + + white = 0.001; + black = 0.001; + + c = a; + + float n, m; + n = m = 0; + + while(vlen(c - b) > 1) + { + ++m; + + tracebox(c, mi, ma, b, MOVE_WORLDONLY, world); + ++n; + + if(!trace_startsolid) + { + black += vlen(trace_endpos - c); + c = trace_endpos; + } + + n += tracebox_inverted(c, mi, ma, b, MOVE_WORLDONLY, world); + + white += vlen(trace_endpos - c); + c = trace_endpos; + } + + if(n > 200) + dprint("HOLY SHIT! FullTraceFraction: ", ftos(n), " total traces, ", ftos(m), " iterations\n"); + + return white / (black + white); +} +float RadarMapAtPoint_Trace(float x, float y, float w, float h, float zmin, float zsize, float q) +{ + vector a, b, mi, ma; + + mi = '0 0 0'; + ma = '1 0 0' * w + '0 1 0' * h; + a = '1 0 0' * x + '0 1 0' * y + '0 0 1' * zmin; + b = '1 0 0' * x + '0 1 0' * y + '0 0 1' * (zsize + zmin); + + return FullTraceFraction(a, mi, ma, b); +} +float RadarMapAtPoint_LineBlock(float x, float y, float w, float h, float zmin, float zsize, float q) +{ + vector o, mi, ma; + float i, r; + vector dz; + + q = 256 * q - 1; + // 256q-1 is the ideal sample count to map equal amount of sample values to one pixel value + + mi = '0 0 0'; + dz = (zsize / q) * '0 0 1'; + ma = '1 0 0' * w + '0 1 0' * h + dz; + o = '1 0 0' * x + '0 1 0' * y + '0 0 1' * zmin; + + if(x < world.absmin_x - w) + return 0; + if(y < world.absmin_y - h) + return 0; + if(x > world.absmax_x) + return 0; + if(y > world.absmax_y) + return 0; + + r = 0; + for(i = 0; i < q; ++i) + { + vector v1, v2; + v1 = v2 = o + dz * i + mi; + v1_x += random() * (ma_x - mi_x); + v1_y += random() * (ma_y - mi_y); + v1_z += random() * (ma_z - mi_z); + v2_x += random() * (ma_x - mi_x); + v2_y += random() * (ma_y - mi_y); + v2_z += random() * (ma_z - mi_z); + traceline(v1, v2, MOVE_WORLDONLY, world); + if(trace_startsolid || trace_fraction < 1) + ++r; + } + return r / q; +} +float RadarMapAtPoint_Block(float x, float y, float w, float h, float zmin, float zsize, float q) +{ + vector o, mi, ma; + float i, r; + vector dz; + + q = 256 * q - 1; + // 256q-1 is the ideal sample count to map equal amount of sample values to one pixel value + + mi = '0 0 0'; + dz = (zsize / q) * '0 0 1'; + ma = '1 0 0' * w + '0 1 0' * h + dz; + o = '1 0 0' * x + '0 1 0' * y + '0 0 1' * zmin; + + if(x < world.absmin_x - w) + return 0; + if(y < world.absmin_y - h) + return 0; + if(x > world.absmax_x) + return 0; + if(y > world.absmax_y) + return 0; + + r = 0; + for(i = 0; i < q; ++i) + { + tracebox(o + dz * i, mi, ma, o + dz * i, MOVE_WORLDONLY, world); + if(trace_startsolid) + ++r; + } + return r / q; +} +float RadarMapAtPoint_Sample(float x, float y, float w, float h, float zmin, float zsize, float q) +{ + vector a, b, mi, ma; + + q *= 4; // choose q so it matches the regular algorithm in speed + + q = 256 * q - 1; + // 256q-1 is the ideal sample count to map equal amount of sample values to one pixel value + + mi = '0 0 0'; + ma = '1 0 0' * w + '0 1 0' * h; + a = '1 0 0' * x + '0 1 0' * y + '0 0 1' * zmin; + b = '1 0 0' * w + '0 1 0' * h + '0 0 1' * zsize; + + float c, i; + c = 0; + + for(i = 0; i < q; ++i) + { + vector v; + v_x = a_x + random() * b_x; + v_y = a_y + random() * b_y; + v_z = a_z + random() * b_z; + traceline(v, v, MOVE_WORLDONLY, world); + if(trace_startsolid) + ++c; + } + + return c / q; +} +void sharpen_set(float x, float v) +{ + sharpen_buffer[x + 2 * RADAR_WIDTH_MAX] = v; +} +float sharpen_getpixel(float x, float y) +{ + if(x < 0) + return 0; + if(x >= RADAR_WIDTH_MAX) + return 0; + if(y < 0) + return 0; + if(y > 2) + return 0; + return sharpen_buffer[x + y * RADAR_WIDTH_MAX]; +} +float sharpen_get(float x, float a) +{ + float sum; + sum = sharpen_getpixel(x, 1); + if(a == 0) + return sum; + sum *= (8 + 1/a); + sum -= sharpen_getpixel(x - 1, 0); + sum -= sharpen_getpixel(x - 1, 1); + sum -= sharpen_getpixel(x - 1, 2); + sum -= sharpen_getpixel(x + 1, 0); + sum -= sharpen_getpixel(x + 1, 1); + sum -= sharpen_getpixel(x + 1, 2); + sum -= sharpen_getpixel(x, 0); + sum -= sharpen_getpixel(x, 2); + return bound(0, sum * a, 1); +} +void sharpen_shift(float w) +{ + float i; + for(i = 0; i < w; ++i) + { + sharpen_buffer[i] = sharpen_buffer[i + RADAR_WIDTH_MAX]; + sharpen_buffer[i + RADAR_WIDTH_MAX] = sharpen_buffer[i + 2 * RADAR_WIDTH_MAX]; + sharpen_buffer[i + 2 * RADAR_WIDTH_MAX] = 0; + } +} +void sharpen_init(float w) +{ + float i; + for(i = 0; i < w; ++i) + { + sharpen_buffer[i] = 0; + sharpen_buffer[i + RADAR_WIDTH_MAX] = 0; + sharpen_buffer[i + 2 * RADAR_WIDTH_MAX] = 0; + } +} +void RadarMap_Next() +{ + if(radarmapper.count & 4) + { + localcmd("quit\n"); + } + else if(radarmapper.count & 2) + { + localcmd(strcat("defer 1 \"sv_cmd radarmap --flags ", ftos(radarmapper.count), strcat(" --res ", ftos(radarmapper.size_x), " ", ftos(radarmapper.size_y), " --sharpen ", ftos(radarmapper.ltime), " --qual ", ftos(radarmapper.size_z)), "\"\n")); + GotoNextMap(0); + } + remove(radarmapper); + radarmapper = world; +} +void RadarMap_Think() +{ + // rough map entity + // cnt: current line + // size: pixel width/height + // maxs: cell width/height + // frame: counter + + float i, x, l; + string si; + + if(self.frame == 0) + { + // initialize + get_mi_min_max_texcoords(1); + self.mins = mi_picmin; + self.maxs_x = (mi_picmax_x - mi_picmin_x) / self.size_x; + self.maxs_y = (mi_picmax_y - mi_picmin_y) / self.size_y; + self.maxs_z = mi_max_z - mi_min_z; + print("Picture mins/maxs: ", ftos(self.maxs_x), " and ", ftos(self.maxs_y), " should match\n"); + self.netname = strzone(strcat("gfx/", mi_shortname, "_radar.xpm")); + if(!(self.count & 1)) + { + self.cnt = fopen(self.netname, FILE_READ); + if(self.cnt < 0) + self.cnt = fopen(strcat("gfx/", mi_shortname, "_radar.tga"), FILE_READ); + if(self.cnt < 0) + self.cnt = fopen(strcat("gfx/", mi_shortname, "_radar.png"), FILE_READ); + if(self.cnt < 0) + self.cnt = fopen(strcat("gfx/", mi_shortname, "_radar.jpg"), FILE_READ); + if(self.cnt < 0) + self.cnt = fopen(strcat("gfx/", mi_shortname, "_mini.tga"), FILE_READ); + if(self.cnt < 0) + self.cnt = fopen(strcat("gfx/", mi_shortname, "_mini.png"), FILE_READ); + if(self.cnt < 0) + self.cnt = fopen(strcat("gfx/", mi_shortname, "_mini.jpg"), FILE_READ); + if(self.cnt >= 0) + { + fclose(self.cnt); + + print(self.netname, " already exists, aborting (you may want to specify --force)\n"); + RadarMap_Next(); + return; + } + } + self.cnt = fopen(self.netname, FILE_WRITE); + if(self.cnt < 0) + { + print("Error writing ", self.netname, "\n"); + remove(self); + radarmapper = world; + return; + } + print("Writing to ", self.netname, "...\n"); + fputs(self.cnt, "/* XPM */\n"); + fputs(self.cnt, "static char *RadarMap[] = {\n"); + fputs(self.cnt, "/* columns rows colors chars-per-pixel */\n"); + fputs(self.cnt, strcat("\"", ftos(self.size_x), " ", ftos(self.size_y), " 256 2\",\n")); + for(i = 0; i < 256; ++i) + { + si = substring(doublehex, i*2, 2); + fputs(self.cnt, strcat("\"", si, " c #", si, si, si, "\",\n")); + } + self.frame += 1; + self.nextthink = time; + sharpen_init(self.size_x); + } + else if(self.frame <= self.size_y) + { + // fill the sharpen buffer with this line + sharpen_shift(self.size_x); + i = self.count & 24; + + switch(i) + { + case 0: + default: + for(x = 0; x < self.size_x; ++x) + { + l = RadarMapAtPoint_Block(self.mins_x + x * self.maxs_x, self.mins_y + (self.size_y - self.frame) * self.maxs_y, self.maxs_x, self.maxs_y, self.mins_z, self.maxs_z, self.size_z); + sharpen_set(x, l); + } + break; + case 8: + for(x = 0; x < self.size_x; ++x) + { + l = RadarMapAtPoint_Trace(self.mins_x + x * self.maxs_x, self.mins_y + (self.size_y - self.frame) * self.maxs_y, self.maxs_x, self.maxs_y, self.mins_z, self.maxs_z, self.size_z); + sharpen_set(x, l); + } + break; + case 16: + for(x = 0; x < self.size_x; ++x) + { + l = RadarMapAtPoint_Sample(self.mins_x + x * self.maxs_x, self.mins_y + (self.size_y - self.frame) * self.maxs_y, self.maxs_x, self.maxs_y, self.mins_z, self.maxs_z, self.size_z); + sharpen_set(x, l); + } + break; + case 24: + for(x = 0; x < self.size_x; ++x) + { + l = RadarMapAtPoint_LineBlock(self.mins_x + x * self.maxs_x, self.mins_y + (self.size_y - self.frame) * self.maxs_y, self.maxs_x, self.maxs_y, self.mins_z, self.maxs_z, self.size_z); + sharpen_set(x, l); + } + break; + } + + // do we have enough lines? + if(self.frame >= 2) + { + // write a pixel line + fputs(self.cnt, "\""); + for(x = 0; x < self.size_x; ++x) + { + l = sharpen_get(x, self.ltime); + fputs(self.cnt, substring(doublehex, 2 * floor(l * 256.0), 2)); + } + if(self.frame == self.size_y) + fputs(self.cnt, "\"\n"); + else + { + fputs(self.cnt, "\",\n"); + print(ftos(self.size_y - self.frame), " lines left\n"); + } + } + + // is this the last line? then write back the missing line + if(self.frame == self.size_y) + { + sharpen_shift(self.size_x); + // write a pixel line + fputs(self.cnt, "\""); + for(x = 0; x < self.size_x; ++x) + { + l = sharpen_get(x, self.ltime); + fputs(self.cnt, substring(doublehex, 2 * floor(l * 256.0), 2)); + } + if(self.frame == self.size_y) + fputs(self.cnt, "\"\n"); + else + { + fputs(self.cnt, "\",\n"); + print(ftos(self.size_y - self.frame), " lines left\n"); + } + } + + self.frame += 1; + self.nextthink = time; + } + else + { + // close the file + fputs(self.cnt, "};\n"); + fclose(self.cnt); + print("Finished. Please edit data/", self.netname, " with an image editing application and place it in the TGA format in the gfx folder.\n"); + RadarMap_Next(); + } +} + +float RadarMap_Make(float argc) +{ + float i; + + if(!radarmapper) + { + radarmapper = spawn(); + radarmapper.classname = "radarmapper"; + radarmapper.think = RadarMap_Think; + radarmapper.nextthink = time; + radarmapper.count = 8; // default to the --trace method, as it is faster now + radarmapper.ltime = 1; + radarmapper.size = '512 512 1'; + for(i = 1; i < argc; ++i) + { + switch(argv(i)) + { + case "--force": { radarmapper.count |= 1; break; } + case "--loop": { radarmapper.count |= 2; break; } + case "--quit": { radarmapper.count |= 4; break; } + case "--block": { radarmapper.count &~= 24; break; } + case "--trace": { radarmapper.count &~= 24; radarmapper.count |= 8; break; } + case "--sample": { radarmapper.count &~= 24; radarmapper.count |= 16; break; } + case "--lineblock": { radarmapper.count |= 24; break; } + case "--flags": { ++i; radarmapper.count = stof(argv(i)); break; } // for the recursive call + case "--sharpen": { ++i; radarmapper.ltime = stof(argv(i)); break; } // for the recursive call + case "--res": // minor alias + case "--resolution": { ++i; radarmapper.size_x = stof(argv(i)); ++i; radarmapper.size_y = stof(argv(i)); break; } + case "--qual": // minor alias + case "--quality": { ++i; radarmapper.size_z = stof(argv(i)); break; } + + default: + i = argc; + remove(radarmapper); + radarmapper = world; + break; + } + } + + if(radarmapper) // after doing the arguments, see if we successfully went forward. + { + print("Radarmap entity spawned.\n"); + return TRUE; // if so, don't print usage. + } + } + + return FALSE; +} \ No newline at end of file diff --git a/qcsrc/server/command/radarmap.qh b/qcsrc/server/command/radarmap.qh new file mode 100644 index 0000000000..b92d8466f3 --- /dev/null +++ b/qcsrc/server/command/radarmap.qh @@ -0,0 +1,13 @@ +// =========================================== +// Declarations for radarmap generation code +// =========================================== + +entity radarmapper; + +float RADAR_WIDTH_MAX = 512; +float RADAR_HEIGHT_MAX = 512; +float sharpen_buffer[RADAR_WIDTH_MAX * 3]; + +string doublehex = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFFFF"; +// FF is contained twice, to map 256 to FF too +// removes the need to bound() diff --git a/qcsrc/server/command/sv_cmd.qc b/qcsrc/server/command/sv_cmd.qc new file mode 100644 index 0000000000..98d877c436 --- /dev/null +++ b/qcsrc/server/command/sv_cmd.qc @@ -0,0 +1,1806 @@ +// ===================================================== +// Server side game commands code, reworked by Samual +// Last updated: December 29th, 2011 +// ===================================================== + +// used by GameCommand_make_mapinfo() +void make_mapinfo_Think() +{ + if(MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, 0, 1)) + { + print("Done rebuiling mapinfos.\n"); + MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0); + remove(self); + } + else + { + self.think = make_mapinfo_Think; + self.nextthink = time; + } +} + +// used by GameCommand_extendmatchtime() and GameCommand_reducematchtime() +void changematchtime(float delta, float mi, float ma) +{ + float cur; + float new; + float lim; + + if(delta == 0) + return; + if(autocvar_timelimit < 0) + return; + + if(mi <= 10) + mi = 10; // at least ten sec in the future + cur = time - game_starttime; + if(cur > 0) + mi += cur; // from current time! + + lim = autocvar_timelimit * 60; + + if(delta > 0) + { + if(lim == 0) + return; // cannot increase any further + else if(lim < ma) + new = min(ma, lim + delta); + else // already above maximum: FAIL + return; + } + else + { + if(lim == 0) // infinite: try reducing to max, if we are allowed to + new = max(mi, ma); + else if(lim > mi) // above minimum: decrease + new = max(mi, lim + delta); + else // already below minimum: FAIL + return; + } + + cvar_set("timelimit", ftos(new / 60)); +} + + +// ======================= +// Command Sub-Functions +// ======================= + +void GameCommand_adminmsg(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + entity client; + float accepted; + + string targets = strreplace(",", " ", argv(1)); + string original_targets = strreplace(" ", ", ", targets); + string admin_message = argv(2); + float infobartime = stof(argv(3)); + + string successful, t; + + if((targets) && (admin_message)) + { + for(;targets;) + { + t = car(targets); targets = cdr(targets); + + // Check to see if the player is a valid target + client = GetFilteredEntity(t); + accepted = VerifyClientEntity(client, TRUE, FALSE); + + if not(accepted > 0) + { + print("adminmsg: ", GetClientErrorString(accepted, t), (targets ? ", skipping to next player.\n" : ".\n")); + continue; + } + + // send the centerprint/console print or infomessage + if(infobartime) + { + stuffcmd(client, sprintf("\ninfobar %f \"%s\"\n", infobartime, MakeConsoleSafe(admin_message))); + } + else + { + centerprint(client, strcat("^3", admin_name(), ":\n^7", admin_message)); + sprint(client, strcat("\{1}\{13}^3", admin_name(), "^7: ", admin_message, "\n")); + } + + successful = strcat(successful, (successful ? ", " : ""), client.netname); + dprint("Message sent to ", client.netname, "\n"); + continue; + } + + if(successful) + bprint("Successfully sent message '", admin_message, "' to ", successful, ".\n"); + else + print("No players given (", original_targets, ") could recieve the message.\n"); + + return; + } + } + + default: + print("Incorrect parameters for ^2adminmsg^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd adminmsg clients \"message\" [infobartime]\n"); + print(" 'clients' is a list (separated by commas) of player entity ID's or nicknames\n"); + print(" If infobartime is provided, the message will be sent to infobar.\n"); + print(" Otherwise, it will just be sent as a centerprint message.\n"); + print("Examples: adminmsg 2,4 \"this infomessage will last for ten seconds\" 10\n"); + print(" adminmsg 2,5 \"this message will be a centerprint\"\n"); + return; + } + } +} + +void GameCommand_allready(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + ReadyRestart(); + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd allready\n"); + print(" No arguments required.\n"); + return; + } + } +} + +void GameCommand_allspec(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + entity client; + string reason = argv(1); + float i; + + FOR_EACH_REALPLAYER(client) + { + self = client; + PutObserverInServer(); + ++i; + } + if(i) { bprint(strcat("Successfully forced all (", ftos(i), ") players to spectate", (reason ? strcat(" for reason: '", reason, "'") : ""), ".\n")); } + else { print("No players found to spectate.\n"); } + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd allspec [reason]\n"); + print(" Where 'reason' is an optional argument for explanation of allspec command.\n"); + print("See also: ^2moveplayer, shuffleteams^7\n"); + return; + } + } +} + +void GameCommand_anticheat(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + entity client = GetIndexedEntity(argc, 1); + float accepted = VerifyClientEntity(client, FALSE, FALSE); + + if(accepted > 0) + { + self = client; + anticheat_report(); + return; + } + else + { + print("anticheat: ", GetClientErrorString(accepted, argv(1)), ".\n"); + } + } + + default: + print("Incorrect parameters for ^2anticheat^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd anticheat client\n"); + print(" 'client' is the entity number or name of the player.\n"); + return; + } + } +} + +void GameCommand_bbox(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + print("Original size: ", ftos(world.absmin_x), " ", ftos(world.absmin_y), " ", ftos(world.absmin_z)); + print(" ", ftos(world.absmax_x), " ", ftos(world.absmax_y), " ", ftos(world.absmax_z), "\n"); + print("Currently set size: ", ftos(world.mins_x), " ", ftos(world.mins_y), " ", ftos(world.mins_z)); + print(" ", ftos(world.maxs_x), " ", ftos(world.maxs_y), " ", ftos(world.maxs_z), "\n"); + print("Solid bounding box size:"); + + tracebox('1 0 0' * world.absmin_x, + '0 1 0' * world.absmin_y + '0 0 1' * world.absmin_z, + '0 1 0' * world.absmax_y + '0 0 1' * world.absmax_z, + '1 0 0' * world.absmax_x, + MOVE_WORLDONLY, + world); + if(trace_startsolid) + print(" ", ftos(world.absmin_x)); + else + print(" ", ftos(trace_endpos_x)); + + tracebox('0 1 0' * world.absmin_y, + '1 0 0' * world.absmin_x + '0 0 1' * world.absmin_z, + '1 0 0' * world.absmax_x + '0 0 1' * world.absmax_z, + '0 1 0' * world.absmax_y, + MOVE_WORLDONLY, + world); + if(trace_startsolid) + print(" ", ftos(world.absmin_y)); + else + print(" ", ftos(trace_endpos_y)); + + tracebox('0 0 1' * world.absmin_z, + '1 0 0' * world.absmin_x + '0 1 0' * world.absmin_y, + '1 0 0' * world.absmax_x + '0 1 0' * world.absmax_y, + '0 0 1' * world.absmax_z, + MOVE_WORLDONLY, + world); + if(trace_startsolid) + print(" ", ftos(world.absmin_z)); + else + print(" ", ftos(trace_endpos_z)); + + tracebox('1 0 0' * world.absmax_x, + '0 1 0' * world.absmin_y + '0 0 1' * world.absmin_z, + '0 1 0' * world.absmax_y + '0 0 1' * world.absmax_z, + '1 0 0' * world.absmin_x, + MOVE_WORLDONLY, + world); + if(trace_startsolid) + print(" ", ftos(world.absmax_x)); + else + print(" ", ftos(trace_endpos_x)); + + tracebox('0 1 0' * world.absmax_y, + '1 0 0' * world.absmin_x + '0 0 1' * world.absmin_z, + '1 0 0' * world.absmax_x + '0 0 1' * world.absmax_z, + '0 1 0' * world.absmin_y, + MOVE_WORLDONLY, + world); + if(trace_startsolid) + print(" ", ftos(world.absmax_y)); + else + print(" ", ftos(trace_endpos_y)); + + tracebox('0 0 1' * world.absmax_z, + '1 0 0' * world.absmin_x + '0 1 0' * world.absmin_y, + '1 0 0' * world.absmax_x + '0 1 0' * world.absmax_y, + '0 0 1' * world.absmin_z, + MOVE_WORLDONLY, + world); + if(trace_startsolid) + print(" ", ftos(world.absmax_z)); + else + print(" ", ftos(trace_endpos_z)); + + print("\n"); + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd bbox\n"); + print(" No arguments required.\n"); + print("See also: ^2gettaginfo, trace^7\n"); + return; + } + } +} + +void GameCommand_bot_cmd(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + entity bot; + + if(argv(1) == "reset") + { + bot_resetqueues(); + return; + } + else if(argv(1) == "load" && argc == 3) + { + float fh, i; + string s; + fh = fopen(argv(2), FILE_READ); + if(fh < 0) + { + print("cannot open the file\n"); + return; + } + + i = 0; + while((s = fgets(fh))) + { + argc = tokenize_console(s); + + if(argc >= 3 && argv(0) == "sv_cmd" && argv(1) == "bot_cmd") + { + if(argv(2) == "reset") + { + bot_resetqueues(); + } + else if(argv(2) == "setbots") + { + cvar_settemp("minplayers", "0"); + cvar_settemp("bot_number", argv(3)); + if(!bot_fixcount()) + print("Sorry, could not set requested bot count\n"); + } + else + { + // let's start at token 2 so we can skip sv_cmd bot_cmd + bot = find_bot_by_number(stof(argv(2))); + if(bot == world) + bot = find_bot_by_name(argv(2)); + if(bot) + bot_queuecommand(bot, strcat(argv(3), " ", argv(4))); + } + } + else + localcmd(strcat(s, "\n")); + + ++i; + } + print(ftos(i), " commands read\n"); + fclose(fh); + return; + } + else if(argv(1) == "help") + { + if(argv(2)) + bot_cmdhelp(argv(2)); + else + bot_list_commands(); + return; + } + else if(argc >= 3) // this comes last + { + bot = find_bot_by_number(stof(argv(1))); + if(bot == world) + bot = find_bot_by_name(argv(1)); + if(bot) + { + print(strcat("Command '", strcat(argv(2), " ", argv(3)), "' sent to bot ", bot.netname, "\n")); + bot_queuecommand(bot, strcat(argv(2), " ", argv(3))); + return; + } + else + print(strcat("Error: Can't find bot with the name or id '", argv(1),"' - Did you mistype the command?\n")); // don't return so that usage is shown + } + } + + default: + print("Incorrect parameters for ^2bot_cmd^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd bot_cmd client command [argument]\n"); + print(" 'client' can be either the name or entity id of the bot\n"); + print(" For full list of commands, see bot_cmd help [command].\n"); + print("Examples: sv_cmd bot_cmd client cc \"say something\"\n"); + print(" sv_cmd bot_cmd client presskey jump\n"); + return; + } + } +} + +void GameCommand_cointoss(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + entity client; + string result1 = (argv(2) ? strcat("^7", argv(1), "^3!\n") : "^1HEADS^3!\n"); + string result2 = (argv(2) ? strcat("^7", argv(2), "^3!\n") : "^4TAILS^3!\n"); + string choice = ((random() > 0.5) ? result1 : result2); + + FOR_EACH_CLIENT(client) + centerprint(client, strcat("^3Throwing coin... Result: ", choice)); + bprint(strcat("^3Throwing coin... Result: ", choice)); + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd cointoss [result1 result2]\n"); + print(" Where 'result1' and 'result2' are user created options.\n"); + return; + } + } +} + +void GameCommand_database(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argc == 3) + { + if(argv(1) == "save") + { + db_save(ServerProgsDB, argv(2)); + print(strcat("Copied serverprogs database to '", argv(2), "' in the data directory.\n")); + return; + } + else if(argv(1) == "dump") + { + db_dump(ServerProgsDB, argv(2)); + print("DB dumped.\n"); // wtf does this do? + return; + } + else if(argv(1) == "load") + { + db_close(ServerProgsDB); + ServerProgsDB = db_load(argv(2)); + print(strcat("Loaded '", argv(2), "' as new serverprogs database.\n")); + return; + } + } + } + + default: + print("Incorrect parameters for ^2database^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd database action filename\n"); + print(" Where 'action' is the command to complete,\n"); + print(" and 'filename' is what it acts upon.\n"); + print(" Full list of commands here: \"save, dump, load.\"\n"); + return; + } + } +} + +void GameCommand_defer_clear(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + entity client; + float accepted; + + if(argc >= 2) + { + client = GetIndexedEntity(argc, 1); + accepted = VerifyClientEntity(client, TRUE, FALSE); + + if(accepted > 0) + { + stuffcmd(client, "defer clear\n"); + print("defer clear stuffed to ", client.netname, "\n"); + } + else { print("defer_clear: ", GetClientErrorString(accepted, argv(1)), ".\n"); } + + return; + } + } + + default: + print("Incorrect parameters for ^2defer_clear^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd defer_clear client\n"); + print(" 'client' is the entity number or name of the player.\n"); + print("See also: ^2defer_clear_all^7\n"); + return; + } + } +} + +void GameCommand_defer_clear_all(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + entity client; + float i; + float argc; + + FOR_EACH_CLIENT(client) + { + argc = tokenize_console(strcat("defer_clear ", ftos(num_for_edict(client)))); + GameCommand_defer_clear(CMD_REQUEST_COMMAND, argc); + ++i; + } + if(i) { print(strcat("Successfully stuffed defer clear to all clients (", ftos(i), ")\n")); } // should a message be added if no players were found? + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd defer_clear_all\n"); + print(" No arguments required.\n"); + print("See also: ^2defer_clear^7\n"); + return; + } + } +} + +void GameCommand_delrec(float request, float argc) // perhaps merge later with records and printstats and such? +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argv(1)) + { + if(argv(2)) + race_deleteTime(argv(2), stof(argv(1))); + else + race_deleteTime(GetMapname(), stof(argv(1))); + return; + } + } + + default: + print("Incorrect parameters for ^2delrec^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd delrec ranking [map]\n"); + print(" 'ranking' is which ranking level to clear up to, \n"); + print(" it will clear all records up to nth place.\n"); + print(" if 'map' is not provided it will use current map.\n"); + return; + } + } +} + +void GameCommand_effectindexdump(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + float fh, d; + string s; + + d = db_create(); + print("begin of effects list\n"); + db_put(d, "TE_GUNSHOT", "1"); print("effect TE_GUNSHOT is ", ftos(particleeffectnum("TE_GUNSHOT")), "\n"); + db_put(d, "TE_GUNSHOTQUAD", "1"); print("effect TE_GUNSHOTQUAD is ", ftos(particleeffectnum("TE_GUNSHOTQUAD")), "\n"); + db_put(d, "TE_SPIKE", "1"); print("effect TE_SPIKE is ", ftos(particleeffectnum("TE_SPIKE")), "\n"); + db_put(d, "TE_SPIKEQUAD", "1"); print("effect TE_SPIKEQUAD is ", ftos(particleeffectnum("TE_SPIKEQUAD")), "\n"); + db_put(d, "TE_SUPERSPIKE", "1"); print("effect TE_SUPERSPIKE is ", ftos(particleeffectnum("TE_SUPERSPIKE")), "\n"); + db_put(d, "TE_SUPERSPIKEQUAD", "1"); print("effect TE_SUPERSPIKEQUAD is ", ftos(particleeffectnum("TE_SUPERSPIKEQUAD")), "\n"); + db_put(d, "TE_WIZSPIKE", "1"); print("effect TE_WIZSPIKE is ", ftos(particleeffectnum("TE_WIZSPIKE")), "\n"); + db_put(d, "TE_KNIGHTSPIKE", "1"); print("effect TE_KNIGHTSPIKE is ", ftos(particleeffectnum("TE_KNIGHTSPIKE")), "\n"); + db_put(d, "TE_EXPLOSION", "1"); print("effect TE_EXPLOSION is ", ftos(particleeffectnum("TE_EXPLOSION")), "\n"); + db_put(d, "TE_EXPLOSIONQUAD", "1"); print("effect TE_EXPLOSIONQUAD is ", ftos(particleeffectnum("TE_EXPLOSIONQUAD")), "\n"); + db_put(d, "TE_TAREXPLOSION", "1"); print("effect TE_TAREXPLOSION is ", ftos(particleeffectnum("TE_TAREXPLOSION")), "\n"); + db_put(d, "TE_TELEPORT", "1"); print("effect TE_TELEPORT is ", ftos(particleeffectnum("TE_TELEPORT")), "\n"); + db_put(d, "TE_LAVASPLASH", "1"); print("effect TE_LAVASPLASH is ", ftos(particleeffectnum("TE_LAVASPLASH")), "\n"); + db_put(d, "TE_SMALLFLASH", "1"); print("effect TE_SMALLFLASH is ", ftos(particleeffectnum("TE_SMALLFLASH")), "\n"); + db_put(d, "TE_FLAMEJET", "1"); print("effect TE_FLAMEJET is ", ftos(particleeffectnum("TE_FLAMEJET")), "\n"); + db_put(d, "EF_FLAME", "1"); print("effect EF_FLAME is ", ftos(particleeffectnum("EF_FLAME")), "\n"); + db_put(d, "TE_BLOOD", "1"); print("effect TE_BLOOD is ", ftos(particleeffectnum("TE_BLOOD")), "\n"); + db_put(d, "TE_SPARK", "1"); print("effect TE_SPARK is ", ftos(particleeffectnum("TE_SPARK")), "\n"); + db_put(d, "TE_PLASMABURN", "1"); print("effect TE_PLASMABURN is ", ftos(particleeffectnum("TE_PLASMABURN")), "\n"); + db_put(d, "TE_TEI_G3", "1"); print("effect TE_TEI_G3 is ", ftos(particleeffectnum("TE_TEI_G3")), "\n"); + db_put(d, "TE_TEI_SMOKE", "1"); print("effect TE_TEI_SMOKE is ", ftos(particleeffectnum("TE_TEI_SMOKE")), "\n"); + db_put(d, "TE_TEI_BIGEXPLOSION", "1"); print("effect TE_TEI_BIGEXPLOSION is ", ftos(particleeffectnum("TE_TEI_BIGEXPLOSION")), "\n"); + db_put(d, "TE_TEI_PLASMAHIT", "1"); print("effect TE_TEI_PLASMAHIT is ", ftos(particleeffectnum("TE_TEI_PLASMAHIT")), "\n"); + db_put(d, "EF_STARDUST", "1"); print("effect EF_STARDUST is ", ftos(particleeffectnum("EF_STARDUST")), "\n"); + db_put(d, "TR_ROCKET", "1"); print("effect TR_ROCKET is ", ftos(particleeffectnum("TR_ROCKET")), "\n"); + db_put(d, "TR_GRENADE", "1"); print("effect TR_GRENADE is ", ftos(particleeffectnum("TR_GRENADE")), "\n"); + db_put(d, "TR_BLOOD", "1"); print("effect TR_BLOOD is ", ftos(particleeffectnum("TR_BLOOD")), "\n"); + db_put(d, "TR_WIZSPIKE", "1"); print("effect TR_WIZSPIKE is ", ftos(particleeffectnum("TR_WIZSPIKE")), "\n"); + db_put(d, "TR_SLIGHTBLOOD", "1"); print("effect TR_SLIGHTBLOOD is ", ftos(particleeffectnum("TR_SLIGHTBLOOD")), "\n"); + db_put(d, "TR_KNIGHTSPIKE", "1"); print("effect TR_KNIGHTSPIKE is ", ftos(particleeffectnum("TR_KNIGHTSPIKE")), "\n"); + db_put(d, "TR_VORESPIKE", "1"); print("effect TR_VORESPIKE is ", ftos(particleeffectnum("TR_VORESPIKE")), "\n"); + db_put(d, "TR_NEHAHRASMOKE", "1"); print("effect TR_NEHAHRASMOKE is ", ftos(particleeffectnum("TR_NEHAHRASMOKE")), "\n"); + db_put(d, "TR_NEXUIZPLASMA", "1"); print("effect TR_NEXUIZPLASMA is ", ftos(particleeffectnum("TR_NEXUIZPLASMA")), "\n"); + db_put(d, "TR_GLOWTRAIL", "1"); print("effect TR_GLOWTRAIL is ", ftos(particleeffectnum("TR_GLOWTRAIL")), "\n"); + db_put(d, "TR_SEEKER", "1"); print("effect TR_SEEKER is ", ftos(particleeffectnum("TR_SEEKER")), "\n"); + db_put(d, "SVC_PARTICLE", "1"); print("effect SVC_PARTICLE is ", ftos(particleeffectnum("SVC_PARTICLE")), "\n"); + + fh = fopen("effectinfo.txt", FILE_READ); + while((s = fgets(fh))) + { + tokenize_console(s); + if(argv(0) == "effect") + { + if(db_get(d, argv(1)) != "1") + { + if(particleeffectnum(argv(1)) >= 0) + print("effect ", argv(1), " is ", ftos(particleeffectnum(argv(1))), "\n"); + db_put(d, argv(1), "1"); + } + } + } + print("end of effects list\n"); + + db_close(d); + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd effectindexdump\n"); + print(" No arguments required.\n"); + return; + } + } +} + +void GameCommand_extendmatchtime(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + changematchtime(autocvar_timelimit_increment * 60, autocvar_timelimit_min * 60, autocvar_timelimit_max * 60); + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd extendmatchtime\n"); + print(" No arguments required.\n"); + print("See also: ^2reducematchtime^7\n"); + return; + } + } +} + +void GameCommand_find(float request, float argc) // is this even needed? We have prvm_edicts command and such ANYWAY +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + entity client; + + for(client = world; (client = find(client, classname, argv(1))); ) + print(etos(client), "\n"); + + return; + } + + default: + print("Incorrect parameters for ^2find^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd find classname\n"); + print(" Where 'classname' is the classname to search for.\n"); + return; + } + } +} + +void GameCommand_gametype(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argv(1) != "") + { + string s = argv(1); + float t = MapInfo_Type_FromString(s), tsave = MapInfo_CurrentGametype(); + + if(t) + { + MapInfo_SwitchGameType(t); + MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0); + if(MapInfo_count > 0) + bprint("Game type successfully switched to ", s, "\n"); + else + { + bprint("Cannot use this game type: no map for it found\n"); + MapInfo_SwitchGameType(tsave); + MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0); + } + } + else + bprint("Game type switch to ", s, " failed: this type does not exist!\n"); + + return; + } + } + + default: + print("Incorrect parameters for ^2gametype^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd gametype mode\n"); + print(" Where 'mode' is the gametype mode to switch to.\n"); + print("See also: ^2gotomap^7\n"); + return; + } + } +} + +void GameCommand_gettaginfo(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + entity tmp_entity; + float i; + vector v; + + if(argc >= 4) + { + tmp_entity = spawn(); + if(argv(1) == "w") + setmodel(tmp_entity, (nextent(world)).weaponentity.model); + else + { + precache_model(argv(1)); + setmodel(tmp_entity, argv(1)); + } + tmp_entity.frame = stof(argv(2)); + if(substring(argv(3), 0, 1) == "#") + i = stof(substring(argv(3), 1, -1)); + else + i = gettagindex(tmp_entity, argv(3)); + if(i) + { + v = gettaginfo(tmp_entity, i); + print("model ", tmp_entity.model, " frame ", ftos(tmp_entity.frame), " tag ", gettaginfo_name); + print(" index ", ftos(i), " parent ", ftos(gettaginfo_parent), "\n"); + print(" vector = ", ftos(v_x), " ", ftos(v_y), " ", ftos(v_z), "\n"); + print(" offset = ", ftos(gettaginfo_offset_x), " ", ftos(gettaginfo_offset_y), " ", ftos(gettaginfo_offset_z), "\n"); + print(" forward = ", ftos(gettaginfo_forward_x), " ", ftos(gettaginfo_forward_y), " ", ftos(gettaginfo_forward_z), "\n"); + print(" right = ", ftos(gettaginfo_right_x), " ", ftos(gettaginfo_right_y), " ", ftos(gettaginfo_right_z), "\n"); + print(" up = ", ftos(gettaginfo_up_x), " ", ftos(gettaginfo_up_y), " ", ftos(gettaginfo_up_z), "\n"); + if(argc >= 6) + { + v_y = -v_y; + localcmd(strcat(argv(4), vtos(v), argv(5), "\n")); + } + } + else + print("bone not found\n"); + + remove(tmp_entity); + return; + } + } + + default: + print("Incorrect parameters for ^2gettaginfo^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd gettaginfo model frame index [command one] [command two]\n"); + print("See also: ^2bbox, trace^7\n"); + return; + } + } +} + +void GameCommand_gotomap(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argv(1)) + { + print(GotoMap(argv(1)), "\n"); + return; + } + } + + default: + print("Incorrect parameters for ^2gotomap^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd gotomap map\n"); + print(" Where 'map' is the *.bsp file to change to.\n"); + print("See also: ^2gametype^7\n"); + return; + } + } +} + +void GameCommand_lockteams(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(teamplay) + { + lockteams = 1; + bprint("^1The teams are now locked.\n"); + } + else + { + bprint("lockteams command can only be used in a team-based gamemode.\n"); + } + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd lockteams\n"); + print(" No arguments required.\n"); + print("See also: ^2unlockteams^7\n"); + return; + } + } +} + +void GameCommand_make_mapinfo(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + entity tmp_entity; + + tmp_entity = spawn(); + tmp_entity.classname = "make_mapinfo"; + tmp_entity.think = make_mapinfo_Think; + tmp_entity.nextthink = time; + MapInfo_Enumerate(); + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd make_mapinfo\n"); + print(" No arguments required.\n"); + print("See also: ^2radarmap^7\n"); + return; + } + } +} + +void GameCommand_moveplayer(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + float accepted; + entity client; + + string targets = strreplace(",", " ", argv(1)); + string original_targets = strreplace(" ", ", ", targets); + string destination = argv(2); + string notify = argv(3); + + string successful, t; + + // lets see if the target(s) even actually exist. + if((targets) && (destination)) + { + for(;targets;) + { + t = car(targets); targets = cdr(targets); + + // Check to see if the player is a valid target + client = GetFilteredEntity(t); + accepted = VerifyClientEntity(client, FALSE, FALSE); + + if not(accepted > 0) + { + print("moveplayer: ", GetClientErrorString(accepted, t), (targets ? ", skipping to next player.\n" : ".\n")); + continue; + } + + // Where are we putting this player? + if(destination == "spec" || destination == "spectator") + { + if(client.classname != "spectator" && client.classname != "observer") + { + self = client; + PutObserverInServer(); + + successful = strcat(successful, (successful ? ", " : ""), client.netname); + } + else + { + print("Player ", ftos(GetFilteredNumber(t)), " (", client.netname, ") is already spectating.\n"); + } + continue; + } + else + { + if(client.classname != "spectator" && client.classname != "observer") + { + if(teamplay) + { + // set up + float team_color; + float save = client.team_forced; + client.team_forced = 0; + + // find the team to move the player to + team_color = ColourToNumber(destination); + if(team_color == client.team) // already on the destination team + { + // keep the forcing undone + print("Player ", ftos(GetFilteredNumber(t)), " (", client.netname, ") is already on the ", ColoredTeamName(client.team), (targets ? ", skipping to next player.\n" : ".\n")); + continue; + } + else if(team_color == 0) // auto team + { + team_color = NumberToTeamNumber(FindSmallestTeam(client, FALSE)); + } + else + { + CheckAllowedTeams(client); + } + client.team_forced = save; + + // Check to see if the destination team is even available + switch(team_color) + { + case COLOR_TEAM1: if(c1 == -1) { print("Sorry, can't move player to red team if it doesn't exist.\n"); return; } break; + case COLOR_TEAM2: if(c2 == -1) { print("Sorry, can't move player to blue team if it doesn't exist.\n"); return; } break; + case COLOR_TEAM3: if(c3 == -1) { print("Sorry, can't move player to yellow team if it doesn't exist.\n"); return; } break; + case COLOR_TEAM4: if(c4 == -1) { print("Sorry, can't move player to pink team if it doesn't exist.\n"); return; } break; + + default: print("Sorry, can't move player here if team ", destination, " doesn't exist.\n"); return; + } + + // If so, lets continue and finally move the player + client.team_forced = 0; + MoveToTeam(client, team_color, 6, stof(notify)); + successful = strcat(successful, (successful ? ", " : ""), client.netname); + print("Player ", ftos(GetFilteredNumber(t)), " (", client.netname, ") has been moved to the ", ColoredTeamName(team_color), ".\n"); + continue; + } + else + { + print("Can't change teams when currently not playing a team game.\n"); + return; + } + } + else + { + print("Can't change teams if the player isn't in the game.\n"); // well technically we could, but should we allow that? :P + return; + } + } + } + + if(successful) + bprint("Successfully moved players ", successful, " to destination ", destination, ".\n"); + else + print("No players given (", original_targets, ") are able to move.\n"); + + return; // still correct parameters so return to avoid usage print + } + } + + default: + print("Incorrect parameters for ^2moveplayer^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd moveplayer clients destination [notify]\n"); + print(" 'clients' is a list (separated by commas) of player entity ID's or nicknames\n"); + print(" 'destination' is what to send the player to, be it team or spectating\n"); + print(" Full list of destinations here: \"spec, spectator, red, blue, yellow, pink, auto.\"\n"); + print(" 'notify' is whether or not to send messages notifying of the move. Detail below.\n"); + print(" 0 (00) automove centerprint, admin message; 1 (01) automove centerprint, no admin message\n"); + print(" 2 (10) no centerprint, admin message; 3 (11) no centerprint, no admin message\n"); + print("Examples: sv_cmd moveplayer 1,3,5 red 3\n"); + print(" sv_cmd moveplayer 2 spec \n"); + print("See also: ^2allspec, shuffleteams^7\n"); + return; + } + } +} + +void GameCommand_nospectators(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + blockSpectators = 1; + entity plr; + FOR_EACH_CLIENT(plr) //give every spectator <g_maxplayers_spectator_blocktime> seconds time to become a player + { + if(plr.classname == "spectator" || plr.classname == "observer") + { + plr.spectatortime = time; + sprint(plr, strcat("^7You have to become a player within the next ", ftos(autocvar_g_maxplayers_spectator_blocktime), " seconds, otherwise you will be kicked, because spectators aren't allowed at this time!\n")); + } + } + bprint(strcat("^7All spectators will be automatically kicked when not joining the game after ", ftos(autocvar_g_maxplayers_spectator_blocktime), " seconds!\n")); + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd nospectators\n"); + print(" No arguments required.\n"); + return; + } + } +} + +void GameCommand_playerdemo(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argv(2) && argv(3)) + { + entity client; + float i, n, accepted; + + switch(argv(1)) + { + case "read": + { + client = GetIndexedEntity(argc, 2); + accepted = VerifyClientEntity(client, FALSE, TRUE); + + if not(accepted > 0) + { + print("playerdemo: read: ", GetClientErrorString(accepted, argv(2)), ".\n"); + return; + } + + self = client; + playerdemo_open_read(argv(next_token)); + return; + } + + case "write": + { + client = GetIndexedEntity(argc, 2); + accepted = VerifyClientEntity(client, FALSE, FALSE); + + if not(accepted > 0) + { + print("playerdemo: write: ", GetClientErrorString(accepted, argv(2)), ".\n"); + return; + } + + self = client; + playerdemo_open_write(argv(next_token)); + return; + } + + case "auto_read_and_write": + { + n = GetFilteredNumber(argv(3)); + cvar_set("bot_number", ftos(n)); + + localcmd("wait; wait; wait\n"); + for(i = 0; i < n; ++i) { localcmd("sv_cmd playerdemo read ", ftos(i+2), " ", argv(2), ftos(i+1), "\n"); } + + localcmd("sv_cmd playerdemo write 1 ", ftos(n+1), "\n"); + return; + } + + case "auto_read": + { + n = GetFilteredNumber(argv(3)); + cvar_set("bot_number", ftos(n)); + + localcmd("wait; wait; wait\n"); + for(i = 0; i < n; ++i) { localcmd("sv_cmd playerdemo read ", ftos(i+2), " ", argv(2), ftos(i+1), "\n"); } + return; + } + } + } + } + + default: + print("Incorrect parameters for ^2playerdemo^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd playerdemo command (entitynumber filename | entitynumber botnumber)\n"); + print(" Full list of commands here: \"read, write, auto_read_and_write, auto_read.\"\n"); + return; + } + } +} + +void GameCommand_printstats(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + DumpStats(FALSE); + print("stats dumped.\n"); + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd printstats\n"); + print(" No arguments required.\n"); + return; + } + } +} + +void GameCommand_radarmap(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(RadarMap_Make(argc)) + return; + } + + default: + print("Incorrect parameters for ^2radarmap^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd radarmap [--force] [--loop] [--quit] [--block | --trace | --sample | --lineblock] [--sharpen N] [--res W H] [--qual Q]\n"); + print(" The quality factor Q is roughly proportional to the time taken.\n"); + print(" trace supports no quality factor; its result should look like --block with infinite quality factor.\n"); + print("See also: ^2make_mapinfo^7\n"); + return; + } + } +} + +void GameCommand_reducematchtime(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + changematchtime(autocvar_timelimit_decrement *-60, autocvar_timelimit_min * 60, autocvar_timelimit_max * 60); + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd reducematchtime\n"); + print(" No arguments required.\n"); + print("See also: ^2extendmatchtime^7\n"); + return; + } + } +} + +void GameCommand_setbots(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argc >= 2) + { + cvar_settemp("minplayers", "0"); + cvar_settemp("bot_number", argv(1)); + bot_fixcount(); + return; + } + } + + default: + print("Incorrect parameters for ^2setbots^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd setbots botnumber\n"); + print(" Where 'botnumber' is the amount of bots to set bot_number cvar to.\n"); + print("See also: ^2bot_cmd^7\n"); + return; + } + } +} + +void GameCommand_shuffleteams(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(teamplay) + { + entity tmp_player, client; + float i, x, z, t_teams, t_players, team_color, accepted; + + // count the total amount of players and total amount of teams + FOR_EACH_PLAYER(tmp_player) + { + CheckAllowedTeams(tmp_player); + + if(c1 >= 0) t_teams = max(1, t_teams); + if(c2 >= 0) t_teams = max(2, t_teams); + if(c3 >= 0) t_teams = max(3, t_teams); + if(c4 >= 0) t_teams = max(4, t_teams); + + ++t_players; + } + + // build a list of the players in a random order + FOR_EACH_PLAYER(tmp_player) + { + for(;;) + { + i = bound(1, floor(random() * maxclients) + 1, maxclients); + + if(shuffleteams_players[i]) + { + continue; // a player is already assigned to this slot + } + else + { + shuffleteams_players[i] = num_for_edict(tmp_player); + break; + } + } + } + + // finally, from the list made earlier, re-join the players in different order. + for(i = 1; i <= t_teams; ++i) + { + // find out how many players to assign to this team + x = (t_players / t_teams); + x = ((i == 1) ? ceil(x) : floor(x)); + + team_color = NumberToTeamNumber(i); + + // sort through the random list of players made earlier + for(z = 1; z <= maxclients; ++z) + { + if not(shuffleteams_teams[i] >= x) + { + if not(shuffleteams_players[z]) + continue; // not a player, move on to next random slot + + if(VerifyClientNumber(shuffleteams_players[z])) + self = edict_num(shuffleteams_players[z]); + + if(self.team != team_color) + MoveToTeam(self, team_color, 6, 0); + + shuffleteams_players[z] = 0; + shuffleteams_teams[i] = shuffleteams_teams[i] + 1; + } + else + { + break; // move on to next team + } + } + } + + bprint("Successfully shuffled the players around randomly.\n"); + + // clear the buffers now + for (i=0; i<SHUFFLETEAMS_MAX_PLAYERS; ++i) + shuffleteams_players[i] = 0; + + for (i=0; i<SHUFFLETEAMS_MAX_TEAMS; ++i) + shuffleteams_teams[i] = 0; + } + else + { + print("Can't shuffle teams when currently not playing a team game.\n"); + } + + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd shuffleteams\n"); + print(" No arguments required.\n"); + print("See also: ^2moveplayer, allspec^7\n"); + return; + } + } +} + +void GameCommand_stuffto(float request, float argc) +{ + // This... is a fairly dangerous and powerful command... - It allows any arguments to be sent to a client via rcon. + // Because of this, it is disabled by default and must be enabled by the server owner when doing compilation. That way, + // we can be certain they understand the risks of it... So to enable, compile server with -DSTUFFTO_ENABLED argument. + + #ifdef STUFFTO_ENABLED + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(argv(2)) + { + entity client = GetIndexedEntity(argc, 1)); + float accepted = VerifyClientEntity(client, TRUE, FALSE); + + if(accepted > 0) + { + stuffcmd(client, strcat("\n", argv(next_token), "\n")); + print(strcat("Command: \"", argv(next_token), "\" sent to ", GetCallerName(client), " (", argv(1) ,").\n")); + } + else + print("stuffto: ", GetClientErrorString(accepted, argv(1)), ".\n"); + + return; + } + } + + default: + print("Incorrect parameters for ^2stuffto^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd stuffto client \"command\"\n"); + print(" 'client' is the entity number or name of the player,\n"); + print(" and 'command' is the command to be sent to that player.\n"); + return; + } + } + #else + if(request) + { + print("stuffto command is not enabled on this server.\n"); + return; + } + #endif +} + +void GameCommand_trace(float request, float argc) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + entity e; + vector org, delta, start, end, p, q, q0, pos, vv, dv; + float i, f, safe, unsafe, dq, dqf; + + switch(argv(1)) + { + case "debug": + { + print("TEST CASE. If this returns the runaway loop counter error, possibly everything is oaky.\n"); + for(;;) + { + org = world.mins; + delta = world.maxs - world.mins; + + start_x = org_x + random() * delta_x; + start_y = org_y + random() * delta_y; + start_z = org_z + random() * delta_z; + + end_x = org_x + random() * delta_x; + end_y = org_y + random() * delta_y; + end_z = org_z + random() * delta_z; + + start = stov(vtos(start)); + end = stov(vtos(end)); + + tracebox(start, PL_MIN, PL_MAX, end, MOVE_NOMONSTERS, world); + if(!trace_startsolid) + { + p = trace_endpos; + tracebox(p, PL_MIN, PL_MAX, p, MOVE_NOMONSTERS, world); + if(trace_startsolid || trace_fraction == 1) + { + rint(42); // do an engine breakpoint on VM_rint so you can get the trace that errnoeously returns startsolid + tracebox(start, PL_MIN, PL_MAX, end, MOVE_NOMONSTERS, world); + tracebox(p, PL_MIN, PL_MAX, q, MOVE_NOMONSTERS, world); + + if(trace_startsolid) + { + // how much do we need to back off? + safe = 1; + unsafe = 0; + for(;;) + { + pos = p * (1 - (safe + unsafe) * 0.5) + start * ((safe + unsafe) * 0.5); + tracebox(pos, PL_MIN, PL_MAX, pos, MOVE_NOMONSTERS, world); + if(trace_startsolid) + { + if((safe + unsafe) * 0.5 == unsafe) + break; + unsafe = (safe + unsafe) * 0.5; + } + else + { + if((safe + unsafe) * 0.5 == safe) + break; + safe = (safe + unsafe) * 0.5; + } + } + + print("safe distance to back off: ", ftos(safe * vlen(p - start)), "qu\n"); + print("unsafe distance to back off: ", ftos(unsafe * vlen(p - start)), "qu\n"); + + tracebox(p, PL_MIN + '0.1 0.1 0.1', PL_MAX - '0.1 0.1 0.1', p, MOVE_NOMONSTERS, world); + if(trace_startsolid) + print("trace_endpos much in solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p), "\n"); + else + print("trace_endpos just in solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p), "\n"); + break; + } + + q0 = p; + dq = 0; + dqf = 1; + for(;;) + { + q = p + normalize(end - p) * (dq + dqf); + if(q == q0) + break; + tracebox(p, PL_MIN, PL_MAX, q, MOVE_NOMONSTERS, world); + if(trace_startsolid) + error("THIS ONE cannot happen"); + if(trace_fraction > 0) + dq += dqf * trace_fraction; + dqf *= 0.5; + q0 = q; + } + if(dq > 0) + { + print("trace_endpos still before solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p), "\n"); + print("could go ", ftos(dq), " units further to ", vtos(q), "\n"); + break; + } + } + } + } + return; + } + + case "debug2": + { + e = nextent(world); + tracebox(e.origin + '0 0 32', e.mins, e.maxs, e.origin + '0 0 -1024', MOVE_NORMAL, e); + vv = trace_endpos; + if(trace_fraction == 1) + { + print("not above ground, aborting\n"); + return; + } + f = 0; + for(i = 0; i < 100000; ++i) + { + dv = randomvec(); + if(dv_z > 0) + dv = -1 * dv; + tracebox(vv, e.mins, e.maxs, vv + dv, MOVE_NORMAL, e); + if(trace_startsolid) + print("bug 1\n"); + if(trace_fraction == 1) + if(dv_z < f) + { + print("bug 2: ", ftos(dv_x), " ", ftos(dv_y), " ", ftos(dv_z)); + print(" (", ftos(asin(dv_z / vlen(dv)) * 180 / M_PI), " degrees)\n"); + f = dv_z; + } + } + print("highest possible dist: ", ftos(f), "\n"); + return; + } + + case "walk": + { + if(argc == 3) + { + e = nextent(world); + if(tracewalk(e, stov(argv(1)), e.mins, e.maxs, stov(argv(2)), MOVE_NORMAL)) + print("can walk\n"); + else + print("cannot walk\n"); + return; + } + } + + case "showline": + { + if(argc == 3) + { + vv = stov(argv(1)); + dv = stov(argv(2)); + traceline(vv, dv, MOVE_NORMAL, world); + trailparticles(world, particleeffectnum("TR_NEXUIZPLASMA"), vv, trace_endpos); + trailparticles(world, particleeffectnum("TR_CRYLINKPLASMA"), trace_endpos, dv); + return; + } + } + + // no default case, just go straight to invalid + } + } + + default: + print("Incorrect parameters for ^2trace^7\n"); + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd trace command (startpos endpos)\n"); + print(" Full list of commands here: \"debug, debug2, walk, showline.\"\n"); + print("See also: ^2bbox, gettaginfo^7\n"); + return; + } + } +} + +void GameCommand_unlockteams(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(teamplay) + { + lockteams = 0; + bprint("^1The teams are now unlocked.\n"); + } + else + { + bprint("unlockteams command can only be used in a team-based gamemode.\n"); + } + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd unlockteams\n"); + print(" No arguments required.\n"); + print("See also: ^2lockteams^7\n"); + return; + } + } +} + +void GameCommand_warp(float request, float argc) +{ + switch (request) + { + case CMD_REQUEST_COMMAND: + { + if(autocvar_g_campaign) + { + if(argc >= 2) + { + CampaignLevelWarp(stof(argv(1))); + print("Successfully warped to campaign level ", stof(argv(1)), ".\n"); + } + else + { + CampaignLevelWarp(-1); + print("Successfully warped to next campaign level.\n"); + } + } + else + print("Not in campaign, can't level warp\n"); + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd level\n"); + print(" 'level' is the level to change campaign mode to.\n"); + return; + } + } +} + +/* use this when creating a new command, making sure to place it in alphabetical order... also, +** ADD ALL NEW COMMANDS TO commands.cfg WITH PROPER ALIASES IN THE SAME FASHION! +void GameCommand_(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print("\nUsage:^3 sv_cmd \n"); + print(" No arguments required.\n"); + return; + } + } +} +*/ + + +// ================================== +// Macro system for server commands +// ================================== + +// Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;) +// Common commands have double indentation to separate them a bit. +#define SERVER_COMMANDS(request,arguments,command) \ + SERVER_COMMAND("adminmsg", GameCommand_adminmsg(request, arguments), "Send an admin message to a client directly") \ + SERVER_COMMAND("allready", GameCommand_allready(request), "Restart the server and reset the players") \ + SERVER_COMMAND("allspec", GameCommand_allspec(request, arguments), "Force all players to spectate") \ + SERVER_COMMAND("anticheat", GameCommand_anticheat(request, arguments), "Create an anticheat report for a client") \ + SERVER_COMMAND("bbox", GameCommand_bbox(request), "Print detailed information about world size") \ + SERVER_COMMAND("bot_cmd", GameCommand_bot_cmd(request, arguments), "Control and send commands to bots") \ + SERVER_COMMAND("cointoss", GameCommand_cointoss(request, arguments), "Flip a virtual coin and give random result") \ + SERVER_COMMAND("database", GameCommand_database(request, arguments), "Extra controls of the serverprogs database") \ + SERVER_COMMAND("defer_clear", GameCommand_defer_clear(request, arguments), "Clear all queued defer commands for a specific client") \ + SERVER_COMMAND("defer_clear_all", GameCommand_defer_clear_all(request), "Clear all queued defer commands for all clients") \ + SERVER_COMMAND("delrec", GameCommand_delrec(request, arguments), "Delete race time record for a map") \ + SERVER_COMMAND("effectindexdump", GameCommand_effectindexdump(request), "Dump list of effects from code and effectinfo.txt") \ + SERVER_COMMAND("extendmatchtime", GameCommand_extendmatchtime(request), "Increase the timelimit value incrementally") \ + SERVER_COMMAND("find", GameCommand_find(request, arguments), "Search through entities for matching classname") \ + SERVER_COMMAND("gametype", GameCommand_gametype(request, arguments), "Simple command to change the active gametype") \ + SERVER_COMMAND("gettaginfo", GameCommand_gettaginfo(request, arguments), "Get specific information about a weapon model") \ + SERVER_COMMAND("gotomap", GameCommand_gotomap(request, arguments), "Simple command to switch to another map") \ + SERVER_COMMAND("lockteams", GameCommand_lockteams(request), "Disable the ability for players to switch or enter teams") \ + SERVER_COMMAND("make_mapinfo", GameCommand_make_mapinfo(request), "Automatically rebuild mapinfo files") \ + SERVER_COMMAND("moveplayer", GameCommand_moveplayer(request, arguments), "Change the team/status of a player") \ + SERVER_COMMAND("nospectators", GameCommand_nospectators(request), "Automatically remove spectators from a match") \ + SERVER_COMMAND("playerdemo", GameCommand_playerdemo(request, arguments), "Control the ability to save demos of players") \ + SERVER_COMMAND("printstats", GameCommand_printstats(request), "Dump eventlog player stats and other score information") \ + SERVER_COMMAND("radarmap", GameCommand_radarmap(request, arguments), "Generate a radar image of the map") \ + SERVER_COMMAND("reducematchtime", GameCommand_reducematchtime(request), "Decrease the timelimit value incrementally") \ + SERVER_COMMAND("setbots", GameCommand_setbots(request, arguments), "Adjust how many bots are in the match") \ + SERVER_COMMAND("shuffleteams", GameCommand_shuffleteams(request), "Randomly move players to different teams") \ + SERVER_COMMAND("stuffto", GameCommand_stuffto(request, arguments), "Send a command to be executed on a client") \ + SERVER_COMMAND("trace", GameCommand_trace(request, arguments), "Various debugging tools with tracing") \ + SERVER_COMMAND("unlockteams", GameCommand_unlockteams(request), "Enable the ability for players to switch or enter teams") \ + SERVER_COMMAND("warp", GameCommand_warp(request, arguments), "Choose different level in campaign") \ + /* nothing */ + +void GameCommand_macro_help() +{ + #define SERVER_COMMAND(name,function,description) \ + { print(" ^2", name, "^7: ", description, "\n"); } + + SERVER_COMMANDS(0, 0, "") + #undef SERVER_COMMAND + + return; +} + +float GameCommand_macro_command(float argc, string command) +{ + #define SERVER_COMMAND(name,function,description) \ + { if(name == strtolower(argv(0))) { function; return TRUE; } } + + SERVER_COMMANDS(CMD_REQUEST_COMMAND, argc, command) + #undef SERVER_COMMAND + + return FALSE; +} + +float GameCommand_macro_usage(float argc) +{ + #define SERVER_COMMAND(name,function,description) \ + { if(name == strtolower(argv(1))) { function; return TRUE; } } + + SERVER_COMMANDS(CMD_REQUEST_USAGE, argc, "") + #undef SERVER_COMMAND + + return FALSE; +} + +void GameCommand_macro_write_aliases(float fh) +{ + #define SERVER_COMMAND(name,function,description) \ + { CMD_Write_Alias("qc_cmd_sv", name, description); } + + SERVER_COMMANDS(0, 0, "") + #undef SERVER_COMMAND + + return; +} + + +// ========================================= +// Main Function Called By Engine (sv_cmd) +// ========================================= +// If this function exists, game code handles gamecommand instead of the engine code. + +void GameCommand(string command) +{ + float argc = tokenize_console(command); + + // Guide for working with argc arguments by example: + // argc: 1 - 2 - 3 - 4 + // argv: 0 - 1 - 2 - 3 + // cmd vote - master - login - password + + if(strtolower(argv(0)) == "help") + { + if(argc == 1) + { + print("\nServer console commands:\n"); + GameCommand_macro_help(); + + print("\nBanning commands:\n"); + BanCommand_macro_help(); + + print("\nCommon networked commands:\n"); + CommonCommand_macro_help(world); + + print("\nGeneric commands shared by all programs:\n"); + GenericCommand_macro_help(); + + print("\nUsage:^3 sv_cmd COMMAND...^7, where possible commands are listed above.\n"); + print("For help about a specific command, type sv_cmd help COMMAND\n"); + + return; + } + else if(BanCommand_macro_usage(argc)) // Instead of trying to call a command, we're going to see detailed information about it + { + return; + } + else if(CommonCommand_macro_usage(argc, world)) // same here, but for common commands instead + { + return; + } + else if(GenericCommand_macro_usage(argc)) // same here, but for generic commands instead + { + return; + } + else if(GameCommand_macro_usage(argc)) // finally try for normal commands too + { + return; + } + } + else if(BanCommand(command)) + { + return; // handled by server/command/ipban.qc + } + else if(CommonCommand_macro_command(argc, world, command)) + { + return; // handled by server/command/common.qc + } + else if(GenericCommand(command)) + { + return; // handled by common/command/generic.qc + } + else if(GameCommand_macro_command(argc, command)) // continue as usual and scan for normal commands + { + return; // handled by one of the above GameCommand_* functions + } + + // nothing above caught the command, must be invalid + print(((command != "") ? strcat("Unknown server command \"", command, "\"") : "No command provided"), ". For a list of supported commands, try sv_cmd help.\n"); + + return; +} \ No newline at end of file diff --git a/qcsrc/server/command/sv_cmd.qh b/qcsrc/server/command/sv_cmd.qh new file mode 100644 index 0000000000..03bd80cefc --- /dev/null +++ b/qcsrc/server/command/sv_cmd.qh @@ -0,0 +1,16 @@ +// ================================================= +// Declarations for server side game commands +// Last updated: December 25th, 2011 +// ================================================= + +string GotoMap(string m); + +void race_deleteTime(string map, float pos); + +#define SHUFFLETEAMS_MAX_PLAYERS 255 +#define SHUFFLETEAMS_MAX_TEAMS 4 +float shuffleteams_players[SHUFFLETEAMS_MAX_PLAYERS]; // maximum of 255 player slots +float shuffleteams_teams[SHUFFLETEAMS_MAX_TEAMS]; // maximum of 4 teams + +// used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file +void GameCommand_macro_write_aliases(float fh); \ No newline at end of file diff --git a/qcsrc/server/command/vote.qc b/qcsrc/server/command/vote.qc new file mode 100644 index 0000000000..8769629f96 --- /dev/null +++ b/qcsrc/server/command/vote.qc @@ -0,0 +1,988 @@ +// ============================================= +// Server side voting code, reworked by Samual +// Last updated: December 27th, 2011 +// ============================================= + +// Nagger for players to know status of voting +float Nagger_SendEntity(entity to, float sendflags) +{ + float nags, i, f, b; + entity e; + WriteByte(MSG_ENTITY, ENT_CLIENT_NAGGER); + + // bits: + // 1 = ready + // 2 = player needs to ready up + // 4 = vote + // 8 = player needs to vote + // 16 = warmup + // sendflags: + // 64 = vote counts + // 128 = vote string + + nags = 0; + if(readycount) + { + nags |= 1; + if(to.ready == 0) + nags |= 2; + } + if(vote_called) + { + nags |= 4; + if(to.vote_selection == 0) + nags |= 8; + } + if(inWarmupStage) + nags |= 16; + + if(sendflags & 64) + nags |= 64; + + if(sendflags & 128) + nags |= 128; + + if(!(nags & 4)) // no vote called? send no string + nags &~= (64 | 128); + + WriteByte(MSG_ENTITY, nags); + + if(nags & 64) + { + WriteByte(MSG_ENTITY, vote_accept_count); + WriteByte(MSG_ENTITY, vote_reject_count); + WriteByte(MSG_ENTITY, vote_needed_overall); + WriteChar(MSG_ENTITY, to.vote_selection); + } + + if(nags & 128) + WriteString(MSG_ENTITY, vote_called_display); + + if(nags & 1) + { + for(i = 1; i <= maxclients; i += 8) + { + for(f = 0, e = edict_num(i), b = 1; b < 256; b *= 2, e = nextent(e)) + if(clienttype(e) != CLIENTTYPE_REAL || e.ready) + f |= b; + WriteByte(MSG_ENTITY, f); + } + } + + return TRUE; +} + +void Nagger_Init() +{ + Net_LinkEntity(nagger = spawn(), FALSE, 0, Nagger_SendEntity); +} + +void Nagger_VoteChanged() +{ + if(nagger) + nagger.SendFlags |= 128; +} + +void Nagger_VoteCountChanged() +{ + if(nagger) + nagger.SendFlags |= 64; +} + +void Nagger_ReadyCounted() +{ + if(nagger) + nagger.SendFlags |= 1; +} + + +// ======================= +// Game logic for voting +// ======================= + +void VoteReset() +{ + entity tmp_player; + + FOR_EACH_CLIENT(tmp_player) { tmp_player.vote_selection = 0; } + + if(vote_called) + { + strunzone(vote_called_command); + strunzone(vote_called_display); + } + + vote_called = VOTE_NULL; + vote_caller = world; + vote_endtime = 0; + + vote_called_command = string_null; + vote_called_display = string_null; + + vote_parsed_command = string_null; + vote_parsed_display = string_null; + + Nagger_VoteChanged(); +} + +void VoteStop(entity stopper) +{ + bprint("\{1}^2* ^3", GetCallerName(stopper), "^2 stopped ^3", GetCallerName(vote_caller), "^2's vote\n"); + if(autocvar_sv_eventlog) { GameLogEcho(strcat(":vote:vstop:", ftos(stopper.playerid))); } + + // Don't force them to wait for next vote, this way they can e.g. correct their vote. + if((vote_caller) && (stopper == vote_caller)) { vote_caller.vote_waittime = time + autocvar_sv_vote_stop; } + + VoteReset(); +} + +void VoteAccept() +{ + bprint("\{1}^2* ^3", GetCallerName(vote_caller), "^2's vote for ^1", vote_called_display, "^2 was accepted\n"); + + if((vote_called == VOTE_MASTER) && vote_caller) + vote_caller.vote_master = 1; + else + localcmd(strcat(vote_called_command, "\n")); + + if(vote_caller) { vote_caller.vote_waittime = 0; } // people like your votes, you don't need to wait to vote again + + VoteReset(); + Announce("voteaccept"); +} + +void VoteReject() +{ + bprint("\{1}^2* ^3", GetCallerName(vote_caller), "^2's vote for ", vote_called_display, "^2 was rejected\n"); + VoteReset(); + Announce("votefail"); +} + +void VoteTimeout() +{ + bprint("\{1}^2* ^3", GetCallerName(vote_caller), "^2's vote for ", vote_called_display, "^2 timed out\n"); + VoteReset(); + Announce("votefail"); +} + +void VoteSpam(float notvoters, float mincount, string result) +{ + bprint(strcat( + strcat("\{1}^2* vote results: ^1", ftos(vote_accept_count)), + strcat("^2:^1", ftos(vote_reject_count)), + ((mincount >= 0) ? strcat("^2 (^1", ftos(mincount), "^2 needed)") : "^2"), + strcat(", ^1", ftos(vote_abstain_count), "^2 didn't care"), + strcat(", ^1", ftos(notvoters), strcat("^2 didn't ", ((mincount >= 0) ? string_null : "have to "), "vote\n")))); + + if(autocvar_sv_eventlog) + { + GameLogEcho(strcat( + strcat(":vote:v", result, ":", ftos(vote_accept_count)), + strcat(":", ftos(vote_reject_count)), + strcat(":", ftos(vote_abstain_count)), + strcat(":", ftos(notvoters)), + strcat(":", ftos(mincount)))); + } +} + +void VoteCount() +{ + // declarations + vote_accept_count = vote_reject_count = vote_abstain_count = 0; + + float spectators_allowed = ((autocvar_sv_vote_nospectators != 2) + || ((autocvar_sv_vote_nospectators == 1) && inWarmupStage) + || (autocvar_sv_vote_nospectators == 0)); + + float vote_player_count, is_player, notvoters; + float vote_real_player_count, vote_real_accept_count; + float vote_real_reject_count, vote_real_abstain_count; + float vote_needed_of_voted, final_needed_votes; + float vote_factor_overall, vote_factor_of_voted; + + entity tmp_player; + + Nagger_VoteCountChanged(); + + // add up all the votes from each connected client + FOR_EACH_REALCLIENT(tmp_player) + { + is_player = (tmp_player.classname == "player"); + + ++vote_player_count; + if(is_player) { ++vote_real_player_count; } + + switch(tmp_player.vote_selection) + { + case VOTE_SELECT_REJECT: { ++vote_reject_count; { if(is_player) ++vote_real_reject_count; } break; } + case VOTE_SELECT_ACCEPT: { ++vote_accept_count; { if(is_player) ++vote_real_reject_count; } break; } + case VOTE_SELECT_ABSTAIN: { ++vote_abstain_count; { if(is_player) ++vote_real_abstain_count; } break; } + default: break; + } + } + + // Check to see if there are enough players on the server to allow master voting... otherwise, vote master could be used for evil. + if((vote_called == VOTE_MASTER) && autocvar_sv_vote_master_playerlimit > vote_player_count) + { + if(vote_caller) { vote_caller.vote_waittime = 0; } + print_to(vote_caller, "^1There are not enough players on this server to allow you to become vote master."); + VoteReset(); + return; + } + + // if spectators aren't allowed to vote and there are players in a match, then only count the players in the vote and ignore spectators. + if(!spectators_allowed && (vote_real_player_count > 0)) + { + vote_accept_count = vote_real_accept_count; + vote_reject_count = vote_real_reject_count; + vote_abstain_count = vote_real_abstain_count; + vote_player_count = vote_real_player_count; + } + + // people who have no opinion in any way :D + notvoters = (vote_player_count - vote_accept_count - vote_reject_count - vote_abstain_count); + + // determine the goal for the vote to be passed or rejected normally + vote_factor_overall = bound(0.5, autocvar_sv_vote_majority_factor, 0.999); + vote_needed_overall = floor((vote_player_count - vote_abstain_count) * vote_factor_overall) + 1; + + // if the vote times out, determine the amount of votes needed of the people who actually already voted + vote_factor_of_voted = bound(0.5, autocvar_sv_vote_majority_factor_of_voted, 0.999); + vote_needed_of_voted = floor((vote_accept_count + vote_reject_count) * vote_factor_of_voted) + 1; + + + // finally calculate the result of the vote + if(vote_accept_count >= vote_needed_overall) + { + VoteSpam(notvoters, -1, "yes"); // there is enough acceptions to pass the vote + VoteAccept(); + return; + } + + if(vote_reject_count > vote_player_count - vote_abstain_count - vote_needed_overall) + { + VoteSpam(notvoters, -1, "no"); // there is enough rejections to deny the vote + VoteReject(); + return; + } + + // there is not enough votes in either direction, now lets just calculate what the voters have said + if(time > vote_endtime) + { + final_needed_votes = vote_needed_overall; + + if(autocvar_sv_vote_majority_factor_of_voted) + { + if(vote_accept_count >= vote_needed_of_voted) + { + VoteSpam(notvoters, min(vote_needed_overall, vote_needed_of_voted), "yes"); + VoteAccept(); + return; + } + + if(vote_accept_count + vote_reject_count > 0) + { + VoteSpam(notvoters, min(vote_needed_overall, vote_needed_of_voted), "no"); + VoteReject(); + return; + } + + final_needed_votes = min(vote_needed_overall, vote_needed_of_voted); + } + + // it didn't pass or fail, so not enough votes to even make a decision. + VoteSpam(notvoters, final_needed_votes, "timeout"); + VoteTimeout(); + } +} + +void VoteThink() +{ + if(vote_endtime > 0) // a vote was called + if(time > vote_endtime) // time is up + { + VoteCount(); + } + + return; +} + + +// ======================= +// Game logic for warmup +// ======================= + +// Restarts the map after the countdown is over (and cvar sv_ready_restart_after_countdown is set) +void ReadyRestart_think() +{ + restart_mapalreadyrestarted = 1; + reset_map(TRUE); + Score_ClearAll(); + remove(self); + + return; +} + +// Forces a restart of the game without actually reloading the map // this is a mess... +void ReadyRestart_force() +{ + entity tmp_player, restart_timer; + + bprint("^1Server is restarting...\n"); + + VoteReset(); + + // clear overtime, we have to decrease timelimit to its original value again. + if (checkrules_overtimesadded > 0 && g_race_qualifying != 2) { cvar_set("timelimit", ftos(autocvar_timelimit - (checkrules_overtimesadded * autocvar_timelimit_overtime))); } + + checkrules_suddendeathend = checkrules_overtimesadded = checkrules_suddendeathwarning = 0; + + readyrestart_happened = 1; + game_starttime = time; + if(!g_ca && !g_arena) { game_starttime += RESTART_COUNTDOWN; } + + restart_mapalreadyrestarted = 0; // reset this var, needed when cvar sv_ready_restart_repeatable is in use + + // disable the warmup global for the server + inWarmupStage = 0; // once the game is restarted the game is in match stage + + // reset the .ready status of all players (also spectators) + FOR_EACH_CLIENTSLOT(tmp_player) { tmp_player.ready = 0; } + readycount = 0; + Nagger_ReadyCounted(); // NOTE: this causes a resend of that entity, and will also turn off warmup state on the client + + // lock teams with lockonrestart + if(autocvar_teamplay_lockonrestart && teamplay) + { + lockteams = 1; + bprint("^1The teams are now locked.\n"); + } + + //initiate the restart-countdown-announcer entity + if(autocvar_sv_ready_restart_after_countdown && !g_ca && !g_arena) + { + restart_timer = spawn(); + restart_timer.think = ReadyRestart_think; + restart_timer.nextthink = game_starttime; + } + + // after a restart every players number of allowed timeouts gets reset, too + if(autocvar_sv_timeout) { FOR_EACH_REALPLAYER(tmp_player) { tmp_player.allowed_timeouts = autocvar_sv_timeout_number; } } + + //reset map immediately if this cvar is not set + if not(autocvar_sv_ready_restart_after_countdown) { reset_map(TRUE); } + + if(autocvar_sv_eventlog) { GameLogEcho(":restart"); } +} + +void ReadyRestart() +{ + // no arena, assault support yet... + if(g_arena | g_assault | gameover | intermission_running | race_completing) + localcmd("restart\n"); + else + localcmd("\nsv_hook_gamerestart\n"); + + // Reset ALL scores, but only do that at the beginning of the countdown if sv_ready_restart_after_countdown is off! + // Otherwise scores could be manipulated during the countdown. + if not(autocvar_sv_ready_restart_after_countdown) { Score_ClearAll(); } + + ReadyRestart_force(); + + return; +} + +// Count the players who are ready and determine whether or not to restart the match +void ReadyCount() +{ + entity tmp_player; + float ready_needed_factor, ready_needed_count; + float t_ready, t_players; + + FOR_EACH_REALPLAYER(tmp_player) + { + ++t_players; + if(tmp_player.ready) { ++t_ready; } + } + + readycount = t_ready; + + Nagger_ReadyCounted(); + + ready_needed_factor = bound(0.5, cvar("g_warmup_majority_factor"), 0.999); + ready_needed_count = floor(t_players * ready_needed_factor) + 1; + + if(readycount >= ready_needed_count) + { + ReadyRestart(); + } + + return; +} + + +// ====================================== +// Supporting functions for VoteCommand +// ====================================== + +float Votecommand_check_assignment(entity caller, float assignment) +{ + float from_server = (!caller); + + if((assignment == VC_ASGNMNT_BOTH) + || ((!from_server && assignment == VC_ASGNMNT_CLIENTONLY) + || (from_server && assignment == VC_ASGNMNT_SERVERONLY))) + { + return TRUE; + } + + return FALSE; +} + +string VoteCommand_extractcommand(string input, float startpos, float argc) +{ + string output; + + if((argc - 1) < startpos) + output = ""; + else + output = substring(input, argv_start_index(startpos), argv_end_index(-1) - argv_start_index(startpos)); + + return output; +} + +float VoteCommand_checknasty(string vote_command) +{ + if((strstrofs(vote_command, ";", 0) >= 0) + || (strstrofs(vote_command, "\n", 0) >= 0) + || (strstrofs(vote_command, "\r", 0) >= 0) + || (strstrofs(vote_command, "$", 0) >= 0)) + return FALSE; + + return TRUE; +} + +float VoteCommand_checkinlist(string vote_command, string list) +{ + string l = strcat(" ", list, " "); + + if(strstrofs(l, strcat(" ", vote_command, " "), 0) >= 0) + return TRUE; + + // if gotomap is allowed, chmap is too, and vice versa + if(vote_command == "gotomap") + if(strstrofs(l, " chmap ", 0) >= 0) + return TRUE; + + if(vote_command == "chmap") + if(strstrofs(l, " gotomap ", 0) >= 0) + return TRUE; + + return FALSE; +} + +string ValidateMap(string validated_map, entity caller) +{ + validated_map = MapInfo_FixName(validated_map); + + if(!validated_map) + { + print_to(caller, "This map is not available on this server."); + return string_null; + } + + if(!autocvar_sv_vote_override_mostrecent && caller) + { + if(Map_IsRecent(validated_map)) + { + print_to(caller, "This server does not allow for recent maps to be played again. Please be patient for some rounds."); + return string_null; + } + } + + if(!MapInfo_CheckMap(validated_map)) + { + print_to(caller, strcat("^1Invalid mapname, \"^3", validated_map, "^1\" does not support the current game mode.")); + return string_null; + } + + return validated_map; +} + +float VoteCommand_parse(entity caller, string vote_command, string vote_list, float startpos, float argc) +{ + string first_command; + + first_command = argv(startpos); + + if not(VoteCommand_checkinlist(first_command, vote_list)) + return FALSE; + + if(argc < startpos) // These commands won't work without arguments + { + switch(first_command) + { + case "map": + case "chmap": + case "gotomap": + case "kick": + case "kickban": + return FALSE; + + default: { break; } + } + } + + switch(first_command) // now go through and parse the proper commands to adjust as needed. + { + case "kick": + case "kickban": // catch all kick/kickban commands + { + entity victim = GetIndexedEntity(argc, (startpos + 1)); + float accepted = VerifyClientEntity(victim, TRUE, FALSE); + + if(accepted > 0) + { + string reason = ((argc > next_token) ? substring(vote_command, argv_start_index(next_token), argv_end_index(-1) - argv_start_index(next_token)) : "No reason provided"); + string command_arguments; + + if(first_command == "kickban") + command_arguments = strcat(ftos(autocvar_g_ban_default_bantime), " ", ftos(autocvar_g_ban_default_masksize), " ~"); + else + command_arguments = reason; + + vote_parsed_command = strcat(first_command, " # ", ftos(num_for_edict(victim)), " ", command_arguments); + vote_parsed_display = strcat("^1", vote_command, " (^7", victim.netname, "^1): ", reason); + } + else { print_to(caller, strcat("vcall: ", GetClientErrorString(accepted, argv(startpos + 1)), ".\n")); return FALSE; } + + break; + } + + case "map": + case "chmap": + case "gotomap": // re-direct all map selection commands to gotomap + { + vote_command = ValidateMap(argv(startpos + 1), caller); + if not(vote_command) { return FALSE; } + vote_parsed_command = strcat("gotomap ", vote_command); + vote_parsed_display = strzone(strcat("^1", vote_parsed_command)); + + break; + } + + default: + { + vote_parsed_command = vote_command; + vote_parsed_display = strzone(strcat("^1", vote_command)); + + break; + } + } + + return TRUE; +} + + +// ======================= +// Command Sub-Functions +// ======================= + +void VoteCommand_abstain(float request, entity caller) // CLIENT ONLY +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if not(vote_called) { print_to(caller, "^1No vote called."); } + else if not(caller.vote_selection == VOTE_SELECT_NULL || autocvar_sv_vote_change) { print_to(caller, "^1You have already voted."); } + + else // everything went okay, continue changing vote + { + print_to(caller, "^1You abstained from your vote."); + caller.vote_selection = VOTE_SELECT_ABSTAIN; + msg_entity = caller; + if(!autocvar_sv_vote_singlecount) { VoteCount(); } + } + + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " vote abstain")); + print_to(caller, " No arguments required."); + return; + } + } +} + +void VoteCommand_call(float request, entity caller, float argc, string vote_command) // BOTH +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + float spectators_allowed = ((autocvar_sv_vote_nospectators != 2) + || ((autocvar_sv_vote_nospectators == 1) && inWarmupStage) + || (autocvar_sv_vote_nospectators == 0)); + + float tmp_playercount; + entity tmp_player; + + vote_command = VoteCommand_extractcommand(vote_command, 2, argc); + + if not(autocvar_sv_vote_call || !caller) { print_to(caller, "^1Vote calling is not allowed."); } + else if(vote_called) { print_to(caller, "^1There is already a vote called."); } + else if(!spectators_allowed && (caller && (caller.classname != "player"))) { print_to(caller, "^1Only players can call a vote."); } + else if(timeout_status) { print_to(caller, "^1You can not call a vote while a timeout is active."); } + else if(caller && (time < caller.vote_waittime)) { print_to(caller, strcat("^1You have to wait ^2", ftos(ceil(caller.vote_waittime - time)), "^1 seconds before you can again call a vote.")); } + else if not(VoteCommand_checknasty(vote_command)) { print_to(caller, "^1Syntax error in command, see 'vhelp' for more info."); } + else if not(VoteCommand_parse(caller, vote_command, autocvar_sv_vote_commands, 2, argc)) { print_to(caller, "^1This command is not acceptable, see 'vhelp' for more info."); } + + else // everything went okay, continue with calling the vote + { + vote_caller = caller; // remember who called the vote + vote_called = VOTE_NORMAL; + vote_called_command = strzone(vote_parsed_command); + vote_called_display = strzone(vote_parsed_display); + vote_endtime = time + autocvar_sv_vote_timeout; + + if(caller) + { + caller.vote_selection = VOTE_SELECT_ACCEPT; + caller.vote_waittime = time + autocvar_sv_vote_wait; + msg_entity = caller; + } + + FOR_EACH_REALCLIENT(tmp_player) { ++tmp_playercount; } + if(tmp_playercount > 1) { Announce("votecall"); } // don't announce a "vote now" sound if player is alone + + bprint("\{1}^2* ^3", GetCallerName(vote_caller), "^2 calls a vote for ", vote_called_display, "\n"); + if(autocvar_sv_eventlog) { GameLogEcho(strcat(":vote:vcall:", ftos(vote_caller.playerid), ":", vote_called_display)); } + Nagger_VoteChanged(); + VoteCount(); // needed if you are the only one + } + + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " vote call command")); + print_to(caller, " Where 'command' is the command to request a vote upon."); + print_to(caller, strcat("Examples: ", GetCommandPrefix(caller), " vote call gotomap dance")); + print_to(caller, strcat(" ", GetCommandPrefix(caller), " vote call endmatch")); + return; + } + } +} + +void VoteCommand_master(float request, entity caller, float argc, string vote_command) // CLIENT ONLY +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(autocvar_sv_vote_master) + { + switch(strtolower(argv(2))) + { + case "do": + { + vote_command = VoteCommand_extractcommand(vote_command, 3, argc); + + if not(caller.vote_master) { print_to(caller, "^1You do not have vote master privelages."); } + else if not(VoteCommand_checknasty(vote_command)) { print_to(caller, "^1Syntax error in command, see 'vhelp' for more info."); } + else if not(VoteCommand_parse(caller, vote_command, strcat(autocvar_sv_vote_commands, " ", autocvar_sv_vote_master_commands), 3, argc)) { print_to(caller, "^1This command is not acceptable, see 'vhelp' for more info."); } + + else // everything went okay, proceed with command + { + localcmd(strcat(vote_parsed_command, "\n")); + print_to(caller, strcat("Executing command '", vote_parsed_display, "' on server.")); + bprint("\{1}^2* ^3", GetCallerName(caller), "^2 used their ^3master^2 status to do \"^2", vote_parsed_display, "^2\".\n"); + if(autocvar_sv_eventlog) { GameLogEcho(strcat(":vote:vdo:", ftos(caller.playerid), ":", vote_parsed_display)); } + } + + return; + } + + case "login": + { + if not(autocvar_sv_vote_master_password != "") { print_to(caller, "^1Login to vote master is not allowed."); } + else if(caller.vote_master) { print_to(caller, "^1You are already logged in as vote master."); } + else if not(autocvar_sv_vote_master_password == argv(3)) { print_to(caller, strcat("Rejected vote master login from ", GetCallerName(caller))); } + + else // everything went okay, proceed with giving this player master privilages + { + caller.vote_master = TRUE; + print_to(caller, strcat("Accepted vote master login from ", GetCallerName(caller))); + bprint("\{1}^2* ^3", GetCallerName(caller), "^2 logged in as ^3master^2\n"); + if(autocvar_sv_eventlog) { GameLogEcho(strcat(":vote:vlogin:", ftos(caller.playerid))); } + } + + return; + } + + default: // calling a vote for master + { + if not(autocvar_sv_vote_master_callable) { print_to(caller, "^1Vote to become vote master is not allowed."); } + else if(vote_called) { print_to(caller, "^1There is already a vote called."); } + else if(timeout_status) { print_to(caller, "^1You can not call a vote while a timeout is active."); } + + else // everything went okay, continue with creating vote + { + vote_caller = caller; + vote_called = VOTE_MASTER; + vote_called_command = strzone("XXX"); + vote_called_display = strzone("^3master"); + vote_endtime = time + autocvar_sv_vote_timeout; + + caller.vote_selection = VOTE_SELECT_ACCEPT; + caller.vote_waittime = time + autocvar_sv_vote_wait; + + bprint("\{1}^2* ^3", GetCallerName(vote_caller), "^2 calls a vote to become ^3master^2.\n"); + if(autocvar_sv_eventlog) { GameLogEcho(strcat(":vote:vcall:", ftos(vote_caller.playerid), ":", vote_called_display)); } + Nagger_VoteChanged(); + VoteCount(); // needed if you are the only one + } + + return; + } + } + } + else { print_to(caller, "^1Master control of voting is not allowed."); } + + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " vote master [action [command | password]]")); + print_to(caller, " If action is left blank, it calls a vote for you to become master."); + print_to(caller, " Otherwise the actions are either 'do' a command or 'login' as master."); + return; + } + } +} + +void VoteCommand_no(float request, entity caller) // CLIENT ONLY +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if not(vote_called) { print_to(caller, "^1No vote called."); } + else if not(caller.vote_selection == VOTE_SELECT_NULL || autocvar_sv_vote_change) { print_to(caller, "^1You have already voted."); } + else if(((caller == vote_caller) || caller.vote_master) && autocvar_sv_vote_no_stops_vote) { VoteStop(caller); } + + else // everything went okay, continue changing vote + { + print_to(caller, "^1You rejected the vote."); + caller.vote_selection = VOTE_SELECT_REJECT; + msg_entity = caller; + if(!autocvar_sv_vote_singlecount) { VoteCount(); } + } + + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " vote no")); + print_to(caller, " No arguments required."); + return; + } + } +} + +void VoteCommand_status(float request, entity caller) // BOTH +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(vote_called) + print_to(caller, strcat("^7Vote for ", vote_called_display, "^7 called by ^7", GetCallerName(vote_caller), "^7.")); + else + print_to(caller, "^1No vote called."); + + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " vote status")); + print_to(caller, " No arguments required."); + return; + } + } +} + +void VoteCommand_stop(float request, entity caller) // BOTH +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if not(vote_called) { print_to(caller, "^1No vote called."); } + else if((caller == vote_caller) || !caller || caller.vote_master) { VoteStop(caller); } + else { print_to(caller, "^1You are not allowed to stop that vote."); } + + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " vote stop")); + print_to(caller, " No arguments required."); + return; + } + } +} + +void VoteCommand_yes(float request, entity caller) // CLIENT ONLY +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if not(vote_called) { print_to(caller, "^1No vote called."); } + else if not(caller.vote_selection == VOTE_SELECT_NULL || autocvar_sv_vote_change) { print_to(caller, "^1You have already voted."); } + + else // everything went okay, continue changing vote + { + print_to(caller, "^1You accepted the vote."); + caller.vote_selection = VOTE_SELECT_ACCEPT; + msg_entity = caller; + if(!autocvar_sv_vote_singlecount) { VoteCount(); } + } + + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " vote yes")); + print_to(caller, " No arguments required."); + return; + } + } +} + +/* use this when creating a new command, making sure to place it in alphabetical order... also, +** ADD ALL NEW COMMANDS TO commands.cfg WITH PROPER ALIASES IN THE SAME FASHION! +void VoteCommand_(float request) +{ + switch(request) + { + case CMD_REQUEST_COMMAND: + { + + return; + } + + default: + case CMD_REQUEST_USAGE: + { + print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " vote "); + print_to(caller, " No arguments required."); + return; + } + } +} +*/ + + +// ================================ +// Macro system for vote commands +// ================================ + +// Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;) +#define VOTE_COMMANDS(request,caller,arguments,command) \ + VOTE_COMMAND("abstain", VoteCommand_abstain(request, caller), "Abstain your vote in current vote", VC_ASGNMNT_CLIENTONLY) \ + VOTE_COMMAND("call", VoteCommand_call(request, caller, arguments, command), "Create a new vote for players to decide on", VC_ASGNMNT_BOTH) \ + VOTE_COMMAND("help", VoteCommand_macro_help(caller, arguments), "Shows this information", VC_ASGNMNT_BOTH) \ + VOTE_COMMAND("master", VoteCommand_master(request, caller, arguments, command), "Full control over all voting and vote commands", VC_ASGNMNT_CLIENTONLY) \ + VOTE_COMMAND("no", VoteCommand_no(request, caller), "Select no in current vote", VC_ASGNMNT_CLIENTONLY) \ + VOTE_COMMAND("status", VoteCommand_status(request, caller), "Prints information about current vote", VC_ASGNMNT_BOTH) \ + VOTE_COMMAND("stop", VoteCommand_stop(request, caller), "Immediately end a vote", VC_ASGNMNT_BOTH) \ + VOTE_COMMAND("yes", VoteCommand_yes(request, caller), "Select yes in current vote", VC_ASGNMNT_CLIENTONLY) \ + /* nothing */ + +void VoteCommand_macro_help(entity caller, float argc) +{ + string command_origin = GetCommandPrefix(caller); + + if(argc == 2) // help display listing all commands + { + print_to(caller, "\nVoting commands:\n"); + #define VOTE_COMMAND(name,function,description,assignment) \ + { if(Votecommand_check_assignment(caller, assignment)) { print_to(caller, strcat(" ^2", name, "^7: ", description)); } } + + VOTE_COMMANDS(0, caller, 0, "") + #undef VOTE_COMMAND + + print_to(caller, strcat("\nUsage:^3 ", command_origin, " vote COMMAND...^7, where possible commands are listed above.\n")); + print_to(caller, strcat("For help about a specific command, type ", command_origin, " vote help COMMAND")); + print_to(caller, strcat("\n^7You can call a vote for or execute these commands: ^3", autocvar_sv_vote_commands, "^7 and maybe further ^3arguments^7")); + } + else // usage for individual command + { + #define VOTE_COMMAND(name,function,description,assignment) \ + { if(Votecommand_check_assignment(caller, assignment)) { if(name == strtolower(argv(2))) { function; return; } } } + + VOTE_COMMANDS(CMD_REQUEST_USAGE, caller, argc, "") + #undef VOTE_COMMAND + } + + return; +} + +float VoteCommand_macro_command(entity caller, float argc, string vote_command) +{ + #define VOTE_COMMAND(name,function,description,assignment) \ + { if(Votecommand_check_assignment(caller, assignment)) { if(name == strtolower(argv(1))) { function; return TRUE; } } } + + VOTE_COMMANDS(CMD_REQUEST_COMMAND, caller, argc, vote_command) + #undef VOTE_COMMAND + + return FALSE; +} + + +// ====================================== +// Main function handling vote commands +// ====================================== + +void VoteCommand(float request, entity caller, float argc, string vote_command) +{ + // Guide for working with argc arguments by example: + // argc: 1 - 2 - 3 - 4 + // argv: 0 - 1 - 2 - 3 + // cmd vote - master - login - password + + switch(request) + { + case CMD_REQUEST_COMMAND: + { + if(VoteCommand_macro_command(caller, argc, vote_command)) + return; + } + + default: + print_to(caller, strcat(((argv(1) != "") ? strcat("Unknown vote command \"", argv(1), "\"") : "No command provided"), ". For a list of supported commands, try ", GetCommandPrefix(caller), " vote help.\n")); + case CMD_REQUEST_USAGE: + { + VoteCommand_macro_help(caller, argc); + return; + } + } +} \ No newline at end of file diff --git a/qcsrc/server/command/vote.qh b/qcsrc/server/command/vote.qh new file mode 100644 index 0000000000..748b7ce6d9 --- /dev/null +++ b/qcsrc/server/command/vote.qh @@ -0,0 +1,50 @@ +// ================================================ +// Declarations for the vote system/vote commands +// Last updated: December 14th, 2011 +// ================================================ + +// definitions for command selection between progs +#define VC_ASGNMNT_BOTH 1 +#define VC_ASGNMNT_CLIENTONLY 2 +#define VC_ASGNMNT_SERVERONLY 3 + +// vote selection definitions +#define VOTE_SELECT_ABSTAIN -2 +#define VOTE_SELECT_REJECT -1 +#define VOTE_SELECT_NULL 0 +#define VOTE_SELECT_ACCEPT 1 + +// different statuses of the current vote +#define VOTE_NULL 0 +#define VOTE_NORMAL 1 +#define VOTE_MASTER 2 + +// global vote information declarations +entity vote_caller; // original caller of the current vote +float vote_called; // stores status of current vote (See VOTE_*) +float vote_endtime; // time when the vote is finished +float vote_accept_count; // total amount of players who accept the vote (counted by VoteCount() function) +float vote_reject_count; // same as above, but rejected +float vote_abstain_count; // same as above, but abstained +float vote_needed_overall; // total amount of players NEEDED for a vote to pass (based on sv_vote_majority_factor) +.float vote_master; // flag for if the player has vote master privelages +.float vote_waittime; // flag for how long the player must wait before they can vote again +.float vote_selection; // flag for which vote selection the player has made (See VOTE_SELECT_*) +string vote_called_command; // command sent by client +string vote_called_display; // visual string of command sent by client +string vote_parsed_command; // command which is fixed after being parsed +string vote_parsed_display; // visual string which is fixed after being parsed + +// allow functions to be used in other code like g_world.qc and teamplay.qc +void VoteThink(); +void VoteReset(); +void VoteCommand(float request, entity caller, float argc, string vote_command); + +// warmup and nagger stuff +#define RESTART_COUNTDOWN 10 +entity nagger; +float readycount; // amount of players who are ready +float readyrestart_happened; // keeps track of whether a restart has already happened +float restart_mapalreadyrestarted; // bool, indicates whether reset_map() was already executed +.float ready; // flag for if a player is ready +void ReadyCount(); \ No newline at end of file diff --git a/qcsrc/server/constants.qh b/qcsrc/server/constants.qh index dca76fe003..b95c726136 100644 --- a/qcsrc/server/constants.qh +++ b/qcsrc/server/constants.qh @@ -33,6 +33,7 @@ float MOVETYPE_FLYMISSILE = 9; float MOVETYPE_BOUNCE = 10; float MOVETYPE_BOUNCEMISSILE = 11; // Like bounce but doesn't lose speed on bouncing //float MOVETYPE_FOLLOW = 12; // 'Attaches' the entity to its aim_ent +//float MOVETYPE_FLY_WORLDONLY = 33; float SOLID_NOT = 0; float SOLID_TRIGGER = 1; @@ -124,13 +125,6 @@ float MSG_ALL = 2; // reliable float MSG_INIT = 3; // initialization float MSG_ENTITY = 5; // csqc -vector PL_VIEW_OFS = '0 0 35'; -vector PL_MIN = '-16 -16 -24'; -vector PL_MAX = '16 16 45'; -vector PL_CROUCH_VIEW_OFS = '0 0 15'; -vector PL_CROUCH_MIN = '-16 -16 -24'; -vector PL_CROUCH_MAX = '16 16 25'; - // Sajt - added these, just as constants. Not sure how you want them actually put in the game, but I just // did this so at least they worked // NOTE: instagib IS NOT compatible with rocket-arena, so make sure to prevent selecting both in a menu @@ -139,8 +133,6 @@ vector PL_CROUCH_MAX = '16 16 25'; //float GAME_FULLBRIGHT_PLAYERS = 64; /// makes the players model fullbright //float GAME_TEAMS = 128; /// Teams, red/green/yellow/blue -float game; // set to "gamecfg" on spawnfunc_worldspawn - //float POWERUP_STRENGTH_DAMAGE = 2; // damage multiplier for strength powerup //float POWERUP_STRENGTH_FORCE = 4; // force multiplier for strength powerup diff --git a/qcsrc/server/csqcprojectile.qc b/qcsrc/server/csqcprojectile.qc index 31e5b77885..d5b6697f25 100644 --- a/qcsrc/server/csqcprojectile.qc +++ b/qcsrc/server/csqcprojectile.qc @@ -103,25 +103,3 @@ void UpdateCSQCProjectileAfterTeleport(entity e) e.SendFlags |= 0x08; } } - -.void(void) csqcprojectile_oldthink; -.float csqcprojectile_oldnextthink; - -void CSQCProjectile_Update_Think() -{ - UpdateCSQCProjectile(self); - self.think = self.csqcprojectile_oldthink; - self.nextthink = max(time, self.csqcprojectile_oldnextthink); -} - -void UpdateCSQCProjectileNextFrame(entity e) -{ - if(e.SendEntity == CSQCProjectile_SendEntity) - if(e.think != CSQCProjectile_Update_Think) - { - e.csqcprojectile_oldthink = e.think; - e.csqcprojectile_oldnextthink = e.nextthink; - e.think = CSQCProjectile_Update_Think; - e.nextthink = time; - } -} diff --git a/qcsrc/server/csqcprojectile.qh b/qcsrc/server/csqcprojectile.qh index f569279e41..e00c0988b9 100644 --- a/qcsrc/server/csqcprojectile.qh +++ b/qcsrc/server/csqcprojectile.qh @@ -3,5 +3,4 @@ void CSQCProjectile(entity e, float clientanimate, float type, float docull); void UpdateCSQCProjectile(entity e); void UpdateCSQCProjectileAfterTeleport(entity e); -void UpdateCSQCProjectileNextFrame(entity e); void CSQCProjectile_Check(entity e); diff --git a/qcsrc/server/ctf.qc b/qcsrc/server/ctf.qc index b31e142938..f5835377d9 100644 --- a/qcsrc/server/ctf.qc +++ b/qcsrc/server/ctf.qc @@ -49,7 +49,7 @@ float ctf_captureshield_shielded(entity p) // player is in the worse half, if >= half the players are better than him, or consequently, if < half of the players are worse // use this rule here - + if(players_worseeq >= players_total * captureshield_max_ratio) return FALSE; @@ -66,12 +66,12 @@ void ctf_captureshield_update(entity p, float dir) { if(should) { - centerprint_atprio(p, CENTERPRIO_SHIELDING, "^3You are now ^4shielded^3 from the flag\n^3for ^1too many unsuccessful attempts^3 to capture.\n\n^3Make some defensive scores before trying again."); + Send_CSQC_Centerprint_Generic(other, CPID_CTF_CAPTURESHIELD, "^3You are ^4shielded^3 from the flag\n^3for ^1too many unsuccessful attempts^3 to capture.\n\n^3Get some defensive scores before trying again.", 5, 0); // TODO csqc notifier for this } else { - centerprint_atprio(p, CENTERPRIO_SHIELDING, "^3You are now free.\n\n^3Feel free to ^1try to capture^3 the flag again\n^3if you think you will succeed."); + Send_CSQC_Centerprint_Generic(p, CPID_CTF_CAPTURESHIELD, "^3You are now free.\n\n^3Feel free to ^1try to capture^3 the flag again\n^3if you think you will succeed.", 5, 0); // TODO csqc notifier for this } p.ctf_captureshielded = should; @@ -88,6 +88,7 @@ float ctf_captureshield_customize() return TRUE; } +.float ctf_captureshield_touch_msgtime; void ctf_captureshield_touch() { if not(other.ctf_captureshielded) @@ -99,7 +100,9 @@ void ctf_captureshield_touch() mymid = (self.absmin + self.absmax) * 0.5; othermid = (other.absmin + other.absmax) * 0.5; Damage(other, self, self, 0, DEATH_HURTTRIGGER, mymid, normalize(othermid - mymid) * captureshield_force); - centerprint_atprio(other, CENTERPRIO_SHIELDING, "^3You are ^4shielded^3 from the flag\n^3for ^1too many unsuccessful attempts^3 to capture.\n\n^3Get some defensive scores before trying again."); + if (time - other.ctf_captureshield_touch_msgtime > 2) + Send_CSQC_Centerprint_Generic(other, CPID_CTF_CAPTURESHIELD, "^3You are ^4shielded^3 from the flag\n^3for ^1too many unsuccessful attempts^3 to capture.\n\n^3Get some defensive scores before trying again.", 5, 0); + other.ctf_captureshield_touch_msgtime = time; } void ctf_flag_spawnstuff() @@ -125,23 +128,14 @@ void ctf_flag_spawnstuff() self.basewaypoint = self.nearestwaypoint; if(self.team == COLOR_TEAM1) - { - WaypointSprite_SpawnFixed("redbase", self.origin + '0 0 61', self, sprite); - WaypointSprite_UpdateTeamRadar(self.sprite, RADARICON_FLAG, colormapPaletteColor(COLOR_TEAM1 - 1, FALSE)); - } + WaypointSprite_SpawnFixed("redbase", self.origin + '0 0 61', self, sprite, RADARICON_FLAG, colormapPaletteColor(COLOR_TEAM1 - 1, FALSE)); else - { - WaypointSprite_SpawnFixed("bluebase", self.origin + '0 0 61', self, sprite); - WaypointSprite_UpdateTeamRadar(self.sprite, RADARICON_FLAG, colormapPaletteColor(COLOR_TEAM2 - 1, FALSE)); - } + WaypointSprite_SpawnFixed("bluebase", self.origin + '0 0 61', self, sprite, RADARICON_FLAG, colormapPaletteColor(COLOR_TEAM2 - 1, FALSE)); } float ctf_score_value(string parameter) { - if(g_ctf_win_mode != 2) - return cvar(strcat("g_ctf_personal", parameter)); - else - return cvar(strcat("g_ctf_flag", parameter)); + return cvar(strcat("g_ctf_personal", parameter)); } void FakeTimeLimit(entity e, float t) @@ -173,7 +167,7 @@ void place_flag() setattachment(self, world, ""); self.mdl = self.model; - self.flags = FL_ITEM; + self.flags = FL_ITEM | FL_NOTARGET; self.solid = SOLID_TRIGGER; self.movetype = MOVETYPE_NONE; self.velocity = '0 0 0'; @@ -196,7 +190,7 @@ void place_flag() } InitializeEntity(self, ctf_flag_spawnstuff, INITPRIO_SETLOCATION); -}; +} void LogCTF(string mode, float flagteam, entity actor) { @@ -234,8 +228,8 @@ void RegenFlag(entity e) e.angles = e.mangle; e.cnt = FLAG_BASE; e.owner = world; - e.flags = FL_ITEM; // clear FL_ONGROUND and any other junk -}; + e.flags = FL_ITEM | FL_NOTARGET; // clear FL_ONGROUND and any other junk +} void ReturnFlag(entity e) { @@ -256,11 +250,11 @@ void ReturnFlag(entity e) } e.owner = world; RegenFlag(e); -}; +} void DropFlag(entity e, entity penalty_receiver, entity attacker) { - local entity p; + entity p; if(e.classname != "item_flag_team") { @@ -296,11 +290,11 @@ void DropFlag(entity e, entity penalty_receiver, entity attacker) ctf_captureshield_update(p, 0); // shield only e.playerid = attacker.playerid; e.ctf_droptime = time; - WaypointSprite_Spawn("flagdropped", 0, 0, e, '0 0 1' * 61, world, COLOR_TEAM1 + COLOR_TEAM2 - e.team, e, waypointsprite_attachedforcarrier, FALSE); + WaypointSprite_Spawn("flagdropped", 0, 0, e, '0 0 1' * 61, world, COLOR_TEAM1 + COLOR_TEAM2 - e.team, e, waypointsprite_attachedforcarrier, FALSE, RADARICON_FLAG, '0 1 1'); + WaypointSprite_Ping(e.waypointsprite_attachedforcarrier); if(p.waypointsprite_attachedforcarrier) { - WaypointSprite_Ping(p.waypointsprite_attachedforcarrier); WaypointSprite_DetachCarrier(p); } else @@ -309,7 +303,7 @@ void DropFlag(entity e, entity penalty_receiver, entity attacker) backtrace("Flag carrier had no flag sprite?!?"); } LogCTF("dropped", p.team, p); - sound (self, CHAN_TRIGGER, self.noise4, VOL_BASE, ATTN_NONE); + sound (p, CH_TRIGGER, self.noise4, VOL_BASE, ATTN_NONE); setattachment(e, world, ""); e.damageforcescale = autocvar_g_balance_ctf_damageforcescale; @@ -319,7 +313,7 @@ void DropFlag(entity e, entity penalty_receiver, entity attacker) p.flagcarried = world; e.owner = world; - e.flags = FL_ITEM; // clear FL_ONGROUND and any other junk + e.flags = FL_ITEM | FL_NOTARGET; // clear FL_ONGROUND and any other junk e.solid = SOLID_TRIGGER; e.movetype = MOVETYPE_TOSS; // setsize(e, '-16 -16 0', '16 16 74'); @@ -332,11 +326,11 @@ void DropFlag(entity e, entity penalty_receiver, entity attacker) tracebox(e.origin, e.mins, e.maxs, e.origin, TRUE, e); if(trace_startsolid) dprint("FLAG FALLTHROUGH will happen SOON\n"); -}; +} void FlagThink() { - local entity e; + entity e; self.nextthink = time + 0.1; @@ -364,7 +358,7 @@ void FlagThink() { bprint("The ", self.netname, " became impatient after ", ftos_decimals(flagcaptimerecord, 2), " seconds and returned itself\n"); - sound (self, CHAN_TRIGGER, self.noise3, VOL_BASE, ATTN_NONE); + sound (self, CH_TRIGGER, self.noise3, VOL_BASE, ATTN_NONE); self.owner.impulse = 141; // returning! e = self; @@ -391,7 +385,7 @@ void FlagThink() if (time > self.pain_finished) { bprint("The ", self.netname, " has returned to base\n"); - sound (self, CHAN_TRIGGER, self.noise3, VOL_BASE, ATTN_NONE); + sound (self, CH_TRIGGER, self.noise3, VOL_BASE, ATTN_NONE); LogCTF("returned", self.team, world); ReturnFlag(self); } @@ -405,24 +399,30 @@ void FlagThink() DropFlag(self, world, world); return; } +} - if(autocvar_g_ctf_allow_drop) - if(e.BUTTON_USE) - DropFlag(self, e, world); -}; +float ctf_usekey() +{ + if(self.flagcarried) + { + DropFlag(self.flagcarried, self, world); + return TRUE; + } + return FALSE; +} void flag_cap_ring_spawn(vector org) { shockwave_spawn("models/ctf/shockwavetransring.md3", org - '0 0 15', -0.8, 0, 1); -}; +} void FlagTouch() { if(gameover) return; - local float t; - local entity player; - local string s, s0, h0, h1; + float t; + entity player; + string s, s0, h0, h1; if (other.classname != "player") return; if (other.health < 1) // ignore dead players @@ -493,7 +493,7 @@ void FlagTouch() } } - sound (other, CHAN_AUTO, self.noise2, VOL_BASE, ATTN_NONE); + sound (other, CH_TRIGGER, self.noise2, VOL_BASE, ATTN_NONE); WaypointSprite_DetachCarrier(other); if(self.speedrunning) FakeTimeLimit(other, -1); @@ -509,10 +509,10 @@ void FlagTouch() { if (other.next_take_time > time) return; - + if (autocvar_g_ctf_flag_pickup_effects) // pickup effect pointparticles(particleeffectnum("smoke_ring"), 0.5 * (self.absmin + self.absmax), '0 0 0', 1); - + // pick up self.flagpickuptime = time; // used for timing runs self.speedrunning = other.speedrunning; // if speedrunning, flag will self-return and teleport the owner back after the record @@ -531,7 +531,7 @@ void FlagTouch() self.dropperid = other.playerid; PlayerScore_Add(other, SP_CTF_PICKUPS, 1); LogCTF("steal", self.team, other); - sound (other, CHAN_AUTO, self.noise, VOL_BASE, ATTN_NONE); + sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTN_NONE); FOR_EACH_PLAYER(player) if(player.team == self.team) @@ -540,8 +540,7 @@ void FlagTouch() self.movetype = MOVETYPE_NONE; setorigin(self, FLAG_CARRY_POS); setattachment(self, other, ""); - WaypointSprite_AttachCarrier("flagcarrier", other); - WaypointSprite_UpdateTeamRadar(other.waypointsprite_attachedforcarrier, RADARICON_FLAGCARRIER, '1 1 0'); + WaypointSprite_AttachCarrier("flagcarrier", other, RADARICON_FLAGCARRIER, '1 1 0'); WaypointSprite_Ping(self.sprite); return; @@ -549,7 +548,7 @@ void FlagTouch() if (self.cnt == FLAG_DROPPED) { - self.flags = FL_ITEM; // clear FL_ONGROUND and any other junk + self.flags = FL_ITEM | FL_NOTARGET; // clear FL_ONGROUND and any other junk if (other.team == self.team || (other.team != COLOR_TEAM1 && other.team != COLOR_TEAM2)) { // return flag @@ -587,7 +586,7 @@ void FlagTouch() } PlayerScore_Add(other, SP_CTF_RETURNS, 1); LogCTF("return", self.team, other); - sound (other, CHAN_AUTO, self.noise1, VOL_BASE, ATTN_NONE); + sound (other, CH_TRIGGER, self.noise1, VOL_BASE, ATTN_NONE); ReturnFlag(self); } else if (!other.flagcarried && (other.playerid != self.dropperid || time > self.ctf_droptime + autocvar_g_balance_ctf_delay_collect)) @@ -597,7 +596,7 @@ void FlagTouch() if (autocvar_g_ctf_flag_pickup_effects) // field pickup effect pointparticles(particleeffectnum("smoke_ring"), 0.5 * (self.absmin + self.absmax), '0 0 0', 1); - + // pick up self.solid = SOLID_NOT; setorigin(self, self.origin); // relink @@ -619,7 +618,7 @@ void FlagTouch() UpdateFrags(other, f); PlayerScore_Add(other, SP_CTF_PICKUPS, 1); LogCTF("pickup", self.team, other); - sound (other, CHAN_AUTO, self.noise, VOL_BASE, ATTN_NONE); + sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTN_NONE); FOR_EACH_PLAYER(player) if(player.team == self.team) @@ -630,11 +629,10 @@ void FlagTouch() setattachment(self, other, ""); self.damageforcescale = 0; self.takedamage = DAMAGE_NO; - WaypointSprite_AttachCarrier("flagcarrier", other); - WaypointSprite_UpdateTeamRadar(other.waypointsprite_attachedforcarrier, RADARICON_FLAGCARRIER, '1 1 0'); + WaypointSprite_AttachCarrier("flagcarrier", other, RADARICON_FLAGCARRIER, '1 1 0'); } } -}; +} /*QUAKED spawnfunc_info_player_team1 (1 0 0) (-16 -16 -24) (16 16 24) CTF Starting point for a player @@ -653,8 +651,8 @@ void spawnfunc_info_player_team1() } self.team = COLOR_TEAM1; // red spawnfunc_info_player_deathmatch(); -}; -//self.team = 4;self.classname = "info_player_start";spawnfunc_info_player_start();}; +} +//self.team = 4;self.classname = "info_player_start";spawnfunc_info_player_start();} /*QUAKED spawnfunc_info_player_team2 (1 0 0) (-16 -16 -24) (16 16 24) CTF Starting point for a player in @@ -673,8 +671,8 @@ void spawnfunc_info_player_team2() } self.team = COLOR_TEAM2; // blue spawnfunc_info_player_deathmatch(); -}; -//self.team = 13;self.classname = "info_player_start";spawnfunc_info_player_start();}; +} +//self.team = 13;self.classname = "info_player_start";spawnfunc_info_player_start();} /*QUAKED spawnfunc_info_player_team3 (1 0 0) (-16 -16 -24) (16 16 24) CTF Starting point for a player in @@ -693,7 +691,7 @@ void spawnfunc_info_player_team3() } self.team = COLOR_TEAM3; // yellow spawnfunc_info_player_deathmatch(); -}; +} /*QUAKED spawnfunc_info_player_team4 (1 0 0) (-16 -16 -24) (16 16 24) @@ -713,7 +711,7 @@ void spawnfunc_info_player_team4() } self.team = COLOR_TEAM4; // purple spawnfunc_info_player_deathmatch(); -}; +} void item_flag_reset() { @@ -736,11 +734,11 @@ void item_flag_postspawn() if(self.team == COLOR_TEAM2) // Blue self.glow_color = 210; - + self.glow_size = 25; self.glow_trail = 1; } -}; +} /*QUAKED spawnfunc_item_flag_team1 (0 0.5 0.8) (-48 -48 -37) (48 48 37) CTF flag for team one (Red). @@ -767,6 +765,7 @@ Keys: (default ctf/respawn.wav) */ +void spawnfunc_item_flag_team2(); void spawnfunc_item_flag_team1() { if (!g_ctf) @@ -775,21 +774,22 @@ void spawnfunc_item_flag_team1() return; } + if (g_ctf_reverse) + { + float old_g_ctf_reverse = g_ctf_reverse; + g_ctf_reverse = 0; // avoid an endless loop + spawnfunc_item_flag_team2(); + g_ctf_reverse = old_g_ctf_reverse; + return; + } + // link flag into ctf_worldflaglist self.ctf_worldflagnext = ctf_worldflaglist; ctf_worldflaglist = self; self.classname = "item_flag_team"; - if(g_ctf_reverse) - { - self.team = COLOR_TEAM2; // color 13 team (blue) - self.items = IT_KEY1; // silver key (bluish enough) - } - else - { - self.team = COLOR_TEAM1; // color 4 team (red) - self.items = IT_KEY2; // gold key (redish enough) - } + self.team = COLOR_TEAM1; // color 4 team (red) + self.items = IT_KEY2; // gold key (redish enough) self.netname = "^1RED^7 flag"; self.target = "###item###"; self.skin = autocvar_g_ctf_flag_red_skin; @@ -838,7 +838,7 @@ void spawnfunc_item_flag_team1() precache_model("models/ctf/shockwavetransring.md3"); self.reset = item_flag_reset; -}; +} /*QUAKED spawnfunc_item_flag_team2 (0 0.5 0.8) (-48 -48 -24) (48 48 64) CTF flag for team two (Blue). @@ -873,21 +873,22 @@ void spawnfunc_item_flag_team2() return; } + if (g_ctf_reverse) + { + float old_g_ctf_reverse = g_ctf_reverse; + g_ctf_reverse = 0; // avoid an endless loop + spawnfunc_item_flag_team1(); + g_ctf_reverse = old_g_ctf_reverse; + return; + } + // link flag into ctf_worldflaglist self.ctf_worldflagnext = ctf_worldflaglist; ctf_worldflaglist = self; self.classname = "item_flag_team"; - if(g_ctf_reverse) - { - self.team = COLOR_TEAM1; // color 4 team (red) - self.items = IT_KEY2; // gold key (redish enough) - } - else - { - self.team = COLOR_TEAM2; // color 13 team (blue) - self.items = IT_KEY1; // silver key (bluish enough) - } + self.team = COLOR_TEAM2; // color 13 team (blue) + self.items = IT_KEY1; // silver key (bluish enough) self.netname = "^4BLUE^7 flag"; self.target = "###item###"; self.skin = autocvar_g_ctf_flag_blue_skin; @@ -936,7 +937,7 @@ void spawnfunc_item_flag_team2() precache_model("models/ctf/shockwavetransring.md3"); self.reset = item_flag_reset; -}; +} /*QUAKED spawnfunc_ctf_team (0 .5 .8) (-16 -16 -24) (16 16 32) @@ -963,12 +964,12 @@ void spawnfunc_ctf_team() } self.classname = "ctf_team"; self.team = self.cnt + 1; -}; +} // code from here on is just to support maps that don't have control point and team entities void ctf_spawnteam (string teamname, float teamcolor) { - local entity oldself; + entity oldself; oldself = self; self = spawn(); self.classname = "ctf_team"; @@ -978,7 +979,7 @@ void ctf_spawnteam (string teamname, float teamcolor) spawnfunc_ctf_team(); self = oldself; -}; +} // spawn some default teams if the map is not set up for ctf void ctf_spawnteams() @@ -989,7 +990,7 @@ void ctf_spawnteams() ctf_spawnteam("Red", COLOR_TEAM1 - 1); ctf_spawnteam("Blue", COLOR_TEAM2 - 1); -}; +} void ctf_delayedinit() { @@ -998,7 +999,7 @@ void ctf_delayedinit() ctf_spawnteams(); ScoreRules_ctf(); -}; +} void ctf_init() { @@ -1008,12 +1009,7 @@ void ctf_init() captureshield_min_negscore = autocvar_g_ctf_shield_min_negscore; captureshield_max_ratio = autocvar_g_ctf_shield_max_ratio; captureshield_force = autocvar_g_ctf_shield_force; - - -//#NO AUTOCVARS START - g_ctf_win_mode = cvar("g_ctf_win_mode"); -//#NO AUTOCVARS END -}; +} void ctf_setstatus2(entity flag, float shift) { @@ -1028,7 +1024,7 @@ void ctf_setstatus2(entity flag, float shift) { // no status bits } -}; +} void ctf_setstatus() { @@ -1038,7 +1034,7 @@ void ctf_setstatus() self.items &~= IT_BLUE_FLAG_LOST; self.items &~= IT_CTF_SHIELDED; - local entity flag; + entity flag; float redflags, blueflags; if(self.ctf_captureshielded) @@ -1074,32 +1070,32 @@ void ctf_setstatus() ctf_setstatus2(flag, IT_BLUE_FLAG_TAKEN); } } -}; +} /* -entity(float cteam) ctf_team_has_commander = +entity ctf_team_has_commander(float cteam) { entity pl; if(cteam != COLOR_TEAM1 || cteam != COLOR_TEAM2) return world; - + FOR_EACH_REALPLAYER(pl) { if(pl.team == cteam && pl.iscommander) { return pl; } } return world; -}; +} -void(entity e, float st) ctf_setstate = +void ctf_setstate(entity e, float st) { e.ctf_state = st; ++e.version; -}; +} -void(float cteam) ctf_new_commander = +void ctf_new_commander(float cteam) { entity pl, plmax; - + plmax = world; FOR_EACH_REALPLAYER(pl) { if(pl.team == cteam) { @@ -1119,25 +1115,25 @@ void(float cteam) ctf_new_commander = ctf_setstate(plmax, 3); sprint(plmax, "^3You're the commander now!\n"); centerprint(plmax, "^3You're the commander now!\n"); -}; +} -void() ctf_clientconnect = +void ctf_clientconnect() { self.iscommander = FALSE; - + if(!self.team || self.classname != "player") { ctf_setstate(self, -1); } else ctf_setstate(self, 0); self.team_saved = self.team; - + if(self.team != 0 && self.classname == "player" && !ctf_team_has_commander(self.team)) { ctf_new_commander(self.team); } -}; +} -void() ctf_playerchanged = +void ctf_playerchanged() { if(!self.team || self.classname != "player") { ctf_setstate(self, -1); @@ -1156,22 +1152,22 @@ void() ctf_playerchanged = ctf_setstate(self, -1); ctf_new_commander(self.team_saved); } - + self.team_saved = self.team; - + ctf_new_commander(self.team); -}; +} -void() ctf_clientdisconnect = +void ctf_clientdisconnect() { if(self.iscommander) { ctf_new_commander(self.team); } -}; +} entity GetPlayer(string); -float() ctf_clientcommand = +float ctf_clientcommand() { entity e; if(argv(0) == "order") { @@ -1212,5 +1208,5 @@ float() ctf_clientcommand = return TRUE; } return FALSE; -}; +} */ diff --git a/qcsrc/server/defs.qh b/qcsrc/server/defs.qh index 86a57d460b..865d39b10e 100644 --- a/qcsrc/server/defs.qh +++ b/qcsrc/server/defs.qh @@ -1,28 +1,27 @@ #define INDEPENDENT_ATTACK_FINISHED -float require_spawnfunc_prefix; // if this float exists, only functions with spawnfunc_ name prefix qualify as spawn functions - -#define BUTTON_ATCK button0 -#define BUTTON_JUMP button2 -#define BUTTON_ATCK2 button3 -#define BUTTON_ZOOM button4 -#define BUTTON_CROUCH button5 -#define BUTTON_HOOK button6 -#define BUTTON_INFO button7 -#define BUTTON_CHAT buttonchat -#define BUTTON_USE buttonuse -#define BUTTON_DRAG button8 +noref float require_spawnfunc_prefix; // if this float exists, only functions with spawnfunc_ name prefix qualify as spawn functions + +#define BUTTON_ATCK button0 +#define BUTTON_JUMP button2 +#define BUTTON_ATCK2 button3 +#define BUTTON_ZOOM button4 +#define BUTTON_CROUCH button5 +#define BUTTON_HOOK button6 +#define BUTTON_INFO button7 +#define BUTTON_CHAT buttonchat +#define BUTTON_USE buttonuse +#define BUTTON_DRAG button8 +#define BUTTON_ZOOMSCRIPT button9 // Globals float ctf_score_value(string parameter); -float g_dm, g_domination, g_ctf, g_tdm, g_keyhunt, g_onslaught, g_assault, g_arena, g_ca, g_lms, g_runematch, g_race, g_nexball, g_cts, g_freezetag, g_keepaway; float g_cloaked, g_footsteps, g_jump_grunt, g_grappling_hook, g_midair, g_minstagib, g_pinata, g_norecoil, g_minstagib_invis_alpha, g_bloodloss; float g_warmup_limit; float g_warmup_allguns; float g_warmup_allow_timeout; -float g_ctf_win_mode; float g_ctf_ignore_frags; float g_ctf_reverse; float g_race_qualifying; @@ -77,14 +76,13 @@ float maxclients; //.float style; //.float skill; .float sounds; +.float platmovetype; .string killtarget; .vector pos1, pos2; .vector mangle; -.float cvar_cl_hitsound; - .float pain_finished; //Added by Supajoe .float pain_frame; //" .float statdraintime; // record the one-second intervals between draining health and armour when they're over 100 @@ -106,8 +104,8 @@ float maxclients; //.float cnt2; .float play_time; +.float respawn_time; .float death_time; -.float dead_frame; .float fade_time; .float fade_rate; @@ -128,7 +126,7 @@ float maxclients; .vector anim_die1; // player dies .vector anim_die2; // player dies differently .vector anim_draw; // player pulls out a weapon -.vector anim_duck; // player crouches (from idle to duckidle) +// .vector anim_duck; // player crouches (from idle to duckidle) .vector anim_duckwalk; // player walking while crouching .vector anim_duckjump; // player jumping from a crouch .vector anim_duckidle; // player idling while crouching @@ -142,12 +140,21 @@ float maxclients; .vector anim_runbackwards; // player running backward .vector anim_strafeleft; // player shuffling left quickly .vector anim_straferight; // player shuffling right quickly -.vector anim_dead1; // player dead (must be identical to last frame of die1) -.vector anim_dead2; // player dead (must be identical to last frame of die2) +//.vector anim_dead1; // player dead (must be identical to last frame of die1) +//.vector anim_dead2; // player dead (must be identical to last frame of die2) .vector anim_forwardright; // player running forward and right .vector anim_forwardleft; // player running forward and left .vector anim_backright; // player running backward and right .vector anim_backleft; // player running back and left +.vector anim_melee; // player doing the melee action +.vector anim_duck; // player doing the melee action +.vector anim_duckwalkbackwards; +.vector anim_duckwalkstrafeleft; +.vector anim_duckwalkstraferight; +.vector anim_duckwalkforwardright; +.vector anim_duckwalkforwardleft; +.vector anim_duckwalkbackright; +.vector anim_duckwalkbackleft; // weapon animation vectors: .vector anim_fire1; @@ -170,6 +177,9 @@ void setanim(entity e, vector anim, float looping, float override, float restart //.float chasecam; .float damageforcescale; +#define MIN_DAMAGEEXTRARADIUS 2 +#define MAX_DAMAGEEXTRARADIUS 16 +.float damageextraradius; //.float gravity; @@ -188,6 +198,7 @@ void setanim(entity e, vector anim, float looping, float override, float restart .float watersound_finished; .float iscreature; +.float damagedbycontents; .vector oldvelocity; .float pauseregen_finished; @@ -201,7 +212,12 @@ void setanim(entity e, vector anim, float looping, float override, float restart .entity weaponentity; .entity exteriorweaponentity; .vector weaponentity_glowmod; -.float switchweapon; + +//.float weapon; // current weapon +.float switchweapon; // weapon requested to switch to +.float switchingweapon; // weapon currently being switched to (is copied from switchweapon once switch is possible) +.string weaponname; // name of .weapon + .float autoswitch; float weapon_action(float wpn, float wrequest); float client_hasweapon(entity cl, float wpn, float andammo, float complain); @@ -229,7 +245,6 @@ void weapon_defaultspawnfunc(float wpn); string w_deathtypestring; -void(entity client, string s) centerprint_builtin = #73; .vector dest1, dest2; float gameover; @@ -240,12 +255,14 @@ float alreadychangedlevel; .float runes; +// Keys player is holding +.float itemkeys; +// message delay for func_door locked by keys and key locks +// this field is used on player entities +.float key_door_messagetime; -.float welcomemessage_time; -.float version; -// minstagib vars -.float jump_interval; // laser refire +.float version; //swamp .float in_swamp; // bool @@ -254,11 +271,6 @@ float alreadychangedlevel; // footstep interval .float nextstep; -.float ready; -#define RESTART_COUNTDOWN 10 -float restart_mapalreadyrestarted; //bool, indicates whether reset_map() was already executed -entity restartTimer; -void restartTimer_Think(); float blockSpectators; //if set, new or existing spectators or observers will be removed unless they become a player within g_maxplayers_spectator_blocktime seconds .float spectatortime; //point in time since the client is spectating or observing void checkSpectatorBlock(); @@ -267,25 +279,9 @@ void checkSpectatorBlock(); .float jointime; // time of joining .float alivetime; // time of being alive -float isJoinAllowed(); +float nJoinAllowed(float includeMe); #define PREVENT_JOIN_TEXT "^1You may not join the game at this time.\n\nThe player limit reached maximum capacity." -//sv_timeout: pauses the game by setting the gamespeed to a really low value (see TIMEOUT_SLOWMO_VALUE) -#define TIMEOUT_SLOWMO_VALUE 0.0001 -float sys_frametime; // gets initialised in worlspawn, saves the value from autocvar_sys_ticrate -float remainingTimeoutTime; // contains the time in seconds that the active timeout has left -float remainingLeadTime; // contains the number of seconds left of the leadtime (before the timeout starts) -float timeoutStatus; // (values: 0, 1, 2) contains whether a timeout is not active (0), was called but still at leadtime (1) or is active (2) -.float allowedTimeouts; // contains the number of allowed timeouts for each player -entity timeoutInitiator; // contains the entity of the player who started the last timeout -float orig_slowmo; // contains the value of autocvar_slowmo so that, after timeout finished, it isn't set to slowmo 1 necessarily -.vector lastV_angle; //used when pausing the game in order to force the player to keep his old view angle fixed -entity timeoutHandler; //responsible for centerprinting the timeout countdowns and playing sounds -void timeoutHandler_Think(); -void evaluateTimeout(); -void evaluateTimein(); -string getTimeoutText(float addOneSecond); - .float spawnshieldtime; .float lms_nextcheck; @@ -309,9 +305,11 @@ float default_weapon_alpha; .float() customizeentityforclient; .float cvar_cl_handicap; -.float cvar_cl_playerdetailreduction; -.float cvar_scr_centertime; -.float cvar_cl_shownames; +.float cvar_cl_clippedspectating; +.float cvar_cl_autoscreenshot; +.float cvar_cl_movement_track_canjump; +.float cvar_cl_newusekeysupported; + .string cvar_g_xonoticversion; .string cvar_cl_weaponpriority; .string cvar_cl_weaponpriorities[10]; @@ -320,14 +318,13 @@ float default_weapon_alpha; .float cvar_cl_forceplayermodelsfromxonotic; float sv_clforceplayermodels; #endif -float sv_loddistance1; -float sv_loddistance2; .float cvar_cl_gunalign; .float cvar_cl_noantilag; .string weaponorder_byimpulse; .float cvar_cl_allow_uid2name; +.float cvar_cl_allow_uidtracking; .string stored_netname; void Announce(string snd); @@ -335,18 +332,11 @@ void AnnounceTo(entity e, string snd); .float version_nagtime; -.float modelindex_lod0; -.float modelindex_lod0_from_xonotic; -.float skinindex; -.float modelindex_lod1; -.float modelindex_lod2; - #define NUM_JUMPPADSUSED 3 .float jumppadcount; .entity jumppadsused[NUM_JUMPPADSUSED]; string gamemode_name; -float teams_matter; float startitem_failed; @@ -362,24 +352,11 @@ float W_AmmoItemCode(float wpn); float W_WeaponBit(float wpn); string W_Name(float weaponid); -void UpdateSelectedPlayer(); -void ClearSelectedPlayer(); -.entity selected_player; -.entity last_selected_player; -.float selected_player_time; // when this player has been selected -.float selected_player_count; // how long this player has been directly pointed to -.float selected_player_display_needs_update; // are regular updates necessary? (health) -.float selected_player_display_timeout; // when the selection will time out - void FixIntermissionClient(entity e); void FixClientCvars(entity e); float weaponsInMap; -void centerprint_atprio(entity e, float prio, string s); -void centerprint_expire(entity e, float prio); -void centerprint(entity e, string s); - .float respawn_countdown; // next number to count float bot_waypoints_for_items; @@ -399,13 +376,6 @@ float assault_attacker_team; // speedrun: when 1, player auto teleports back when capture timeout happens .float speedrunning; -// Q3 support -.float notteam; -.float notsingle; -.float notfree; -.float notq3a; -float q3acompat_machineshotgunswap; - // database float ServerProgsDB; float TemporaryDB; @@ -414,6 +384,7 @@ float TemporaryDB; float some_spawn_has_been_used; float have_team_spawns; // 0 = no team spawns requested, -1 = team spawns requested but none found, 1 = team spawns requested and found +float have_team_spawns_forteam[17]; // 0 = this team has no spawns, 1 = this team has spawns; team 0 is the "no-team" // set when showing a kill countdown .entity killindicator; @@ -427,7 +398,6 @@ float lockteams; float sv_maxidle; float sv_maxidle_spectatorsareidle; -float sv_pogostick; float tracebox_hits_trigger_hurt(vector start, vector mi, vector ma, vector end); float next_pingtime; @@ -440,18 +410,26 @@ float next_pingtime; // TODO implemented fall and falling #define ALLPLAYERSOUNDS \ _VOICEMSG(death) \ - _VOICEMSG(fall) \ _VOICEMSG(drown) \ + _VOICEMSG(fall) \ + _VOICEMSG(fall) \ + _VOICEMSG(falling) \ _VOICEMSG(gasp) \ _VOICEMSG(jump) \ + _VOICEMSG(pain100) \ _VOICEMSG(pain25) \ _VOICEMSG(pain50) \ - _VOICEMSG(pain75) \ - _VOICEMSG(pain100) + _VOICEMSG(pain75) + #define ALLVOICEMSGS \ _VOICEMSG(attack) \ _VOICEMSG(attackinfive) \ + _VOICEMSG(coverme) \ + _VOICEMSG(defend) \ + _VOICEMSG(freelance) \ + _VOICEMSG(incoming) \ _VOICEMSG(meet) \ + _VOICEMSG(needhelp) \ _VOICEMSG(seenflag) \ _VOICEMSG(taunt) \ _VOICEMSG(teamshoot) @@ -461,24 +439,18 @@ ALLPLAYERSOUNDS ALLVOICEMSGS #undef _VOICEMSG -// reserved sound names for the future (models lack sounds for them): +// reserved sound names for the future (some models lack sounds for them): +// _VOICEMSG(flagcarriertakingdamage) \ +// _VOICEMSG(getflag) \ +// reserved sound names for the future (ALL models lack sounds for them): // _VOICEMSG(affirmative) \ // _VOICEMSG(attacking) \ // _VOICEMSG(defending) \ // _VOICEMSG(roaming) \ // _VOICEMSG(onmyway) \ // _VOICEMSG(droppedflag) \ -// _VOICEMSG(flagcarriertakingdamage) \ // _VOICEMSG(negative) \ // _VOICEMSG(seenenemy) \ -// _VOICEMSG(fall) \ -// _VOICEMSG(getflag) \ -// _VOICEMSG(incoming) \ -// _VOICEMSG(coverme) \ -// _VOICEMSG(needhelp) \ -// _VOICEMSG(defend) \ -// _VOICEMSG(freelance) \ -// _VOICEMSG(falling) \ string globalsound_fall; string globalsound_metalfall; @@ -511,6 +483,7 @@ float GetPlayerSoundSampleField_notFound; .float version_mismatch; float independent_players; +#define INDEPENDENT_PLAYERS (autocvar__independent_players ? (autocvar__independent_players > 0) : independent_players) #define IS_INDEPENDENT_PLAYER(e) ((e).solid == SOLID_TRIGGER) #define MAKE_INDEPENDENT_PLAYER(e) (((e).solid = SOLID_TRIGGER) + ((e).frags = FRAGS_PLAYER_NONSOLID)) // we're using + here instead of , because fteqcc sucks @@ -555,6 +528,7 @@ void target_voicescript_clear(entity pl); .string target2; .string target3; .string target4; +.float target_random; .float trigger_reverse; // Nexball @@ -572,10 +546,6 @@ void ClientData_Touch(entity e); vector debug_shotorg; // if non-zero, overrides the shot origin of all weapons -// the QC VM sucks -#define BITXOR(v,b) ((v) + (b) - 2 * ((v) & (b))) -#define BITXOR_ASSIGN(v,b) ((v) += ((b) - 2 * ((v) & (b)))) - .float wasplayer; float servertime, serverprevtime, serverframetime; @@ -603,6 +573,9 @@ string matchid; .float last_pickup; +.float hit_time; +.float typehit_time; + .float stat_leadlimit; float radar_showennemies; @@ -612,7 +585,16 @@ float client_cefc_accumulator; float client_cefc_accumulatortime; #endif -.float campingrifle_bulletcounter; +..float current_ammo; + +.float weapon_load[WEP_MAXCOUNT]; +.float ammo_none; // used by the reloading system, must always be 0 +.float clip_load; +.float old_clip_load; +.float clip_size; +.float minelayer_mines; + +.float grab; // 0 = can't grab, 1 = owner can grab, 2 = owner and team mates can grab, 3 = anyone can grab #define PROJECTILE_MAKETRIGGER(e) (e).solid = SOLID_CORPSE; (e).dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE // when doing this, hagar can go through clones @@ -651,6 +633,8 @@ string deathmessage; .float nex_charge_rottime; .float nex_chargepool_ammo; +.float hagar_load; + float allowed_to_spawn; // boolean variable used by the clan arena code to determine if a player can spawn (after the round has ended) float serverflags; @@ -658,5 +642,14 @@ float serverflags; .float team_forced; // can be a team number to force a team, or 0 for default action, or -1 for forced spectator .float freezetag_frozen; -.float freezetag_beginrevive_time; .float freezetag_revive_progress; + +.entity muzzle_flash; +.float misc_bulletcounter; // replaces uzi & hlac bullet counter. + +void PlayerUseKey(); + +typedef vector(entity player, entity spot, vector current) spawn_evalfunc_t; +.spawn_evalfunc_t spawn_evalfunc; + +.entity conveyor; diff --git a/qcsrc/server/domination.qc b/qcsrc/server/domination.qc index 891863f97a..9e56023cb5 100644 --- a/qcsrc/server/domination.qc +++ b/qcsrc/server/domination.qc @@ -21,6 +21,28 @@ Note: The only teams who can use dom control points are identified by spawnfunc_ .entity sprite; .float captime; +// pps: points per second +.float dom_total_pps; +.float dom_pps_red; +.float dom_pps_blue; +.float dom_pps_yellow; +.float dom_pps_pink; +float total_pps; +float pps_red; +float pps_blue; +float pps_yellow; +float pps_pink; +void set_dom_state(entity e) +{ + e.dom_total_pps = total_pps; + e.dom_pps_red = pps_red; + e.dom_pps_blue = pps_blue; + if(c3 >= 0) + e.dom_pps_yellow = pps_yellow; + if(c4 >= 0) + e.dom_pps_pink = pps_pink; +} + void() dom_controlpoint_setup; void LogDom(string mode, float team_before, entity actor) @@ -38,8 +60,8 @@ void() dom_spawnteams; void dompoint_captured () { - local entity head; - local float old_delay, old_team, real_team; + entity head; + float old_delay, old_team, real_team; // now that the delay has expired, switch to the latest team to lay claim to this point head = self.owner; @@ -86,9 +108,9 @@ void dompoint_captured () if (head.noise != "") if(self.enemy) - sound(self.enemy, CHAN_AUTO, head.noise, VOL_BASE, ATTN_NORM); + sound(self.enemy, CH_TRIGGER, head.noise, VOL_BASE, ATTN_NORM); else - sound(self, CHAN_TRIGGER, head.noise, VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER, head.noise, VOL_BASE, ATTN_NORM); if (head.noise1 != "") play2all(head.noise1); @@ -120,13 +142,44 @@ void dompoint_captured () break; case COLOR_TEAM4: WaypointSprite_UpdateSprites(self.sprite, "dom-pink", "", ""); - break; } + + total_pps = 0, pps_red = 0, pps_blue = 0, pps_yellow = 0, pps_pink = 0; + for(head = world; (head = find(head, classname, "dom_controlpoint")) != world; ) + { + if (autocvar_g_domination_point_amt) + points = autocvar_g_domination_point_amt; + else + points = head.frags; + if (autocvar_g_domination_point_rate) + wait_time = autocvar_g_domination_point_rate; + else + wait_time = head.wait; + switch(head.goalentity.team) + { + case COLOR_TEAM1: + pps_red += points/wait_time; + break; + case COLOR_TEAM2: + pps_blue += points/wait_time; + break; + case COLOR_TEAM3: + pps_yellow += points/wait_time; + break; + case COLOR_TEAM4: + pps_pink += points/wait_time; + } + total_pps += points/wait_time; + } + WaypointSprite_UpdateTeamRadar(self.sprite, RADARICON_DOMPOINT, colormapPaletteColor(self.goalentity.team - 1, 0)); WaypointSprite_Ping(self.sprite); self.captime = time; -}; + + FOR_EACH_REALCLIENT(head) + set_dom_state(head); +} void AnimateDomPoint() { @@ -143,7 +196,7 @@ void AnimateDomPoint() void dompointthink() { - local float fragamt; + float fragamt; self.nextthink = time + 0.1; @@ -186,7 +239,7 @@ void dompointthink() void dompointtouch() { - local entity head; + entity head; if (other.classname != "player") return; if (other.health < 1) @@ -234,7 +287,7 @@ void dompointtouch() self.enemy = other; // individual player scoring self.enemy_playerid = other.playerid; dompoint_captured(); -}; +} /*QUAKED spawnfunc_dom_team (0 .5 .8) (-32 -32 -24) (32 32 32) Team declaration for Domination gameplay, this allows you to decide what team @@ -283,11 +336,11 @@ void spawnfunc_dom_team() // this would have to be changed if used in quakeworld if(self.cnt) self.team = self.cnt + 1; // WHY are these different anyway? -}; +} void dom_controlpoint_setup() { - local entity head; + entity head; // find the spawnfunc_dom_team representing unclaimed points head = find(world, classname, "dom_team"); while(head && head.netname != "") @@ -305,11 +358,23 @@ void dom_controlpoint_setup() if(!self.message) self.message = " has captured a control point"; - if(!self.DOMPOINTFRAGS) + if(self.DOMPOINTFRAGS <= 0) self.DOMPOINTFRAGS = 1; - if(!self.wait) + if(self.wait <= 0) self.wait = 5; + float points, waittime; + if (autocvar_g_domination_point_amt) + points = autocvar_g_domination_point_amt; + else + points = self.frags; + if (autocvar_g_domination_point_rate) + waittime = autocvar_g_domination_point_rate; + else + waittime = self.wait; + + total_pps += points/waittime; + if(!self.t_width) self.t_width = 0.02; // frame animation rate if(!self.t_length) @@ -325,9 +390,8 @@ void dom_controlpoint_setup() droptofloor(); waypoint_spawnforitem(self); - WaypointSprite_SpawnFixed("dom-neut", self.origin + '0 0 32', self, sprite); - WaypointSprite_UpdateTeamRadar(self.sprite, RADARICON_DOMPOINT, '0 1 1'); -}; + WaypointSprite_SpawnFixed("dom-neut", self.origin + '0 0 32', self, sprite, RADARICON_DOMPOINT, '0 1 1'); +} @@ -543,12 +607,12 @@ void spawnfunc_dom_controlpoint() self.effects = self.effects | EF_LOWPRECISION; if (autocvar_g_domination_point_fullbright) self.effects |= EF_FULLBRIGHT; -}; +} // code from here on is just to support maps that don't have control point and team entities void dom_spawnteam (string teamname, float teamcolor, string pointmodel, float pointskin, string capsound, string capnarration, string capmessage) { - local entity oldself; + entity oldself; oldself = self; self = spawn(); self.classname = "dom_team"; @@ -571,11 +635,11 @@ void dom_spawnteam (string teamname, float teamcolor, string pointmodel, float p //eprint(self); self = oldself; -}; +} void dom_spawnpoint(vector org) { - local entity oldself; + entity oldself; oldself = self; self = spawn(); self.classname = "dom_controlpoint"; @@ -584,7 +648,7 @@ void dom_spawnpoint(vector org) setorigin(self, org); spawnfunc_dom_controlpoint(); self = oldself; -}; +} // spawn some default teams if the map is not set up for domination void dom_spawnteams() @@ -602,11 +666,11 @@ void dom_spawnteams() if(numteams > 3) dom_spawnteam("Pink", COLOR_TEAM4-1, "models/domination/dom_pink.md3", 0, "domination/claim.wav", "", "Pink team has captured a control point"); dom_spawnteam("", 0, "models/domination/dom_unclaimed.md3", 0, "", "", ""); -}; +} void dom_delayedinit() { - local entity head; + entity head; // if no teams are found, spawn defaults, if custom teams are set, use them if (find(world, classname, "dom_team") == world || autocvar_g_domination_teams_override >= 2) @@ -614,27 +678,20 @@ void dom_delayedinit() // if no control points are found, spawn defaults if (find(world, classname, "dom_controlpoint") == world) { - // here follow default domination points for each map - /* - if (world.model == "maps/e1m1.bsp") + // TODO in a few months (maybe 2011/08): change this into error() and remove this very poor dom point selection + backtrace("This map contains no dom_controlpoint entities. A very poor dom point placement will be chosen. Please fix the map."); + + // if no supported map was found, make every deathmatch spawn a point + head = find(world, classname, "info_player_deathmatch"); + while (head) { - dom_spawnpoint('0 0 0'); - } - else - */ - { - // if no supported map was found, make every deathmatch spawn a point - head = find(world, classname, "info_player_deathmatch"); - while (head) - { - dom_spawnpoint(head.origin); - head = find(head, classname, "info_player_deathmatch"); - } + dom_spawnpoint(head.origin); + head = find(head, classname, "info_player_deathmatch"); } } ScoreRules_dom(); -}; +} void dom_init() { @@ -648,5 +705,11 @@ void dom_init() precache_model("models/domination/dom_unclaimed.md3"); precache_sound("domination/claim.wav"); InitializeEntity(world, dom_delayedinit, INITPRIO_GAMETYPE); -}; + + addstat(STAT_DOM_TOTAL_PPS, AS_FLOAT, dom_total_pps); + addstat(STAT_DOM_PPS_RED, AS_FLOAT, dom_pps_red); + addstat(STAT_DOM_PPS_BLUE, AS_FLOAT, dom_pps_blue); + if(c3 >= 0) addstat(STAT_DOM_PPS_YELLOW, AS_FLOAT, dom_pps_yellow); + if(c4 >= 0) addstat(STAT_DOM_PPS_PINK, AS_FLOAT, dom_pps_pink); +} diff --git a/qcsrc/server/ent_cs.qc b/qcsrc/server/ent_cs.qc index bee79d682e..af9a73ecae 100644 --- a/qcsrc/server/ent_cs.qc +++ b/qcsrc/server/ent_cs.qc @@ -18,7 +18,7 @@ void entcs_init() { print("Initializing ClientSide information entities\n"); -}; +} float entcs_customize() { @@ -30,8 +30,8 @@ float entcs_customize() return FALSE; if(other == o) return FALSE; - if(other.classname == "player") - if(o.team != other.team) + if((other.classname == "player") || other.caplayer) + if(!teamplay || o.team != other.team) if not (radar_showennemies) return FALSE; return TRUE; @@ -39,35 +39,57 @@ float entcs_customize() float entcs_send(entity to, float sf) { - entity o; - o = self.owner; WriteByte(MSG_ENTITY, ENT_CLIENT_ENTCS); - WriteByte(MSG_ENTITY, num_for_edict(o)); - WriteShort(MSG_ENTITY, o.origin_x); - WriteShort(MSG_ENTITY, o.origin_y); - WriteShort(MSG_ENTITY, o.origin_z); - WriteByte(MSG_ENTITY, o.angles_y * 256.0 / 360); + WriteByte(MSG_ENTITY, sf); + if(sf & 1) + WriteByte(MSG_ENTITY, num_for_edict(self.owner)-1); + if(sf & 2) + { + WriteShort(MSG_ENTITY, self.origin_x); + WriteShort(MSG_ENTITY, self.origin_y); + WriteShort(MSG_ENTITY, self.origin_z); + } + if(sf & 4) + WriteByte(MSG_ENTITY, self.angles_y * 256.0 / 360); + if(sf & 8) + WriteByte(MSG_ENTITY, self.health / 10); // FIXME use a better scale? + if(sf & 16) + WriteByte(MSG_ENTITY, self.armorvalue / 10); // FIXME use a better scale? return TRUE; -}; +} void entcs_think() { - self.nextthink = time; + self.nextthink = time + 0.033333333333; // increase this to like 0.15 once the client can do smoothing entity o; o = self.owner; - if(o.origin != self.origin || o.angles != self.angles) + if(o.origin != self.origin) { setorigin(self, o.origin); + self.SendFlags |= 2; + } + if(o.angles_y != self.angles_y) + { self.angles = o.angles; - self.SendFlags |= 1; + self.SendFlags |= 4; } -}; + if(o.health != self.health) + { + self.health = o.health; + self.SendFlags |= 8; + } + if(o.armorvalue != self.armorvalue) + { + self.armorvalue = o.armorvalue; + self.SendFlags |= 16; + } +} entity attach_entcs() { - local entity ent; + entity ent; ent = spawn(); ent.classname = "entcs_sender_v2"; @@ -81,10 +103,10 @@ entity attach_entcs() self.entcs = ent; return ent; -}; +} void detach_entcs() { remove(self.entcs); self.entcs = world; -}; +} diff --git a/qcsrc/server/extensions.qh b/qcsrc/server/extensions.qh deleted file mode 100644 index afe67c9b5b..0000000000 --- a/qcsrc/server/extensions.qh +++ /dev/null @@ -1,2407 +0,0 @@ - -//DarkPlaces supported extension list, draft version 1.04 - -//things that don't have extensions yet: -.float disableclientprediction; - -//definitions that id Software left out: -//these are passed as the 'nomonsters' parameter to traceline/tracebox (yes really this was supported in all quake engines, nomonsters is misnamed) -float MOVE_NORMAL = 0; // same as FALSE -float MOVE_NOMONSTERS = 1; // same as TRUE -float MOVE_MISSILE = 2; // save as movement with .movetype == MOVETYPE_FLYMISSILE - -//checkextension function -//idea: expected by almost everyone -//darkplaces implementation: LordHavoc -float(string s) checkextension = #99; -//description: -//check if (cvar("pr_checkextension")) before calling this, this is the only -//guaranteed extension to be present in the extension system, it allows you -//to check if an extension is available, by name, to check for an extension -//use code like this: -//// (it is recommended this code be placed in worldspawn or a worldspawn called function somewhere) -//if (cvar("pr_checkextension")) -//if (checkextension("DP_SV_SETCOLOR")) -// ext_setcolor = TRUE; -//from then on you can check ext_setcolor to know if that extension is available - -//BX_WAL_SUPPORT -//idea: id Software -//darkplaces implementation: LordHavoc -//description: -//indicates the engine supports .wal textures for filenames in the textures/ directory -//(note: DarkPlaces has supported this since 2001 or 2002, but did not advertise it as an extension, then I noticed Betwix was advertising it and added the extension accordingly) - -//DP_BUTTONCHAT -//idea: Vermeulen -//darkplaces implementation: LordHavoc -//field definitions: -.float buttonchat; -//description: -//true if the player is currently chatting (in messagemode, menus or console) - -//DP_BUTTONUSE -//idea: id Software -//darkplaces implementation: LordHavoc -//field definitions: -.float buttonuse; -//client console commands: -//+use -//-use -//description: -//made +use and -use commands work, they now control the .buttonuse field (.button1 was used by many mods for other purposes). - -//DP_CL_LOADSKY -//idea: Nehahra, LordHavoc -//darkplaces implementation: LordHavoc -//client console commands: -//"loadsky" (parameters: "basename", example: "mtnsun_" would load "mtnsun_up.tga" and "mtnsun_rt.tga" and similar names, use "" to revert to quake sky, note: this is the same as Quake2 skybox naming) -//description: -//sets global skybox for the map for this client (can be stuffed to a client by QC), does not hurt much to repeatedly execute this command, please don't use this in mods if it can be avoided (only if changing skybox is REALLY needed, otherwise please use DP_GFX_SKYBOX). - -//DP_CON_SET -//idea: id Software -//darkplaces implementation: LordHavoc -//description: -//indicates this engine supports the "set" console command which creates or sets a non-archived cvar (not saved to config.cfg on exit), it is recommended that set and seta commands be placed in default.cfg for mod-specific cvars. - -//DP_CON_SETA -//idea: id Software -//darkplaces implementation: LordHavoc -//description: -//indicates this engine supports the "seta" console command which creates or sets an archived cvar (saved to config.cfg on exit), it is recommended that set and seta commands be placed in default.cfg for mod-specific cvars. - -//DP_CON_ALIASPARAMETERS -//idea: many -//darkplaces implementation: Black -//description: -//indicates this engine supports aliases containing $1 through $9 parameter macros (which when called will expand to the parameters passed to the alias, for example alias test "say $2 $1", then you can type test hi there and it will execute say there hi), as well as $0 (name of the alias) and $* (all parameters $1 onward). - -//DP_CON_EXPANDCVAR -//idea: many, PHP -//darkplaces implementation: Black -//description: -//indicates this engine supports console commandlines containing $cvarname which will expand to the contents of that cvar as a parameter, for instance say my fov is $fov, will say "my fov is 90", or similar. - -//DP_CON_STARTMAP -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//description: -//adds two engine-called aliases named startmap_sp and startmap_dm which are called when the engine tries to start a singleplayer game from the menu (startmap_sp) or the -listen or -dedicated options are used or the engine is a dedicated server (uses startmap_dm), these allow a mod or game to specify their own map instead of start, and also distinguish between singleplayer and -listen/-dedicated, also these need not be a simple "map start" command, they can do other things if desired, startmap_sp and startmap_dm both default to "map start". - -//DP_EF_ADDITIVE -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//effects bit: -float EF_ADDITIVE = 32; -//description: -//additive blending when this object is rendered - -//DP_EF_BLUE -//idea: id Software -//darkplaces implementation: LordHavoc -//effects bit: -float EF_BLUE = 64; -//description: -//entity emits blue light (used for quad) - -//DP_EF_DOUBLESIDED -//idea: LordHavoc -//darkplaces implementation: [515] and LordHavoc -//effects bit: -float EF_DOUBLESIDED = 32768; -//description: -//render entity as double sided (backfaces are visible, I.E. you see the 'interior' of the model, rather than just the front), can be occasionally useful on transparent stuff. - -//DP_EF_FLAME -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//effects bit: -float EF_FLAME = 1024; -//description: -//entity is on fire - -//DP_EF_FULLBRIGHT -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//effects bit: -float EF_FULLBRIGHT = 512; -//description: -//entity is always brightly lit - -//DP_EF_NODEPTHTEST -//idea: Supa -//darkplaces implementation: LordHavoc -//effects bit: -float EF_NODEPTHTEST = 8192; -//description: -//makes entity show up to client even through walls, useful with EF_ADDITIVE for special indicators like where team bases are in a map, so that people don't get lost - -//DP_EF_NODRAW -//idea: id Software -//darkplaces implementation: LordHavoc -//effects bit: -float EF_NODRAW = 16; -//description: -//prevents server from sending entity to client (forced invisible, even if it would have been a light source or other such things) - -//DP_EF_NOGUNBOB -//idea: Chris Page, Dresk -//darkplaces implementation: LordHAvoc -//effects bit: -float EF_NOGUNBOB = 256; -//description: -//this has different meanings depending on the entity it is used on: -//player entity - prevents gun bobbing on player.viewmodel -//viewmodelforclient entity - prevents gun bobbing on an entity attached to the player's view -//other entities - no effect -//uses: -//disabling gun bobbing on a diving mask or other model used as a .viewmodel. -//disabling gun bobbing on view-relative models meant to be part of the heads up display. (note: if fov is changed these entities may be off-screen, or too near the center of the screen, so use fov 90 in this case) - -//DP_EF_NOSHADOW -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//effects bit: -float EF_NOSHADOW = 4096; -//description: -//realtime lights will not cast shadows from this entity (but can still illuminate it) - -//DP_EF_RED -//idea: id Software -//darkplaces implementation: LordHavoc -//effects bit: -float EF_RED = 128; -//description: -//entity emits red light (used for invulnerability) - -//DP_EF_RESTARTANIM_BIT -//idea: id software -//darkplaces implementation: divVerent -//effects bit: -float EF_RESTARTANIM_BIT = 1048576; -//description: -//when toggled, the current animation is restarted. Useful for weapon animation. -//to toggle this bit in QC, you can do: -// self.effects += (EF_RESTARTANIM_BIT - 2 * (self.effects & EF_RESTARTANIM_BIT)); - -//DP_EF_STARDUST -//idea: MythWorks Inc -//darkplaces implementation: LordHavoc -//effects bit: -float EF_STARDUST = 2048; -//description: -//entity emits bouncing sparkles in every direction - -//DP_EF_TELEPORT_BIT -//idea: id software -//darkplaces implementation: divVerent -//effects bit: -float EF_TELEPORT_BIT = 2097152; -//description: -//when toggled, interpolation of the entity is skipped for one frame. Useful for teleporting. -//to toggle this bit in QC, you can do: -// self.effects += (EF_TELEPORT_BIT - 2 * (self.effects & EF_TELEPORT_BIT)); - -//DP_ENT_ALPHA -//idea: Nehahra -//darkplaces implementation: LordHavoc -//fields: -.float alpha; -//description: -//controls opacity of the entity, 0.0 is forced to be 1.0 (otherwise everything would be invisible), use -1 if you want to make something invisible, 1.0 is solid (like normal). - -//DP_ENT_COLORMOD -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//field definition: -.vector colormod; -//description: -//controls color of the entity, '0 0 0', is forced to be '1 1 1' (otherwise everything would be black), used for tinting objects, for instance using '1 0.6 0.4' on an ogre would give you an orange ogre (order is red green blue), note the colors can go up to '8 8 8' (8x as bright as normal). - -//DP_ENT_CUSTOMCOLORMAP -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//description: -//if .colormap is set to 1024 + pants + shirt * 16, those colors will be used for colormapping the entity, rather than looking up a colormap by player number. - -/* -//NOTE: no longer supported by darkplaces because all entities are delta compressed now -//DP_ENT_DELTACOMPRESS // no longer supported -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//effects bit: -float EF_DELTA = 8388608; -//description: -//(obsolete) applies delta compression to the network updates of the entity, making updates smaller, this might cause some unreliable behavior in packet loss situations, so it should only be used on numerous (nails/plasma shots/etc) or unimportant objects (gibs/shell casings/bullet holes/etc). -*/ - -//DP_ENT_EXTERIORMODELTOCLIENT -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//fields: -.entity exteriormodeltoclient; -//description: -//the entity is visible to all clients with one exception: if the specified client is using first person view (not using chase_active) the entity will not be shown. Also if tag attachments are supported any entities attached to the player entity will not be drawn in first person. - -//DP_ENT_GLOW -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//field definitions: -.float glow_color; -.float glow_size; -.float glow_trail; -//description: -//customizable glowing light effect on the entity, glow_color is a paletted (8bit) color in the range 0-255 (note: 0 and 254 are white), glow_size is 0 or higher (up to the engine what limit to cap it to, darkplaces imposes a 1020 limit), if glow_trail is true it will leave a trail of particles of the same color as the light. - -//DP_ENT_GLOWMOD -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//field definition: -.vector glowmod; -//description: -//controls color of the entity's glow texture (fullbrights), '0 0 0', is forced to be '1 1 1' (otherwise everything would be black), used for tinting objects, see colormod (same color restrictions apply). - -//DP_ENT_LOWPRECISION -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//effects bit: -float EF_LOWPRECISION = 4194304; -//description: -//uses low quality origin coordinates, reducing network traffic compared to the default high precision, intended for numerous objects (projectiles/gibs/bullet holes/etc). - -//DP_ENT_SCALE -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//field definitions: -.float scale; -//description: -//controls rendering scale of the object, 0 is forced to be 1, darkplaces uses 1/16th accuracy and a limit of 15.9375, can be used to make an object larger or smaller. - -//DP_ENT_VIEWMODEL -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//field definitions: -.entity viewmodelforclient; -//description: -//this is a very special capability, attachs the entity to the view of the client specified, origin and angles become relative to the view of that client, all effects can be used (multiple skins on a weapon model etc)... the entity is not visible to any other client. - -//DP_GECKO_SUPPORT -//idea: Res2k, BlackHC -//darkplaces implementation: Res2k, BlackHC -//constant definitions: -float GECKO_BUTTON_DOWN = 0; -float GECKO_BUTTON_UP = 1; -// either use down and up or just press but not all of them! -float GECKO_BUTTON_PRESS = 2; -// use this for mouse events if needed? -float GECKO_BUTTON_DOUBLECLICK = 3; -//builtin definitions: -float(string name) gecko_create( string name ) = #487; -void(string name) gecko_destroy( string name ) = #488; -void(string name) gecko_navigate( string name, string URI ) = #489; -float(string name) gecko_keyevent( string name, float key, float eventtype ) = #490; -void gecko_mousemove( string name, float x, float y ) = #491; -void gecko_resize( string name, float w, float h ) = #492; -vector gecko_get_texture_extent( string name ) = #493; -//engine-called QC prototypes: -//string(string name, string query) Qecko_Query; -//description: -//provides an interface to the offscreengecko library and allows for internet browsing in games - -//DP_GFX_EXTERNALTEXTURES -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//description: -//loads external textures found in various directories (tenebrae compatible)... -/* -in all examples .tga is merely the base texture, it can be any of these: -.tga (base texture) -_glow.tga (fullbrights or other glowing overlay stuff, NOTE: this is done using additive blend, not alpha) -_pants.tga (pants overlay for colormapping on models, this should be shades of grey (it is tinted by pants color) and black wherever the base texture is not black, as this is an additive blend) -_shirt.tga (same idea as pants, but for shirt color) -_diffuse.tga (this may be used instead of base texture for per pixel lighting) -_gloss.tga (specular texture for per pixel lighting, note this can be in color (tenebrae only supports greyscale)) -_norm.tga (normalmap texture for per pixel lighting) -_bump.tga (bumpmap, converted to normalmap at load time, supported only for reasons of tenebrae compatibility) -_luma.tga (same as _glow but supported only for reasons of tenebrae compatibility) - -due to glquake's incomplete Targa(r) loader, this section describes -required Targa(r) features support: -types: -type 1 (uncompressed 8bit paletted with 24bit/32bit palette) -type 2 (uncompressed 24bit/32bit true color, glquake supported this) -type 3 (uncompressed 8bit greyscale) -type 9 (RLE compressed 8bit paletted with 24bit/32bit palette) -type 10 (RLE compressed 24bit/32bit true color, glquake supported this) -type 11 (RLE compressed 8bit greyscale) -attribute bit 0x20 (Origin At Top Left, top to bottom, left to right) - -image formats guaranteed to be supported: tga, pcx, lmp -image formats that are optional: png, jpg - -mdl/spr/spr32 examples: -skins are named _A (A being a number) and skingroups are named like _A_B -these act as suffixes on the model name... -example names for skin _2_1 of model "progs/armor.mdl": -game/override/progs/armor.mdl_2_1.tga -game/textures/progs/armor.mdl_2_1.tga -game/progs/armor.mdl_2_1.tga -example names for skin _0 of the model "progs/armor.mdl": -game/override/progs/armor.mdl_0.tga -game/textures/progs/armor.mdl_0.tga -game/progs/armor.mdl_0.tga -note that there can be more skins files (of the _0 naming) than the mdl -contains, this is only useful to save space in the .mdl file if classic quake -compatibility is not a concern. - -bsp/md2/md3 examples: -example names for the texture "quake" of model "maps/start.bsp": -game/override/quake.tga -game/textures/quake.tga -game/quake.tga - -sbar/menu/console textures: for example the texture "conchars" (console font) in gfx.wad -game/override/gfx/conchars.tga -game/textures/gfx/conchars.tga -game/gfx/conchars.tga -*/ - -//DP_GFX_EXTERNALTEXTURES_PERMAPTEXTURES -//idea: Fuh? -//darkplaces implementation: LordHavoc -//description: -//Q1BSP and HLBSP map loading loads external textures found in textures/<mapname>/ as well as textures/. -//Where mapname is the bsp filename minus the extension (typically .bsp) and minus maps/ if it is in maps/ (any other path is not removed) -//example: -//maps/e1m1.bsp uses textures in the directory textures/e1m1/ and falls back to textures/ -//maps/b_batt0.bsp uses textures in the directory textures/b_batt0.bsp and falls back to textures/ -//as a more extreme example: -//progs/something/blah.bsp uses textures in the directory textures/progs/something/blah/ and falls back to textures/ - -//DP_GFX_FOG -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//worldspawn fields: -//"fog" (parameters: "density red green blue", example: "0.1 0.3 0.3 0.3") -//description: -//global fog for the map, can not be changed by QC - -//DP_GFX_QUAKE3MODELTAGS -//idea: id Software -//darkplaces implementation: LordHavoc -//field definitions: -.entity tag_entity; // entity this is attached to (call setattachment to set this) -.float tag_index; // which tag on that entity (0 is relative to the entity, > 0 is an index into the tags on the model if it has any) (call setattachment to set this) -//builtin definitions: -void(entity e, entity tagentity, string tagname) setattachment = #443; // attachs e to a tag on tagentity (note: use "" to attach to entity origin/angles instead of a tag) -//description: -//allows entities to be visually attached to model tags (which follow animations perfectly) on other entities, for example attaching a weapon to a player's hand, or upper body attached to lower body, allowing it to change angles and frame separately (note: origin and angles are relative to the tag, use '0 0 0' for both if you want it to follow exactly, this is similar to viewmodelforclient's behavior). -//note 2: if the tag is not found, it defaults to "" (attach to origin/angles of entity) -//note 3: attaching to world turns off attachment -//note 4: the entity that this is attached to must be visible for this to work -//note 5: if an entity is attached to the player entity it will not be drawn in first person. - -//DP_GFX_SKINFILES -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//description: -//alias models (mdl, md2, md3) can have .skin files to replace conventional texture naming, these have a naming format such as: -//progs/test.md3_0.skin -//progs/test.md3_1.skin -//... -// -//these files contain replace commands (replace meshname shadername), example: -//replace "helmet" "progs/test/helmet1.tga" // this is a mesh shader replacement -//replace "teamstripes" "progs/test/redstripes.tga" -//replace "visor" "common/nodraw" // this makes the visor mesh invisible -////it is not possible to rename tags using this format -// -//Or the Quake3 syntax (100% compatible with Quake3's .skin files): -//helmet,progs/test/helmet1.tga // this is a mesh shader replacement -//teamstripes,progs/test/redstripes.tga -//visor,common/nodraw // this makes the visor mesh invisible -//tag_camera, // this defines that the first tag in the model is called tag_camera -//tag_test, // this defines that the second tag in the model is called tag_test -// -//any names that are not replaced are automatically show up as a grey checkerboard to indicate the error status, and "common/nodraw" is a special case that is invisible. -//this feature is intended to allow multiple skin sets on md3 models (which otherwise only have one skin set). -//other commands might be added someday but it is not expected. - -//DP_GFX_SKYBOX -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//worldspawn fields: -//"sky" (parameters: "basename", example: "mtnsun_" would load "mtnsun_up.tga" and "mtnsun_rt.tga" and similar names, note: "sky" is also used the same way by Quake2) -//description: -//global skybox for the map, can not be changed by QC - -//DP_UTF8 -//idea: Blub\0, divVerent -//darkplaces implementation: Blub\0 -//cvar definitions: -// utf8_enable: enable utf8 encoding -//description: utf8 characters are allowed inside cvars, protocol strings, files, progs strings, etc., -//and count as 1 char for string functions like strlen, substring, etc. -// note: utf8_enable is run-time cvar, could be changed during execution -// note: beware that str2chr() could return value bigger than 255 once utf8 is enabled - -//DP_HALFLIFE_MAP -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//description: -//simply indicates that the engine supports HalfLife maps (BSP version 30, NOT the QER RGBA ones which are also version 30). - -//DP_HALFLIFE_MAP_CVAR -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//cvars: -//halflifebsp 0/1 -//description: -//engine sets this cvar when loading a map to indicate if it is halflife format or not. - -//DP_HALFLIFE_SPRITE -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//description: -//simply indicates that the engine supports HalfLife sprites. - -//DP_INPUTBUTTONS -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//field definitions: -.float button3; -.float button4; -.float button5; -.float button6; -.float button7; -.float button8; -//description: -//set to the state of the +button3, +button4, +button5, +button6, +button7, and +button8 buttons from the client, this does not involve protocol changes (the extra 6 button bits were simply not used). -//the exact mapping of protocol button bits on the server is: -//self.button0 = (bits & 1) != 0; -///* button1 is skipped because mods abuse it as a variable, and accordingly it has no bit */ -//self.button2 = (bits & 2) != 0; -//self.button3 = (bits & 4) != 0; -//self.button4 = (bits & 8) != 0; -//self.button5 = (bits & 16) != 0; -//self.button6 = (bits & 32) != 0; -//self.button7 = (bits & 64) != 0; -//self.button8 = (bits & 128) != 0; - -// DP_LIGHTSTYLE_STATICVALUE -// idea: VorteX -// darkplaces implementation: VorteX -// description: allows alternative 'static' lightstyle syntax : "=value" -// examples: "=0.5", "=2.0", "=2.75" -// could be used to control switchable lights or making styled lights with brightness > 2 -// Warning: this extension is experimental. It safely works in CSQC, but SVQC use is limited by the fact -// that other engines (which do not support this extension) could connect to a game and misunderstand this kind of lightstyle syntax - -//DP_LITSPRITES -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//description: -//indicates this engine supports lighting on sprites, any sprite with ! in its filename (both on disk and in the qc) will be lit rather than having forced EF_FULLBRIGHT (EF_FULLBRIGHT on the entity can still force these sprites to not be lit). - -//DP_LITSUPPORT -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//description: -//indicates this engine loads .lit files for any quake1 format .bsp files it loads to enhance maps with colored lighting. -//implementation description: these files begin with the header QLIT followed by version number 1 (as little endian 32bit), the rest of the file is a replacement lightmaps lump, except being 3x as large as the lightmaps lump of the map it matches up with (and yes the between-lightmap padding is expanded 3x to keep this consistent), so the lightmap offset in each surface is simply multiplied by 3 during loading to properly index the lit data, and the lit file is loaded instead of the lightmap lump, other renderer changes are needed to display these of course... see the litsupport.zip sample code (almost a tutorial) at http://icculus.org/twilight/darkplaces for more information. - -//DP_MONSTERWALK -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//description: -//MOVETYPE_WALK is permitted on non-clients, so bots can move smoothly, run off ledges, etc, just like a real player. - -//DP_MOVETYPEBOUNCEMISSILE -//idea: id Software -//darkplaces implementation: id Software -//movetype definitions: -//float MOVETYPE_BOUNCEMISSILE = 11; // already in defs.qc -//description: -//MOVETYPE_BOUNCE but without gravity, and with full reflection (no speed loss like grenades have), in other words - bouncing laser bolts. - -//DP_NULL_MODEL -//idea: Chris -//darkplaces implementation: divVerent -//definitions: -//string dp_null_model = "null"; -//description: -//setmodel(e, "null"); makes an entity invisible, have a zero bbox, but -//networked. useful for shared CSQC entities. - -//DP_MOVETYPEFOLLOW -//idea: id Software, LordHavoc (redesigned) -//darkplaces implementation: LordHavoc -//movetype definitions: -float MOVETYPE_FOLLOW = 12; -//description: -//MOVETYPE_FOLLOW implemented, this uses existing entity fields in unusual ways: -//aiment - the entity this is attached to. -//punchangle - the original angles when the follow began. -//view_ofs - the relative origin (note that this is un-rotated by punchangle, and that is actually the only purpose of punchangle). -//v_angle - the relative angles. -//here's an example of how you would set a bullet hole sprite to follow a bmodel it was created on, even if the bmodel rotates: -//hole.movetype = MOVETYPE_FOLLOW; // make the hole follow -//hole.solid = SOLID_NOT; // MOVETYPE_FOLLOW is always non-solid -//hole.aiment = bmodel; // make the hole follow bmodel -//hole.punchangle = bmodel.angles; // the original angles of bmodel -//hole.view_ofs = hole.origin - bmodel.origin; // relative origin -//hole.v_angle = hole.angles - bmodel.angles; // relative angles - -//DP_QC_ASINACOSATANATAN2TAN -//idea: Urre -//darkplaces implementation: LordHavoc -//constant definitions: -float DEG2RAD = 0.0174532925199432957692369076848861271344287188854172545609719144; -float RAD2DEG = 57.2957795130823208767981548141051703324054724665643215491602438612; -float PI = 3.1415926535897932384626433832795028841971693993751058209749445923; -//builtin definitions: -float(float s) asin = #471; // returns angle in radians for a given sin() value, the result is in the range -PI*0.5 to PI*0.5 -float(float c) acos = #472; // returns angle in radians for a given cos() value, the result is in the range 0 to PI -float(float t) atan = #473; // returns angle in radians for a given tan() value, the result is in the range -PI*0.5 to PI*0.5 -float(float c, float s) atan2 = #474; // returns angle in radians for a given cos() and sin() value pair, the result is in the range -PI to PI (this is identical to vectoyaw except it returns radians rather than degrees) -float(float a) tan = #475; // returns tangent value (which is simply sin(a)/cos(a)) for the given angle in radians, the result is in the range -infinity to +infinity -//description: -//useful math functions for analyzing vectors, note that these all use angles in radians (just like the cos/sin functions) not degrees unlike makevectors/vectoyaw/vectoangles, so be sure to do the appropriate conversions (multiply by DEG2RAD or RAD2DEG as needed). -//note: atan2 can take unnormalized vectors (just like vectoyaw), and the function was included only for completeness (more often you want vectoyaw or vectoangles), atan2(v_x,v_y) * RAD2DEG gives the same result as vectoyaw(v) - -//DP_QC_AUTOCVARS -//idea: divVerent -//darkplaces implementation: divVerent -//description: -//allows QC variables to be bound to cvars -//(works for float, string, vector types) -//example: -// float autocvar_developer; -// float autocvar_registered; -// string autocvar__cl_name; -//NOTE: copying a string-typed autocvar to another variable/field, and then -//changing the cvar or returning from progs is UNDEFINED. Writing to autocvar -//globals is UNDEFINED. Accessing autocvar globals after cvar_set()ing that -//cvar is IMPLEMENTATION DEFINED (an implementation may either yield the -//previous, or the current, value). Whether autocvar globals, after restoring -//a savegame, have the cvar's current value, or the original value at time of -//saving, is UNDEFINED. Restoring a savegame however must not restore the -//cvar values themselves. -//In case the cvar does NOT exist, then it is automatically created with the -//value of the autocvar initializer, if given. This is possible with e.g. -//frikqcc and fteqcc the following way: -// var float autocvar_whatever = 42; -//If no initializer is given, the cvar will be initialized to a string -//equivalent to the NULL value of the given data type, that is, the empty -//string, 0, or '0 0 0'. However, when automatic cvar creation took place, a -//warning is printed to the game console. - -//DP_QC_CHANGEPITCH -//idea: id Software -//darkplaces implementation: id Software -//field definitions: -.float idealpitch; -.float pitch_speed; -//builtin definitions: -void(entity ent) changepitch = #63; -//description: -//equivilant to changeyaw, ent is normally self. (this was a Q2 builtin) - -//DP_QC_COPYENTITY -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -void(entity from, entity to) copyentity = #400; -//description: -//copies all data in the entity to another entity. - -//DP_QC_CVAR_DEFSTRING -//idea: id Software (Doom3), LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -string(string s) cvar_defstring = #482; -//description: -//returns the default value of a cvar, as a tempstring. - -//DP_QC_CVAR_DESCRIPTION -//idea: divVerent -//DarkPlaces implementation: divVerent -//builtin definitions: -string(string name) cvar_description = #518; -//description: -//returns the description of a cvar - -//DP_QC_CVAR_STRING -//idea: VorteX -//DarkPlaces implementation: VorteX, LordHavoc -//builtin definitions: -string(string s) cvar_string = #448; -//description: -//returns the value of a cvar, as a tempstring. - -//DP_QC_CVAR_TYPE -//idea: divVerent -//DarkPlaces implementation: divVerent -//builtin definitions: -float(string name) cvar_type = #495; -float CVAR_TYPEFLAG_EXISTS = 1; -float CVAR_TYPEFLAG_SAVED = 2; -float CVAR_TYPEFLAG_PRIVATE = 4; -float CVAR_TYPEFLAG_ENGINE = 8; -float CVAR_TYPEFLAG_HASDESCRIPTION = 16; -float CVAR_TYPEFLAG_READONLY = 32; - -//DP_QC_EDICT_NUM -//idea: 515 -//DarkPlaces implementation: LordHavoc -//builtin definitions: -entity(float entnum) edict_num = #459; -float(entity ent) wasfreed = #353; // same as in EXT_CSQC extension -//description: -//edict_num returns the entity corresponding to a given number, this works even for freed entities, but you should call wasfreed(ent) to see if is currently active. -//wasfreed returns whether an entity slot is currently free (entities that have never spawned are free, entities that have had remove called on them are also free). - -//DP_QC_ENTITYDATA -//idea: KrimZon -//darkplaces implementation: KrimZon -//builtin definitions: -float() numentityfields = #496; -string(float fieldnum) entityfieldname = #497; -float(float fieldnum) entityfieldtype = #498; -string(float fieldnum, entity ent) getentityfieldstring = #499; -float(float fieldnum, entity ent, string s) putentityfieldstring = #500; -//constants: -//Returned by entityfieldtype -float FIELD_STRING = 1; -float FIELD_FLOAT = 2; -float FIELD_VECTOR = 3; -float FIELD_ENTITY = 4; -float FIELD_FUNCTION = 6; -//description: -//Versatile functions intended for storing data from specific entities between level changes, but can be customized for some kind of partial savegame. -//WARNING: .entity fields cannot be saved and restored between map loads as they will leave dangling pointers. -//numentityfields returns the number of entity fields. NOT offsets. Vectors comprise 4 fields: v, v_x, v_y and v_z. -//entityfieldname returns the name as a string, eg. "origin" or "classname" or whatever. -//entityfieldtype returns a value that the constants represent, but the field may be of another type in more exotic progs.dat formats or compilers. -//getentityfieldstring returns data as would be written to a savegame, eg... "0.05" (float), "0 0 1" (vector), or "Hello World!" (string). Function names can also be returned. -//putentityfieldstring puts the data returned by getentityfieldstring back into the entity. - -//DP_QC_ENTITYSTRING -void(string s) loadfromdata = #529; -void(string s) loadfromfile = #530; -void(string s) callfunction = #605; -void(float fh, entity e) writetofile = #606; -float(string s) isfunction = #607; -void(entity e, string s) parseentitydata = #608; - -//DP_QC_ETOS -//idea: id Software -//darkplaces implementation: id Software -//builtin definitions: -string(entity ent) etos = #65; -//description: -//prints "entity 1" or similar into a string. (this was a Q2 builtin) - -//DP_QC_EXTRESPONSEPACKET -//idea: divVerent -//darkplaces implementation: divVerent -//builtin definitions: -string(void) getextresponse = #624; -//description: -//returns a string of the form "\"ipaddress:port\" data...", or the NULL string -//if no packet was found. Packets can be queued into the client/server by -//sending a packet starting with "\xFF\xFF\xFF\xFFextResponse " to the -//listening port. - -//DP_QC_FINDCHAIN -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -entity(.string fld, string match) findchain = #402; -//description: -//similar to find() but returns a chain of entities like findradius. - -//DP_QC_FINDCHAIN_TOFIELD -//idea: divVerent -//darkplaces implementation: divVerent -//builtin definitions: -entity(.string fld, float match, .entity tofield) findradius_tofield = #22; -entity(.string fld, string match, .entity tofield) findchain_tofield = #402; -entity(.string fld, float match, .entity tofield) findchainflags_tofield = #450; -entity(.string fld, float match, .entity tofield) findchainfloat_tofield = #403; -//description: -//similar to findchain() etc, but stores the chain into .tofield instead of .chain -//actually, the .entity tofield is an optional field of the the existing findchain* functions - -//DP_QC_FINDCHAINFLAGS -//idea: Sajt -//darkplaces implementation: LordHavoc -//builtin definitions: -entity(.float fld, float match) findchainflags = #450; -//description: -//similar to findflags() but returns a chain of entities like findradius. - -//DP_QC_FINDCHAINFLOAT -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -entity(.entity fld, entity match) findchainentity = #403; -entity(.float fld, float match) findchainfloat = #403; -//description: -//similar to findentity()/findfloat() but returns a chain of entities like findradius. - -//DP_QC_FINDFLAGS -//idea: Sajt -//darkplaces implementation: LordHavoc -//builtin definitions: -entity(entity start, .float fld, float match) findflags = #449; -//description: -//finds an entity with the specified flag set in the field, similar to find() - -//DP_QC_FINDFLOAT -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -entity(entity start, .entity fld, entity match) findentity = #98; -entity(entity start, .float fld, float match) findfloat = #98; -//description: -//finds an entity or float field value, similar to find(), but for entity and float fields. - -//DP_QC_FS_SEARCH -//idea: Black -//darkplaces implementation: Black -//builtin definitions: -float(string pattern, float caseinsensitive, float quiet) search_begin = #444; -void(float handle) search_end = #445; -float(float handle) search_getsize = #446; -string(float handle, float num) search_getfilename = #447; -//description: -//search_begin performs a filename search with the specified pattern (for example "maps/*.bsp") and stores the results in a search slot (minimum of 128 supported by any engine with this extension), the other functions take this returned search slot number, be sure to search_free when done (they are also freed on progs reload). -//search_end frees a search slot (also done at progs reload). -//search_getsize returns how many filenames were found. -//search_getfilename returns a filename from the search. - -//DP_QC_GETLIGHT -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -vector(vector org) getlight = #92; -//description: -//returns the lighting at the requested location (in color), 0-255 range (can exceed 255). - -//DP_QC_GETSURFACE -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -float(entity e, float s) getsurfacenumpoints = #434; -vector(entity e, float s, float n) getsurfacepoint = #435; -vector(entity e, float s) getsurfacenormal = #436; -string(entity e, float s) getsurfacetexture = #437; -float(entity e, vector p) getsurfacenearpoint = #438; -vector(entity e, float s, vector p) getsurfaceclippedpoint = #439; -//description: -//functions to query surface information. - -//DP_QC_GETSURFACEPOINTATTRIBUTE -//idea: BlackHC -//darkplaces implementation: BlackHC -// constants -float SPA_POSITION = 0; -float SPA_S_AXIS = 1; -float SPA_T_AXIS = 2; -float SPA_R_AXIS = 3; // same as SPA_NORMAL -float SPA_TEXCOORDS0 = 4; -float SPA_LIGHTMAP0_TEXCOORDS = 5; -float SPA_LIGHTMAP0_COLOR = 6; -//builtin definitions: -vector(entity e, float s, float n, float a) getsurfacepointattribute = #486; - -//description: -//function to query extended information about a point on a certain surface - -//DP_QC_GETSURFACETRIANGLE -//idea: divVerent -//darkplaces implementation: divVerent -//builtin definitions: -float(entity e, float s) getsurfacenumtriangles = #628; -vector(entity e, float s, float n) getsurfacetriangle = #629; -//description: -//function to query triangles of a surface - -//DP_QC_GETTAGINFO -//idea: VorteX, LordHavoc -//DarkPlaces implementation: VorteX -//builtin definitions: -float(entity ent, string tagname) gettagindex = #451; -vector(entity ent, float tagindex) gettaginfo = #452; -//description: -//gettagindex returns the number of a tag on an entity, this number is the same as set by setattachment (in the .tag_index field), allowing the qc to save a little cpu time by keeping the number around if it wishes (this could already be done by calling setattachment and saving off the tag_index). -//gettaginfo returns the origin of the tag in worldspace and sets v_forward, v_right, and v_up to the current orientation of the tag in worldspace, this automatically resolves all dependencies (attachments, including viewmodelforclient), this means you could fire a shot from a tag on a gun entity attached to the view for example. - -//DP_QC_GETTAGINFO_BONEPROPERTIES -//idea: daemon -//DarkPlaces implementation: divVerent -//global definitions: -float gettaginfo_parent; -string gettaginfo_name; -vector gettaginfo_offset; -vector gettaginfo_forward; -vector gettaginfo_right; -vector gettaginfo_up; -//description: -//when this extension is present, gettaginfo fills in some globals with info about the bone that had been queried -//gettaginfo_parent is set to the number of the parent bone, or 0 if it is a root bone -//gettaginfo_name is set to the name of the bone whose index had been specified in gettaginfo -//gettaginfo_offset, gettaginfo_forward, gettaginfo_right, gettaginfo_up contain the transformation matrix of the bone relative to its parent. Note that the matrix may contain a scaling component. - -//DP_QC_GETTIME -//idea: tZork -//darkplaces implementation: tZork, divVerent -//constant definitions: -float GETTIME_FRAMESTART = 0; // time of start of frame -float GETTIME_REALTIME = 1; // current time (may be OS specific) -float GETTIME_HIRES = 2; // like REALTIME, but may reset between QC invocations and thus can be higher precision -float GETTIME_UPTIME = 3; // time since start of the engine -//builtin definitions: -float(float tmr) gettime = #519; -//description: -//some timers to query... - -//DP_QC_GETTIME_CDTRACK -//idea: divVerent -//darkplaces implementation: divVerent -//constant definitions: -float GETTIME_CDTRACK = 4; -//description: -//returns the playing time of the current cdtrack when passed to gettime() -//see DP_END_GETSOUNDTIME for similar functionality but for entity sound channels - -//DP_QC_LOG -//darkplaces implementation: divVerent -//builtin definitions: -float log(float f) = #532; -//description: -//logarithm - -//DP_QC_MINMAXBOUND -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -float(float a, float b) min = #94; -float(float a, float b, float c) min3 = #94; -float(float a, float b, float c, float d) min4 = #94; -float(float a, float b, float c, float d, float e) min5 = #94; -float(float a, float b, float c, float d, float e, float f) min6 = #94; -float(float a, float b, float c, float d, float e, float f, float g) min7 = #94; -float(float a, float b, float c, float d, float e, float f, float g, float h) min8 = #94; -float(float a, float b) max = #95; -float(float a, float b, float c) max3 = #95; -float(float a, float b, float c, float d) max4 = #95; -float(float a, float b, float c, float d, float e) max5 = #95; -float(float a, float b, float c, float d, float e, float f) max6 = #95; -float(float a, float b, float c, float d, float e, float f, float g) max7 = #95; -float(float a, float b, float c, float d, float e, float f, float g, float h) max8 = #95; -float(float minimum, float val, float maximum) bound = #96; -//description: -//min returns the lowest of all the supplied numbers. -//max returns the highest of all the supplied numbers. -//bound clamps the value to the range and returns it. - -//DP_QC_MULTIPLETEMPSTRINGS -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//description: -//this extension makes all builtins returning tempstrings (ftos for example) -//cycle through a pool of multiple tempstrings (at least 16), allowing -//multiple ftos results to be gathered before putting them to use, normal -//quake only had 1 tempstring, causing many headaches. -// -//Note that for longer term storage (or compatibility on engines having -//FRIK_FILE but not this extension) the FRIK_FILE extension's -//strzone/strunzone builtins provide similar functionality (slower though). -// -//NOTE: this extension is superseded by DP_QC_UNLIMITEDTEMPSTRINGS - -//DP_QC_NUM_FOR_EDICT -//idea: Blub\0 -//darkplaces implementation: Blub\0 -//Function to get the number of an entity - a clean way. -float(entity num) num_for_edict = #512; - -//DP_QC_RANDOMVEC -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -vector() randomvec = #91; -//description: -//returns a vector of length < 1, much quicker version of this QC: do {v_x = random()*2-1;v_y = random()*2-1;v_z = random()*2-1;} while(vlen(v) > 1) - -//DP_QC_SINCOSSQRTPOW -//idea: id Software, LordHavoc -//darkplaces implementation: id Software, LordHavoc -//builtin definitions: -float(float val) sin = #60; -float(float val) cos = #61; -float(float val) sqrt = #62; -float(float a, float b) pow = #97; -//description: -//useful math functions, sine of val, cosine of val, square root of val, and raise a to power b, respectively. - -//DP_QC_SPRINTF -//idea: divVerent -//darkplaces implementation: divVerent -//builtin definitions: -string(string format, ...) sprintf = #627; -//description: -//you know sprintf :P -//supported stuff: -// % -// optional: <argpos>$ for the argument to format -// flags: #0- + -// optional: <width>, *, or *<argpos>$ for the field width -// optional: .<precision>, .*, or .*<argpos>$ for the precision -// length modifiers: h for forcing a float, l for forcing an int/entity (by default, %d etc. cast a float to int) -// conversions: -// d takes a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to an int -// i takes an int/entity if no length is specified or i is, and a float if h is specified as length, and cast it to an int -// ouxXc take a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to an unsigned int -// eEfFgG take a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to a double -// s takes a string -// vV takes a vector, and processes the three components as if it were a gG for all three components, separated by space -// For conversions s and c, the flag # makes precision and width interpreted -// as byte count, by default it is interpreted as character count in UTF-8 -// enabled engines. No other conversions can create wide characters, and # -// has another meaning in these. - -//DP_QC_STRFTIME -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -string(float uselocaltime, string format, ...) strftime = #478; -//description: -//provides the ability to get the local (in your timezone) or world (Universal Coordinated Time) time as a string using the formatting of your choice: -//example: "%Y-%m-%d %H:%M:%S" (result looks like: 2007-02-08 01:03:15) -//note: "%F %T" gives the same result as "%Y-%m-%d %H:%M:%S" (ISO 8601 date format and 24-hour time) -//for more format codes please do a web search for strftime 3 and you should find the man(3) pages for this standard C function. -// -//practical uses: -//changing day/night cycle (shops closing, monsters going on the prowl) in an RPG, for this you probably want to use s = strftime(TRUE, "%H");hour = stof(s); -//printing current date/time for competitive multiplayer games, such as the beginning/end of each round in real world time. -//activating eastereggs in singleplayer games on certain dates. -// -//note: some codes such as %x and %X use your locale settings and thus may not make sense to international users, it is not advisable to use these as the server and clients may be in different countries. -//note: if you display local time to a player, it would be a good idea to note whether it is local time using a string like "%F %T (local)", and otherwise use "%F %T (UTC)". -//note: be aware that if the game is saved and reloaded a week later the date and time will be different, so if activating eastereggs in a singleplayer game or something you may want to only check when a level is loaded and then keep the same easteregg state throughout the level so that the easteregg does not deactivate when reloading from a savegame (also be aware that precaches should not depend on such date/time code because reloading a savegame often scrambles the precaches if so!). -//note: this function can return a NULL string (you can check for it with if (!s)) if the localtime/gmtime functions returned NULL in the engine code, such as if those functions don't work on this platform (consoles perhaps?), so be aware that this may return nothing. - -//DP_QC_STRINGCOLORFUNCTIONS -//idea: Dresk -//darkplaces implementation: Dresk -//builtin definitions: -float(string s) strlennocol = #476; // returns how many characters are in a string, minus color codes -string(string s) strdecolorize = #477; // returns a string minus the color codes of the string provided -//description: -//provides additional functionality to strings by supporting functions that isolate and identify strings with color codes - -//DP_QC_STRING_CASE_FUNCTIONS -//idea: Dresk -//darkplaces implementation: LordHavoc / Dresk -//builtin definitions: -string(string s) strtolower = #480; // returns the passed in string in pure lowercase form -string(string s) strtoupper = #481; // returns the passed in string in pure uppercase form -//description: -//provides simple string uppercase and lowercase functions - -//DP_QC_TOKENIZEBYSEPARATOR -//idea: Electro, SavageX, LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -float(string s, string separator1, ...) tokenizebyseparator = #479; -//description: -//this function returns tokens separated by any of the supplied separator strings, example: -//numnumbers = tokenizebyseparator("10.2.3.4", "."); -//returns 4 and the tokens are "10" "2" "3" "4" -//possibly useful for parsing IPv4 addresses (such as "1.2.3.4") and IPv6 addresses (such as "[1234:5678:9abc:def0:1234:5678:9abc:def0]:26000") - -//DP_QC_TOKENIZE_CONSOLE -//idea: divVerent -//darkplaces implementation: divVerent -//builtin definitions: -float(string s) tokenize_console = #514; -float(float i) argv_start_index = #515; -float(float i) argv_end_index = #516; -//description: -//this function returns tokens separated just like the console does -//also, functions are provided to get the index of the first and last character of each token in the original string -//Passing negative values to them, or to argv, will be treated as indexes from the LAST token (like lists work in Perl). So argv(-1) will return the LAST token. - -//DP_QC_TRACEBOX -//idea: id Software -//darkplaces implementation: id Software -//builtin definitions: -void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox = #90; -//description: -//similar to traceline but much more useful, traces a box of the size specified (technical note: in quake1 and halflife bsp maps the mins and maxs will be rounded up to one of the hull sizes, quake3 bsp does not have this problem, this is the case with normal moving entities as well). - -//DP_QC_TRACETOSS -//idea: id Software -//darkplaces implementation: id Software -//builtin definitions: -void(entity ent, entity ignore) tracetoss = #64; -//description: -//simulates movement of the entity as if it is MOVETYPE_TOSS and starting with it's current state (location, velocity, etc), returns relevant trace_ variables (trace_fraction is always 0, all other values are supported - trace_ent, trace_endpos, trace_plane_normal), does not actually alter the entity. - -//DP_QC_TRACE_MOVETYPE_HITMODEL -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//constant definitions: -float MOVE_HITMODEL = 4; -//description: -//allows traces to hit alias models (not sprites!) instead of entity boxes, use as the nomonsters parameter to trace functions, note that you can hit invisible model entities (alpha < 0 or EF_NODRAW or model "", it only checks modelindex) - -//DP_QC_TRACE_MOVETYPE_WORLDONLY -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//constant definitions: -float MOVE_WORLDONLY = 3; -//description: -//allows traces to hit only world (ignoring all entities, unlike MOVE_NOMONSTERS which hits all bmodels), use as the nomonsters parameter to trace functions - -//DP_QC_UNLIMITEDTEMPSTRINGS -//idea: divVerent -//darkplaces implementation: LordHavoc -//description: -//this extension alters Quake behavior such that instead of reusing a single -//tempstring (or multiple) there are an unlimited number of tempstrings, which -//are removed only when a QC function invoked by the engine returns, -//eliminating almost all imaginable concerns with string handling in QuakeC. -// -//in short: -//you can now use and abuse tempstrings as much as you like, you still have to -//use strzone (FRIK_FILE) for permanent storage however. -// -// -// -//implementation notes for other engine coders: -//these tempstrings are expected to be stored in a contiguous buffer in memory -//which may be fixed size or controlled by a cvar, or automatically grown on -//demand (in the case of DarkPlaces). -// -//this concept is similar to quake's Zone system, however these are all freed -//when the QC interpreter returns. -// -//this is basically a poor man's garbage collection system for strings. - -//DP_QC_VECTOANGLES_WITH_ROLL -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -vector(vector forward, vector up) vectoangles2 = #51; // same number as vectoangles -//description: -//variant of vectoangles that takes an up vector to calculate roll angle (also uses this to calculate yaw correctly if the forward is straight up or straight down) -//note: just like normal vectoangles you need to negate the pitch of the returned angles if you want to feed them to makevectors or assign to self.v_angle - -//DP_QC_VECTORVECTORS -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -void(vector dir) vectorvectors = #432; -//description: -//creates v_forward, v_right, and v_up vectors given a forward vector, similar to makevectors except it takes a forward direction vector instead of angles. - -//DP_QC_WHICHPACK -//idea: divVerent -//darkplaces implementation: divVerent -//builtin definitions: -string(string filename) whichpack = #503; -//description: -//returns the name of the pak/pk3/whatever containing the given file, in the same path space as FRIK_FILE functions use (that is, possibly with a path name prefix) - -//DP_QC_URI_ESCAPE -//idea: divVerent -//darkplaces implementation: divVerent -//URI::Escape's functionality -string(string in) uri_escape = #510; -string(string in) uri_unescape = #511; - -//DP_QC_URI_GET -//idea: divVerent -//darkplaces implementation: divVerent -//loads text from an URL into a string -//returns 1 on success of initiation, 0 if there are too many concurrent -//connections already or if the URL is invalid -//the following callback will receive the data and MUST exist! -// void(float id, float status, string data) URI_Get_Callback; -//status is either -// negative for an internal error, -// 0 for success, or -// the HTTP response code on server error (e.g. 404) -//if 1 is returned by uri_get, the callback will be called in the future -float(string url, float id) uri_get = #513; - -//DP_QC_URI_POST -//idea: divVerent -//darkplaces implementation: divVerent -//loads text from an URL into a string after POSTing via HTTP -//works like uri_get, but uri_post sends data with Content-Type: content_type to the server -//and uri_post sends the string buffer buf, joined using the delimiter delim -float(string url, float id, string content_type, string data) uri_post = #513; -float(string url, float id, string content_type, string delim, float buf) uri_postbuf = #513; - -//DP_SKELETONOBJECTS -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//description: -//this extension indicates that FTE_CSQC_SKELETONOBJECTS functionality is available in server QC (as well as CSQC). - -//DP_SV_SPAWNFUNC_PREFIX -//idea: divVerent -//darkplaces implementation: divVerent -//Make functions whose name start with spawnfunc_ take precedence as spawn function for loading entities. -//Useful if you have a field ammo_shells (required in any Quake mod) but want to support spawn functions called ammo_shells (like in Q3A). -//Optionally, you can declare a global "float require_spawnfunc_prefix;" which will require ANY spawn function to start with that prefix. - - -//DP_QUAKE2_MODEL -//idea: quake community -//darkplaces implementation: LordHavoc -//description: -//shows that the engine supports Quake2 .md2 files. - -//DP_QUAKE2_SPRITE -//idea: LordHavoc -//darkplaces implementation: Elric -//description: -//shows that the engine supports Quake2 .sp2 files. - -//DP_QUAKE3_MAP -//idea: quake community -//darkplaces implementation: LordHavoc -//description: -//shows that the engine supports Quake3 .bsp files. - -//DP_QUAKE3_MODEL -//idea: quake community -//darkplaces implementation: LordHavoc -//description: -//shows that the engine supports Quake3 .md3 files. - -//DP_REGISTERCVAR -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -float(string name, string value) registercvar = #93; -//description: -//adds a new console cvar to the server console (in singleplayer this is the player's console), the cvar exists until the mod is unloaded or the game quits. -//NOTE: DP_CON_SET is much better. - -//DP_SND_DIRECTIONLESSATTNNONE -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//description: -//make sounds with ATTN_NONE have no spatialization (enabling easy use as music sources). - -//DP_SND_FAKETRACKS -//idea: requested -//darkplaces implementation: Elric -//description: -//the engine plays sound/cdtracks/track001.wav instead of cd track 1 and so on if found, this allows games and mods to have music tracks without using ambientsound. -//Note: also plays .ogg with DP_SND_OGGVORBIS extension. - -//DP_SND_OGGVORBIS -//idea: Transfusion -//darkplaces implementation: Elric -//description: -//the engine supports loading Ogg Vorbis sound files. Use either the .ogg filename directly, or a .wav of the same name (will try to load the .wav first and then .ogg). - -//DP_SND_STEREOWAV -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//description: -//the engine supports stereo WAV files. (useful with DP_SND_DIRECTIONLESSATTNNONE for music) - -//DP_SND_GETSOUNDTIME -//idea: VorteX -//darkplaces implementation: VorteX -//constant definitions: -float(entity e, float channel) getsoundtime = #533; // get currently sound playing position on entity channel, -1 if not playing or error -float(string sample) soundlength = #534; // returns length of sound sample in seconds, -1 on error (sound not precached, sound system not initialized etc.) -//description: provides opportunity to query length of sound samples and realtime tracking of sound playing on entities (similar to DP_GETTIME_CDTRACK) -//note: beware dedicated server not running sound engine at all, so in dedicated mode this builtins will not work in server progs -//note also: menu progs not supporting getsoundtime() (will give a warning) since it has no sound playing on entities -//examples of use: -// - QC-driven looped sounds -// - QC events when sound playing is finished -// - toggleable ambientsounds -// - subtitles - -//DP_VIDEO_DPV -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//console commands: -// playvideo <videoname> - start playing video -// stopvideo - stops current video -//description: indicated that engine support playing videos in DPV format - -//DP_VIDEO_SUBTITLES -//idea: VorteX -//darkplaces implementation: VorteX -//cvars: -// cl_video_subtitles - toggles subtitles showing -// cl_video_subtitles_lines - how many lines to reserve for subtitles -// cl_video_subtitles_textsize - font size -//console commands: -// playvideo <videoname> <custom_subtitles_file> - start playing video -// stopvideo - stops current video -//description: indicates that engine support subtitles on videos -//subtitles stored in external text files, each video file has it's default subtitles file ( <videoname>.dpsubs ) -//example: for video/act1.dpv default subtitles file will be video/act1.dpsubs -//also video could be played with custom subtitles file by utilizing second parm of playvideo command -//syntax of .dpsubs files: each line in .dpsubs file defines 1 subtitle, there are three tokens: -// <start> <end> "string" -// start: subtitle start time in seconds -// end: subtitle time-to-show in seconds, if 0 - subtitle will be showed until next subtitle is started, -// if below 0 - show until next subtitles minus this number of seconds -// text: subtitle text, color codes (Q3-style and ^xRGB) are allowed -//example of subtitle file: -// 3 0 "Vengeance! Vengeance for my eternity of suffering!" -// 9 0 "Whelp! As if you knew what eternity was!" -// 13 0 "Grovel before your true master." -// 17 0 "Never!" -// 18 7 "I'll hack you from crotch to gizzard and feed what's left of you to your brides..." - -//DP_SOLIDCORPSE -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//solid definitions: -float SOLID_CORPSE = 5; -//description: -//the entity will not collide with SOLID_CORPSE and SOLID_SLIDEBOX entities (and likewise they will not collide with it), this is useful if you want dead bodies that are shootable but do not obstruct movement by players and monsters, note that if you traceline with a SOLID_SLIDEBOX entity as the ignoreent, it will ignore SOLID_CORPSE entities, this is desirable for visibility and movement traces, but not for bullets, for the traceline to hit SOLID_CORPSE you must temporarily force the player (or whatever) to SOLID_BBOX and then restore to SOLID_SLIDEBOX after the traceline. - -//DP_SPRITE32 -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//description: -//the engine supports .spr32 sprites. - -//DP_SV_BOTCLIENT -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//constants: -float CLIENTTYPE_DISCONNECTED = 0; -float CLIENTTYPE_REAL = 1; -float CLIENTTYPE_BOT = 2; -float CLIENTTYPE_NOTACLIENT = 3; -//builtin definitions: -entity() spawnclient = #454; // like spawn but for client slots (also calls relevant connect/spawn functions), returns world if no clients available -float(entity clent) clienttype = #455; // returns one of the CLIENTTYPE_* constants -//description: -//spawns a client with no network connection, to allow bots to use client slots with no hacks. -//How to use: -/* - // to spawn a bot - local entity oldself; - oldself = self; - self = spawnclient(); - if (!self) - { - bprint("Can not add bot, server full.\n"); - self = oldself; - return; - } - self.netname = "Yoyobot"; - self.clientcolors = 12 * 16 + 4; // yellow (12) shirt and red (4) pants - ClientConnect(); - PutClientInServer(); - self = oldself; - - // to remove all bots - local entity head; - head = find(world, classname, "player"); - while (head) - { - if (clienttype(head) == CLIENTTYPE_BOT) - dropclient(head); - head = find(head, classname, "player"); - } - - // to identify if a client is a bot (for example in PlayerPreThink) - if (clienttype(self) == CLIENTTYPE_BOT) - botthink(); -*/ -//see also DP_SV_CLIENTCOLORS DP_SV_CLIENTNAME DP_SV_DROPCLIENT -//How it works: -//creates a new client, calls SetNewParms and stores the parms, and returns the client. -//this intentionally does not call SV_SendServerinfo to allow the QuakeC a chance to set the netname and clientcolors fields before actually spawning the bot by calling ClientConnect and PutClientInServer manually -//on level change ClientConnect and PutClientInServer are called by the engine to spawn in the bot (this is why clienttype() exists to tell you on the next level what type of client this is). -//parms work the same on bot clients as they do on real clients, and do carry from level to level - -//DP_SV_BOUNCEFACTOR -//idea: divVerent -//darkplaces implementation: divVerent -//field definitions: -.float bouncefactor; // velocity multiplier after a bounce -.float bouncestop; // bounce stops if velocity to bounce plane is < bouncestop * gravity AFTER the bounce -//description: -//allows qc to customize MOVETYPE_BOUNCE a bit - -//DP_SV_CLIENTCAMERA -//idea: LordHavoc, others -//darkplaces implementation: Black -//field definitions: -.entity clientcamera; // override camera entity -//description: -//allows another entity to be the camera for a client, for example a remote camera, this is similar to sending svc_setview manually except that it also changes the network culling appropriately. - -//DP_SV_CLIENTCOLORS -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//field definitions: -.float clientcolors; // colors of the client (format: pants + shirt * 16) -//description: -//allows qc to read and modify the client colors associated with a client entity (not particularly useful on other entities), and automatically sends out any appropriate network updates if changed - -//DP_SV_CLIENTNAME -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//description: -//allows qc to modify the client's .netname, and automatically sends out any appropriate network updates if changed - -//DP_SV_CUSTOMIZEENTITYFORCLIENT -//idea: LordHavoc -//darkplaces implementation: [515] and LordHavoc -//field definitions: -.float() customizeentityforclient; // self = this entity, other = client entity -//description: -//allows qc to modify an entity before it is sent to each client, the function returns TRUE if it should send, FALSE if it should not, and is fully capable of editing the entity's fields, this allows cloaked players to appear less transparent to their teammates, navigation markers to only show to their team, etc -//tips on writing customize functions: -//it is a good idea to return FALSE early in the function if possible to reduce cpu usage, because this function may be called many thousands of times per frame if there are many customized entities on a 64+ player server. -//you are free to change anything in self, but please do not change any other entities (the results may be very inconsistent). -//example ideas for use of this extension: -//making icons over teammates' heads which are only visible to teammates. for exasmple: float() playericon_customizeentityforclient = {return self.owner.team == other.team;}; -//making cloaked players more visible to their teammates than their enemies. for example: float() player_customizeentityforclient = {if (self.items & IT_CLOAKING) {if (self.team == other.team) self.alpha = 0.6;else self.alpha = 0.1;} return TRUE;}; -//making explosion models that face the viewer (does not work well with chase_active). for example: float() explosion_customizeentityforclient = {self.angles = vectoangles(other.origin + other.view_ofs - self.origin);self.angles_x = 0 - self.angles_x;}; -//implementation notes: -//entity customization is done before per-client culling (visibility for instance) because the entity may be doing setorigin to display itself in different locations on different clients, may be altering its .modelindex, .effects and other fields important to culling, so customized entities increase cpu usage (non-customized entities can use all the early culling they want however, as they are not changing on a per client basis). - -//DP_SV_DISCARDABLEDEMO -//idea: parasti -//darkplaces implementation: parasti -//field definitions: -.float discardabledemo; -//description: -//when this field is set to a non-zero value on a player entity, a possibly recorded server-side demo for the player is discarded -//Note that this extension only works if: -// auto demos are enabled (the cvar sv_autodemo_perclient is set) -// discarding demos is enabled (the cvar sv_autodemo_perclient_discardable is set) - -//DP_SV_DRAWONLYTOCLIENT -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//field definitions: -.entity drawonlytoclient; -//description: -//the entity is only visible to the specified client. - -//DP_SV_DROPCLIENT -//idea: FrikaC -//darkplaces implementation: LordHavoc -//builtin definitions: -void(entity clent) dropclient = #453; -//description: -//causes the server to immediately drop the client, more reliable than stuffcmd(clent, "disconnect\n"); which could be intentionally ignored by the client engine - -//DP_SV_EFFECT -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -void(vector org, string modelname, float startframe, float endframe, float framerate) effect = #404; -//SVC definitions: -//float svc_effect = #52; // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate -//float svc_effect2 = #53; // [vector] org [short] modelindex [byte] startframe [byte] framecount [byte] framerate -//description: -//clientside playback of simple custom sprite effects (explosion sprites, etc). - -//DP_SV_ENTITYCONTENTSTRANSITION -//idea: Dresk -//darkplaces implementation: Dresk -//field definitions: -.void(float nOriginalContents, float nNewContents) contentstransition; -//description: -//This field function, when provided, is triggered on an entity when the contents (ie. liquid / water / etc) is changed. -//The first parameter provides the entities original contents, prior to the transition. The second parameter provides the new contents. -//NOTE: If this field function is provided on an entity, the standard watersplash sound IS SUPPRESSED to allow for authors to create their own transition sounds. - -//DP_SV_MOVETYPESTEP_LANDEVENT -//idea: Dresk -//darkplaces implementation: Dresk -//field definitions: -.void(vector vImpactVelocity) movetypesteplandevent; -//description: -//This field function, when provided, is triggered on a MOVETYPE_STEP entity when it experiences "land event". -// The standard engine behavior for this event is to play the sv_sound_land CVar sound. -//The parameter provides the velocity of the entity at the time of the impact. The z value may therefore be used to calculate how "hard" the entity struck the surface. -//NOTE: If this field function is provided on a MOVETYPE_STEP entity, the standard sv_sound_land sound IS SUPPRESSED to allow for authors to create their own feedback. - -//DP_SV_POINTSOUND -//idea: Dresk -//darkplaces implementation: Dresk -//builtin definitions: -void(vector origin, string sample, float volume, float attenuation) pointsound = #483; -//description: -//Similar to the standard QC sound function, this function takes an origin instead of an entity and omits the channel parameter. -// This allows sounds to be played at arbitrary origins without spawning entities. - -//DP_SV_ONENTITYNOSPAWNFUNCTION -//idea: Dresk -//darkplaces implementation: Dresk -//engine-called QC prototypes: -//void() SV_OnEntityNoSpawnFunction; -//description: -// This function is called whenever an entity on the server has no spawn function, and therefore has no defined QC behavior. -// You may as such dictate the behavior as to what happens to the entity. -// To mimic the engine's default behavior, simply call remove(self). - -//DP_SV_ONENTITYPREPOSTSPAWNFUNCTION -//idea: divVerent -//darkplaces implementation: divVerent -//engine-called QC prototypes: -//void() SV_OnEntityPreSpawnFunction; -//void() SV_OnEntityPostSpawnFunction; -//description: -// These functions are called BEFORE or AFTER an entity is spawned the regular way. -// You may as such dictate the behavior as to what happens to the entity. -// SV_OnEntityPreSpawnFunction is called before even looking for the spawn function, so you can even change its classname in there. If it remove()s the entity, the spawn function will not be looked for. -// SV_OnEntityPostSpawnFunction is called ONLY after its spawn function or SV_OnEntityNoSpawnFunction was called, and skipped if the entity got removed by either. - -//DP_SV_MODELFLAGS_AS_EFFECTS -//idea: LordHavoc, Dresk -//darkplaces implementation: LordHavoc -//field definitions: -.float modelflags; -//constant definitions: -float EF_NOMODELFLAGS = 8388608; // ignore any effects in a model file and substitute your own -float MF_ROCKET = 1; // leave a trail -float MF_GRENADE = 2; // leave a trail -float MF_GIB = 4; // leave a trail -float MF_ROTATE = 8; // rotate (bonus items) -float MF_TRACER = 16; // green split trail -float MF_ZOMGIB = 32; // small blood trail -float MF_TRACER2 = 64; // orange split trail -float MF_TRACER3 = 128; // purple trail -//description: -//this extension allows model flags to be specified on entities so you can add a rocket trail and glow to any entity, etc. -//setting any of these will override the flags the model already has, to disable the model's flags without supplying any of your own you must use EF_NOMODELFLAGS. -// -//silly example modification #1 to W_FireRocket in weapons.qc: -//missile.effects = EF_NOMODELFLAGS; // rocket without a glow/fire trail -//silly example modification #2 to W_FireRocket in weapons.qc: -//missile.modelflags = MF_GIB; // leave a blood trail instead of glow/fire trail -// -//note: you can not combine multiple kinds of trail, only one of them will be active, you can combine MF_ROTATE and the other MF_ flags however, and using EF_NOMODELFLAGS along with these does no harm. -// -//note to engine coders: they are internally encoded in the protocol as extra EF_ flags (shift the values left 24 bits and send them in the protocol that way), so no protocol change was required (however 32bit effects is a protocol extension itself), within the engine they are referred to as EF_ for the 24bit shifted values. - -//DP_SV_NETADDRESS -//idea: Dresk -//darkplaces implementation: Dresk -//field definitions: -.string netaddress; -//description: -// provides the netaddress of the associated entity (ie. 127.0.0.1) and "null/botclient" if the netconnection of the entity is invalid - -//DP_SV_NODRAWTOCLIENT -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//field definitions: -.entity nodrawtoclient; -//description: -//the entity is not visible to the specified client. - -//DP_SV_PING -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//field definitions: -.float ping; -//description: -//continuously updated field indicating client's ping (based on average of last 16 packet time differences). - -//DP_SV_PING_PACKETLOSS -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//field definitions: -.float ping_packetloss; -.float ping_movementloss; -//description: -//continuously updated field indicating client's packet loss, and movement loss (i.e. packet loss affecting player movement). - -//DP_SV_POINTPARTICLES -//idea: Spike -//darkplaces implementation: LordHavoc -//function definitions: -float(string effectname) particleeffectnum = #335; // same as in CSQC -void(entity ent, float effectnum, vector start, vector end) trailparticles = #336; // same as in CSQC -void(float effectnum, vector org, vector vel, float howmany) pointparticles = #337; // same as in CSQC -//SVC definitions: -//float svc_trailparticles = 60; // [short] entnum [short] effectnum [vector] start [vector] end -//float svc_pointparticles = 61; // [short] effectnum [vector] start [vector] velocity [short] count -//float svc_pointparticles1 = 62; // [short] effectnum [vector] start, same as svc_pointparticles except velocity is zero and count is 1 -//description: -//provides the ability to spawn non-standard particle effects, typically these are defined in a particle effect information file such as effectinfo.txt in darkplaces. -//this is a port of particle effect features from clientside QC (EXT_CSQC) to server QC, as these effects are potentially useful to all games even if they do not make use of EXT_CSQC. -//warning: server must have same order of effects in effectinfo.txt as client does or the numbers would not match up, except for standard quake effects which are always the same numbers. - -//DP_SV_PUNCHVECTOR -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//field definitions: -.vector punchvector; -//description: -//offsets client view in worldspace, similar to view_ofs but all 3 components are used and are sent with at least 8 bits of fraction, this allows the view to be kicked around by damage or hard landings or whatever else, note that unlike punchangle this is not faded over time, it is up to the mod to fade it (see also DP_SV_PLAYERPHYSICS). - -//DP_SV_PLAYERPHYSICS -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//field definitions: -.vector movement; -//cvar definitions: -//"sv_playerphysicsqc" (0/1, default 1, allows user to disable qc player physics) -//engine-called QC prototypes: -//void() SV_PlayerPhysics; -//description: -//.movement vector contains the movement input from the player, allowing QC to do as it wishs with the input, and SV_PlayerPhysics will completely replace the player physics if present (works for all MOVETYPE's), see darkplaces mod source for example of this function (in playermovement.qc, adds HalfLife ladders support, as well as acceleration/deceleration while airborn (rather than the quake sudden-stop while airborn), and simplifies the physics a bit) - -//DP_SV_PRINT -//idea: id Software (QuakeWorld Server) -//darkplaces implementation: Black, LordHavoc -void(string s, ...) print = #339; // same number as in EXT_CSQC -//description: -//this is identical to dprint except that it always prints regardless of the developer cvar. - -//DP_SV_PRECACHEANYTIME -//idea: id Software (Quake2) -//darkplaces implementation: LordHavoc -//description: -//this extension allows precache_model and precache_sound (and any variants) to be used during the game (with automatic messages to clients to precache the new model/sound indices), also setmodel/sound/ambientsound can be called without precaching first (they will cause an automatic precache). - -//DP_SV_QCSTATUS -//idea: divVerent -//darkplaces implementation: divVerent -//1. A global variable -string worldstatus; -//Its content is set as "qcstatus" field in the rules. -//It may be at most 255 characters, and must not contain newlines or backslashes. -//2. A per-client field -.string clientstatus; -//It is sent instead of the "frags" in status responses. -//It should always be set in a way so that stof(player.clientstatus) is a meaningful score value. Other info may be appended. If used this way, the cvar sv_status_use_qcstatus may be set to 1, and then this value will replace the frags in "status". -//Currently, qstat does not support this and will not show player info if used and set to anything other than ftos(some integer). - -//DP_SV_ROTATINGBMODEL -//idea: id Software -//darkplaces implementation: LordHavoc -//description: -//this extension merely indicates that MOVETYPE_PUSH supports avelocity, allowing rotating brush models to be created, they rotate around their origin (needs rotation supporting qbsp/light utilities because id ones expected bmodel entity origins to be '0 0 0', recommend setting "origin" key in the entity fields in the map before compiling, there may be other methods depending on your qbsp, most are more complicated however). -//tip: level designers can create a func_wall with an origin, and avelocity (for example "avelocity" "0 90 0"), and "nextthink" "99999999" to make a rotating bmodel without any qc modifications, such entities will be solid in stock quake but will not rotate) - -//DP_SV_SETCOLOR -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -void(entity ent, float colors) setcolor = #401; -//engine called QC functions (optional): -//void(float color) SV_ChangeTeam; -//description: -//setcolor sets the color on a client and updates internal color information accordingly (equivilant to stuffing a "color" command but immediate) -//SV_ChangeTeam is called by the engine whenever a "color" command is recieved, it may decide to do anything it pleases with the color passed by the client, including rejecting it (by doing nothing), or calling setcolor to apply it, preventing team changes is one use for this. -//the color format is pants + shirt * 16 (0-255 potentially) - -//DP_SV_SLOWMO -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//cvars: -//"slowmo" (0+, default 1) -//description: -//sets the time scale of the server, mainly intended for use in singleplayer by the player, however potentially useful for mods, so here's an extension for it. -//range is 0 to infinite, recommended values to try are 0.1 (very slow, 10% speed), 1 (normal speed), 5 (500% speed). - -//DP_SV_WRITEPICTURE -//idea: divVerent -//darkplaces implementation: divVerent -//builtin definitions: -void(float to, string s, float sz) WritePicture = #501; -//description: -//writes a picture to the data stream so CSQC can read it using ReadPicture, which has the definition -// string(void) ReadPicture = #501; -//The picture data is sent as at most sz bytes, by compressing to low quality -//JPEG. The data being sent will be equivalent to: -// WriteString(to, s); -// WriteShort(to, imagesize); -// for(i = 0; i < imagesize; ++i) -// WriteByte(to, [the i-th byte of the compressed JPEG image]); - -//DP_SV_WRITEUNTERMINATEDSTRING -//idea: FrikaC -//darkplaces implementation: Sajt -//builtin definitions: -void(float to, string s) WriteUnterminatedString = #456; -//description: -//like WriteString, but does not write a terminating 0 after the string. This means you can include things like a player's netname in the middle of a string sent over the network. Just be sure to end it up with either a call to WriteString (which includes the trailing 0) or WriteByte(0) to terminate it yourself. -//A historical note: this extension was suggested by FrikaC years ago, more recently Shadowalker has been badmouthing LordHavoc and Spike for stealing 'his' extension writestring2 which does exactly the same thing but uses a different builtin number and name and extension string, this argument hinges on the idea that it was his idea in the first place, which is incorrect as FrikaC first suggested it and used a rough equivilant of it in his FrikBot mod years ago involving WriteByte calls on each character. - -//DP_TE_BLOOD -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -void(vector org, vector velocity, float howmany) te_blood = #405; -//temp entity definitions: -float TE_BLOOD = 50; -//protocol: -//vector origin -//byte xvelocity (-128 to +127) -//byte yvelocity (-128 to +127) -//byte zvelocity (-128 to +127) -//byte count (0 to 255, how much blood) -//description: -//creates a blood effect. - -//DP_TE_BLOODSHOWER -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower = #406; -//temp entity definitions: -//float TE_BLOODSHOWER = 52; -//protocol: -//vector mins (minimum corner of the cube) -//vector maxs (maximum corner of the cube) -//coord explosionspeed (velocity of blood particles flying out of the center) -//short count (number of blood particles) -//description: -//creates an exploding shower of blood, for making gibbings more convincing. - -//DP_TE_CUSTOMFLASH -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -void(vector org, float radius, float lifetime, vector color) te_customflash = #417; -//temp entity definitions: -//float TE_CUSTOMFLASH = 73; -//protocol: -//vector origin -//byte radius ((MSG_ReadByte() + 1) * 8, meaning 8-2048 unit radius) -//byte lifetime ((MSG_ReadByte() + 1) / 256.0, meaning approximately 0-1 second lifetime) -//byte red (0.0 to 1.0 converted to 0-255) -//byte green (0.0 to 1.0 converted to 0-255) -//byte blue (0.0 to 1.0 converted to 0-255) -//description: -//creates a customized light flash. - -//DP_TE_EXPLOSIONRGB -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -void(vector org, vector color) te_explosionrgb = #407; -//temp entity definitions: -//float TE_EXPLOSIONRGB = 53; -//protocol: -//vector origin -//byte red (0.0 to 1.0 converted to 0 to 255) -//byte green (0.0 to 1.0 converted to 0 to 255) -//byte blue (0.0 to 1.0 converted to 0 to 255) -//description: -//creates a colored explosion effect. - -//DP_TE_FLAMEJET -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -void(vector org, vector vel, float howmany) te_flamejet = #457; -//temp entity definitions: -//float TE_FLAMEJET = 74; -//protocol: -//vector origin -//vector velocity -//byte count (0 to 255, how many flame particles) -//description: -//creates a single puff of flame particles. (not very useful really) - -//DP_TE_PARTICLECUBE -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube = #408; -//temp entity definitions: -//float TE_PARTICLECUBE = 54; -//protocol: -//vector mins (minimum corner of the cube) -//vector maxs (maximum corner of the cube) -//vector velocity -//short count -//byte color (palette color) -//byte gravity (TRUE or FALSE, FIXME should this be a scaler instead?) -//coord randomvel (how much to jitter the velocity) -//description: -//creates a cloud of particles, useful for forcefields but quite customizable. - -//DP_TE_PARTICLERAIN -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain = #409; -//temp entity definitions: -//float TE_PARTICLERAIN = 55; -//protocol: -//vector mins (minimum corner of the cube) -//vector maxs (maximum corner of the cube) -//vector velocity (velocity of particles) -//short count (number of particles) -//byte color (8bit palette color) -//description: -//creates a shower of rain, the rain will appear either at the top (if falling down) or bottom (if falling up) of the cube. - -//DP_TE_PARTICLESNOW -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow = #410; -//temp entity definitions: -//float TE_PARTICLERAIN = 56; -//protocol: -//vector mins (minimum corner of the cube) -//vector maxs (maximum corner of the cube) -//vector velocity (velocity of particles) -//short count (number of particles) -//byte color (8bit palette color) -//description: -//creates a shower of snow, the snow will appear either at the top (if falling down) or bottom (if falling up) of the cube, low velocities are advisable for convincing snow. - -//DP_TE_PLASMABURN -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -void(vector org) te_plasmaburn = #433; -//temp entity definitions: -//float TE_PLASMABURN = 75; -//protocol: -//vector origin -//description: -//creates a small light flash (radius 200, time 0.2) and marks the walls. - -//DP_TE_QUADEFFECTS1 -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -void(vector org) te_gunshotquad = #412; -void(vector org) te_spikequad = #413; -void(vector org) te_superspikequad = #414; -void(vector org) te_explosionquad = #415; -//temp entity definitions: -//float TE_GUNSHOTQUAD = 57; // [vector] origin -//float TE_SPIKEQUAD = 58; // [vector] origin -//float TE_SUPERSPIKEQUAD = 59; // [vector] origin -//float TE_EXPLOSIONQUAD = 70; // [vector] origin -//protocol: -//vector origin -//description: -//all of these just take a location, and are equivilant in function (but not appearance :) to the original TE_GUNSHOT, etc. - -//DP_TE_SMALLFLASH -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -void(vector org) te_smallflash = #416; -//temp entity definitions: -//float TE_SMALLFLASH = 72; -//protocol: -//vector origin -//description: -//creates a small light flash (radius 200, time 0.2). - -//DP_TE_SPARK -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -void(vector org, vector vel, float howmany) te_spark = #411; -//temp entity definitions: -//float TE_SPARK = 51; -//protocol: -//vector origin -//byte xvelocity (-128 to 127) -//byte yvelocity (-128 to 127) -//byte zvelocity (-128 to 127) -//byte count (number of sparks) -//description: -//creates a shower of sparks and a smoke puff. - -//DP_TE_STANDARDEFFECTBUILTINS -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -void(vector org) te_gunshot = #418; -void(vector org) te_spike = #419; -void(vector org) te_superspike = #420; -void(vector org) te_explosion = #421; -void(vector org) te_tarexplosion = #422; -void(vector org) te_wizspike = #423; -void(vector org) te_knightspike = #424; -void(vector org) te_lavasplash = #425; -void(vector org) te_teleport = #426; -void(vector org, float color, float colorlength) te_explosion2 = #427; -void(entity own, vector start, vector end) te_lightning1 = #428; -void(entity own, vector start, vector end) te_lightning2 = #429; -void(entity own, vector start, vector end) te_lightning3 = #430; -void(entity own, vector start, vector end) te_beam = #431; -//description: -//to make life easier on mod coders. - -//DP_TRACE_HITCONTENTSMASK_SURFACEINFO -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//globals: -.float dphitcontentsmask; // if non-zero on the entity passed to traceline/tracebox/tracetoss this will override the normal collidable contents rules and instead hit these contents values (for example AI can use tracelines that hit DONOTENTER if it wants to, by simply changing this field on the entity passed to traceline), this affects normal movement as well as trace calls -float trace_dpstartcontents; // DPCONTENTS_ value at start position of trace -float trace_dphitcontents; // DPCONTENTS_ value of impacted surface (not contents at impact point, just contents of the surface that was hit) -float trace_dphitq3surfaceflags; // Q3SURFACEFLAG_ value of impacted surface -string trace_dphittexturename; // texture name of impacted surface -//constants: -float DPCONTENTS_SOLID = 1; // hit a bmodel, not a bounding box -float DPCONTENTS_WATER = 2; -float DPCONTENTS_SLIME = 4; -float DPCONTENTS_LAVA = 8; -float DPCONTENTS_SKY = 16; -float DPCONTENTS_BODY = 32; // hit a bounding box, not a bmodel -float DPCONTENTS_CORPSE = 64; // hit a SOLID_CORPSE entity -float DPCONTENTS_NODROP = 128; // an area where backpacks should not spawn -float DPCONTENTS_PLAYERCLIP = 256; // blocks player movement -float DPCONTENTS_MONSTERCLIP = 512; // blocks monster movement -float DPCONTENTS_DONOTENTER = 1024; // AI hint brush -float DPCONTENTS_LIQUIDSMASK = 14; // WATER | SLIME | LAVA -float DPCONTENTS_BOTCLIP = 2048; // AI hint brush -float DPCONTENTS_OPAQUE = 4096; // only fully opaque brushes get this (may be useful for line of sight checks) -float Q3SURFACEFLAG_NODAMAGE = 1; -float Q3SURFACEFLAG_SLICK = 2; // low friction surface -float Q3SURFACEFLAG_SKY = 4; // sky surface (also has NOIMPACT and NOMARKS set) -float Q3SURFACEFLAG_LADDER = 8; // climbable surface -float Q3SURFACEFLAG_NOIMPACT = 16; // projectiles should remove themselves on impact (this is set on sky) -float Q3SURFACEFLAG_NOMARKS = 32; // projectiles should not leave marks, such as decals (this is set on sky) -float Q3SURFACEFLAG_FLESH = 64; // projectiles should do a fleshy effect (blood?) on impact -float Q3SURFACEFLAG_NODRAW = 128; // compiler hint (not important to qc) -//float Q3SURFACEFLAG_HINT = 256; // compiler hint (not important to qc) -//float Q3SURFACEFLAG_SKIP = 512; // compiler hint (not important to qc) -//float Q3SURFACEFLAG_NOLIGHTMAP = 1024; // compiler hint (not important to qc) -//float Q3SURFACEFLAG_POINTLIGHT = 2048; // compiler hint (not important to qc) -float Q3SURFACEFLAG_METALSTEPS = 4096; // walking on this surface should make metal step sounds -float Q3SURFACEFLAG_NOSTEPS = 8192; // walking on this surface should not make footstep sounds -float Q3SURFACEFLAG_NONSOLID = 16384; // compiler hint (not important to qc) -//float Q3SURFACEFLAG_LIGHTFILTER = 32768; // compiler hint (not important to qc) -//float Q3SURFACEFLAG_ALPHASHADOW = 65536; // compiler hint (not important to qc) -//float Q3SURFACEFLAG_NODLIGHT = 131072; // compiler hint (not important to qc) -//float Q3SURFACEFLAG_DUST = 262144; // translucent 'light beam' effect (not important to qc) -//description: -//adds additional information after a traceline/tracebox/tracetoss call. -//also (very important) sets trace_* globals before calling .touch functions, -//this allows them to inspect the nature of the collision (for example -//determining if a projectile hit sky), clears trace_* variables for the other -//object in a touch event (that is to say, a projectile moving will see the -//trace results in its .touch function, but the player it hit will see very -//little information in the trace_ variables as it was not moving at the time) - -//DP_VIEWZOOM -//idea: LordHavoc -//darkplaces implementation: LordHavoc -//field definitions: -.float viewzoom; -//description: -//scales fov and sensitivity of player, valid range is 0 to 1 (intended for sniper rifle zooming, and such) - -//EXT_BITSHIFT -//idea: Spike -//darkplaces implementation: [515] -//builtin definitions: -float(float number, float quantity) bitshift = #218; -//description: -//multiplies number by a power of 2 corresponding to quantity (0 = *1, 1 = *2, 2 = *4, 3 = *8, -1 = /2, -2 = /4x, etc), and rounds down (due to integer math) like other bit operations do (& and | and the like). -//note: it is faster to use multiply if you are shifting by a constant, avoiding the quakec function call cost, however that does not do a floor for you. - -//FRIK_FILE -//idea: FrikaC -//darkplaces implementation: LordHavoc -//builtin definitions: -float(string s) stof = #81; // get numerical value from a string -float(string filename, float mode) fopen = #110; // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE), returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason -void(float fhandle) fclose = #111; // closes a file -string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring -void(float fhandle, string s, ...) fputs = #113; // writes a line of text to the end of the file -float(string s) strlen = #114; // returns how many characters are in a string -string(string s1, string s2, ...) strcat = #115; // concatenates two or more strings (for example "abc", "def" would return "abcdef") and returns as a tempstring -string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring - see FTE_STRINGS for enhanced version -vector(string s) stov = #117; // returns vector value from a string -string(string s, ...) strzone = #118; // makes a copy of a string into the string zone and returns it, this is often used to keep around a tempstring for longer periods of time (tempstrings are replaced often) -void(string s) strunzone = #119; // removes a copy of a string from the string zone (you can not use that string again or it may crash!!!) -//constants: -float FILE_READ = 0; -float FILE_APPEND = 1; -float FILE_WRITE = 2; -//cvars: -//pr_zone_min_strings : default 64 (64k), min 64 (64k), max 8192 (8mb) -//description: -//provides text file access functions and string manipulation functions, note that you may want to set pr_zone_min_strings in the worldspawn function if 64k is not enough string zone space. -// -//NOTE: strzone functionality is partially superseded by -//DP_QC_UNLIMITEDTEMPSTRINGS when longterm storage is not needed -//NOTE: substring is upgraded by FTE_STRINGS extension with negative start/length handling identical to php 5.2.0 - -//FTE_CSQC_SKELETONOBJECTS -//idea: Spike, LordHavoc -//darkplaces implementation: LordHavoc -//builtin definitions: -// all skeleton numbers are 1-based (0 being no skeleton) -// all bone numbers are 1-based (0 being invalid) -float(float modlindex) skel_create = #263; // create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex, as the skeleton uses the hierarchy from the model. -float(float skel, entity ent, float modlindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // blend in a percentage of standard animation, 0 replaces entirely, 1 does nothing, 0.5 blends half, etc, and this only alters the bones in the specified range for which out of bounds values like 0,100000 are safe (uses .frame, .frame2, .frame3, .frame4, .lerpfrac, .lerpfrac3, .lerpfrac4, .frame1time, .frame2time, .frame3time, .frame4time), returns skel on success, 0 on failure -float(float skel) skel_get_numbones = #265; // returns how many bones exist in the created skeleton, 0 if skeleton does not exist -string(float skel, float bonenum) skel_get_bonename = #266; // returns name of bone (as a tempstring), "" if invalid bonenum (< 1 for example) or skeleton does not exist -float(float skel, float bonenum) skel_get_boneparent = #267; // returns parent num for supplied bonenum, 0 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this) -float(float skel, string tagname) skel_find_bone = #268; // get number of bone with specified name, 0 on failure, bonenum (1-based) on success, same as using gettagindex but takes modelindex instead of entity -vector(float skel, float bonenum) skel_get_bonerel = #269; // get matrix of bone in skeleton relative to its parent - sets v_forward, v_right, v_up, returns origin (relative to parent bone) -vector(float skel, float bonenum) skel_get_boneabs = #270; // get matrix of bone in skeleton in model space - sets v_forward, v_right, v_up, returns origin (relative to entity) -void(float skel, float bonenum, vector org) skel_set_bone = #271; // set matrix of bone relative to its parent, reads v_forward, v_right, v_up, takes origin as parameter (relative to parent bone) -void(float skel, float bonenum, vector org) skel_mul_bone = #272; // transform bone matrix (relative to its parent) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bone) -void(float skel, float startbone, float endbone, vector org) skel_mul_bones = #273; // transform bone matrices (relative to their parents) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bones) -void(float skeldst, float skelsrc, float startbone, float endbone) skel_copybones = #274; // copy bone matrices (relative to their parents) from one skeleton to another, useful for copying a skeleton to a corpse -void(float skel) skel_delete = #275; // deletes skeleton at the beginning of the next frame (you can add the entity, delete the skeleton, renderscene, and it will still work) -float(float modlindex, string framename) frameforname = #276; // finds number of a specified frame in the animation, returns -1 if no match found -float(float modlindex, float framenum) frameduration = #277; // returns the intended play time (in seconds) of the specified framegroup, if it does not exist the result is 0, if it is a single frame it may be a small value around 0.1 or 0. -//fields: -.float skeletonindex; // active skeleton overriding standard animation on model -.float frame; // primary framegroup animation (strength = 1 - lerpfrac - lerpfrac3 - lerpfrac4) -.float frame2; // secondary framegroup animation (strength = lerpfrac) -.float frame3; // tertiary framegroup animation (strength = lerpfrac3) -.float frame4; // quaternary framegroup animation (strength = lerpfrac4) -.float lerpfrac; // strength of framegroup blend -.float lerpfrac3; // strength of framegroup blend -.float lerpfrac4; // strength of framegroup blend -.float frame1time; // start time of framegroup animation -.float frame2time; // start time of framegroup animation -.float frame3time; // start time of framegroup animation -.float frame4time; // start time of framegroup animation -//description: -//this extension provides a way to do complex skeletal animation on an entity. -// -//see also DP_SKELETONOBJECTS (this extension implemented on server as well as client) -// -//notes: -//each model contains its own skeleton, reusing a skeleton with incompatible models will yield garbage (or not render). -//each model contains its own animation data, you can use animations from other model files (for example saving out all character animations as separate model files). -//if an engine supports loading an animation-only file format such as .md5anim in FTEQW, it can be used to animate any model with a compatible skeleton. -//proper use of this extension may require understanding matrix transforms (v_forward, v_right, v_up, origin), and you must keep in mind that v_right is negative for this purpose. -// -//features include: -//multiple animations blended together. -//animating a model with animations from another model with a compatible skeleton. -//restricting animation blends to certain bones of a model - for example independent animation of legs, torso, head. -//custom bone controllers - for example making eyes track a target location. -// -// -// -//example code follows... -// -//this helper function lets you identify (by parentage) what group a bone -//belongs to - for example "torso", "leftarm", would return 1 ("torso") for -//all children of the bone named "torso", unless they are children of -//"leftarm" (which is a child of "torso") which would return 2 instead... -float(float skel, float bonenum, string g1, string g2, string g3, string g4, string g5, string g6) example_skel_findbonegroup = -{ - local string bonename; - while (bonenum >= 0) - { - bonename = skel_get_bonename(skel, bonenum); - if (bonename == g1) return 1; - if (bonename == g2) return 2; - if (bonename == g3) return 3; - if (bonename == g4) return 4; - if (bonename == g5) return 5; - if (bonename == g6) return 6; - bonenum = skel_get_boneparent(skel, bonenum); - } - return 0; -}; -// create a skeletonindex for our player using current modelindex -void() example_skel_player_setup = -{ - self.skeletonindex = skel_create(self.modelindex); -}; -// setup bones of skeleton based on an animation -// note: animmodelindex can be a different model than self.modelindex -void(float animmodelindex, float framegroup, float framegroupstarttime) example_skel_player_update_begin = -{ - // start with our standard animation - self.frame = framegroup; - self.frame2 = 0; - self.frame3 = 0; - self.frame4 = 0; - self.frame1time = framegroupstarttime; - self.frame2time = 0; - self.frame3time = 0; - self.frame4time = 0; - self.lerpfrac = 0; - self.lerpfrac3 = 0; - self.lerpfrac4 = 0; - skel_build(self.skeletonindex, self, animmodelindex, 0, 0, 100000); -}; -// apply a different framegroup animation to bones with a specified parent -void(float animmodelindex, float framegroup, float framegroupstarttime, float blendalpha, string groupbonename, string excludegroupname1, string excludegroupname2) example_skel_player_update_applyoverride = -{ - local float bonenum; - local float numbones; - self.frame = framegroup; - self.frame2 = 0; - self.frame3 = 0; - self.frame4 = 0; - self.frame1time = framegroupstarttime; - self.frame2time = 0; - self.frame3time = 0; - self.frame4time = 0; - self.lerpfrac = 0; - self.lerpfrac3 = 0; - self.lerpfrac4 = 0; - bonenum = 0; - numbones = skel_get_numbones(self.skeletonindex); - while (bonenum < numbones) - { - if (example_skel_findbonegroup(self.skeletonindex, bonenum, groupbonename, excludegroupname1, excludegroupname2, "", "", "") == 1) - skel_build(self.skeletonindex, self, animmodelindex, 1 - blendalpha, bonenum, bonenum + 1); - bonenum = bonenum + 1; - } -}; -// make eyes point at a target location, be sure v_forward, v_right, v_up are set correctly before calling -void(vector eyetarget, string bonename) example_skel_player_update_eyetarget = -{ - local float bonenum; - local vector ang; - local vector oldforward, oldright, oldup; - local vector relforward, relright, relup, relorg; - local vector boneforward, boneright, boneup, boneorg; - local vector parentforward, parentright, parentup, parentorg; - local vector u, v; - local vector modeleyetarget; - bonenum = skel_find_bone(self.skeletonindex, bonename) - 1; - if (bonenum < 0) - return; - oldforward = v_forward; - oldright = v_right; - oldup = v_up; - v = eyetarget - self.origin; - modeleyetarget_x = v * v_forward; - modeleyetarget_y = 0-v * v_right; - modeleyetarget_z = v * v_up; - // this is an eyeball, make it point at the target location - // first get all the data we can... - relorg = skel_get_bonerel(self.skeletonindex, bonenum); - relforward = v_forward; - relright = v_right; - relup = v_up; - boneorg = skel_get_boneabs(self.skeletonindex, bonenum); - boneforward = v_forward; - boneright = v_right; - boneup = v_up; - parentorg = skel_get_boneabs(self.skeletonindex, skel_get_boneparent(self.skeletonindex, bonenum)); - parentforward = v_forward; - parentright = v_right; - parentup = v_up; - // get the vector from the eyeball to the target - u = modeleyetarget - boneorg; - // now transform it inversely by the parent matrix to produce new rel vectors - v_x = u * parentforward; - v_y = u * parentright; - v_z = u * parentup; - ang = vectoangles2(v, relup); - ang_x = 0 - ang_x; - makevectors(ang); - // set the relative bone matrix - skel_set_bone(self.skeletonindex, bonenum, relorg); - // restore caller's v_ vectors - v_forward = oldforward; - v_right = oldright; - v_up = oldup; -}; -// delete skeleton when we're done with it -// note: skeleton remains valid until next frame when it is really deleted -void() example_skel_player_delete = -{ - skel_delete(self.skeletonindex); - self.skeletonindex = 0; -}; -// -// END OF EXAMPLES FOR FTE_CSQC_SKELETONOBJECTS -// - -//KRIMZON_SV_PARSECLIENTCOMMAND -//idea: KrimZon -//darkplaces implementation: KrimZon, LordHavoc -//engine-called QC prototypes: -//void(string s) SV_ParseClientCommand; -//builtin definitions: -void(entity e, string s) clientcommand = #440; -float(string s) tokenize = #441; -string(float n) argv = #442; -//description: -//provides QC the ability to completely control server interpretation of client commands ("say" and "color" for example, clientcommand is necessary for this and substring (FRIK_FILE) is useful) as well as adding new commands (tokenize, argv, and stof (FRIK_FILE) are useful for this)), whenever a clc_stringcmd is received the QC function is called, and it is up to the QC to decide what (if anything) to do with it - -//NEH_CMD_PLAY2 -//idea: Nehahra -//darkplaces implementation: LordHavoc -//description: -//shows that the engine supports the "play2" console command (plays a sound without spatialization). - -//NEH_RESTOREGAME -//idea: Nehahra -//darkplaces implementation: LordHavoc -//engine-called QC prototypes: -//void() RestoreGame; -//description: -//when a savegame is loaded, this function is called - -//NEXUIZ_PLAYERMODEL -//idea: Nexuiz -//darkplaces implementation: Black -//console commands: -//playermodel <name> - FIXME: EXAMPLE NEEDED -//playerskin <name> - FIXME: EXAMPLE NEEDED -//field definitions: -.string playermodel; // name of player model sent by client -.string playerskin; // name of player skin sent by client -//description: -//these client properties are used by Nexuiz. - -//NXQ_GFX_LETTERBOX -//idea: nxQuake -//darkplaces implementation: LordHavoc -//description: -//shows that the engine supports the "r_letterbox" console variable, set to values in the range 0-100 this restricts the view vertically (and turns off sbar and crosshair), value is a 0-100 percentage of how much to constrict the view, <=0 = normal view height, 25 = 75% of normal view height, 50 = 50%, 75 = 25%, >=100 = no view - -//PRYDON_CLIENTCURSOR -//idea: FrikaC -//darkplaces implementation: LordHavoc -//effects bit: -float EF_SELECTABLE = 16384; // allows cursor to highlight entity (brighten) -//field definitions: -.float cursor_active; // true if cl_prydoncursor mode is on -.vector cursor_screen; // screen position of cursor as -1 to +1 in _x and _y (_z unused) -.vector cursor_trace_start; // position of camera -.vector cursor_trace_endpos; // position of cursor in world (as traced from camera) -.entity cursor_trace_ent; // entity the cursor is pointing at (server forces this to world if the entity is currently free at time of receipt) -//cvar definitions: -//cl_prydoncursor (0/1+, default 0, 1 and above use cursors named gfx/prydoncursor%03i.lmp - or .tga and such if DP_GFX_EXTERNALTEXTURES is implemented) -//description: -//shows that the engine supports the cl_prydoncursor cvar, this puts a clientside mouse pointer on the screen and feeds input to the server for the QuakeC to use as it sees fit. -//the mouse pointer triggers button4 if cursor is at left edge of screen, button5 if at right edge of screen, button6 if at top edge of screen, button7 if at bottom edge of screen. -//the clientside trace skips transparent entities (except those marked EF_SELECTABLE). -//the selected entity highlights only if EF_SELECTABLE is set, a typical selection method would be doubling the brightness of the entity by some means (such as colormod[] *= 2). -//intended to be used by Prydon Gate. - -//TENEBRAE_GFX_DLIGHTS -//idea: Tenebrae -//darkplaces implementation: LordHavoc -//fields: -.float light_lev; // radius (does not affect brightness), typical value 350 -.vector color; // color (does not affect radius), typical value '1 1 1' (bright white), can be up to '255 255 255' (nuclear blast) -.float style; // light style (like normal light entities, flickering torches or switchable, etc) -.float pflags; // flags (see PFLAGS_ constants) -.vector angles; // orientation of the light -.float skin; // cubemap filter number, can be 1-255 (0 is assumed to be none, and tenebrae only allows 16-255), this selects a projective light filter, a value of 1 loads cubemaps/1posx.tga and cubemaps/1negx.tga and posy, negy, posz, and negz, similar to skybox but some sides need to be rotated or flipped -//constants: -float PFLAGS_NOSHADOW = 1; // light does not cast shadows -float PFLAGS_CORONA = 2; // light has a corona flare -float PFLAGS_FULLDYNAMIC = 128; // light enable (without this set no light is produced!) -//description: -//more powerful dynamic light settings -//warning: it is best not to use cubemaps on a light entity that has a model, as using a skin number that a model does not have will cause issues in glquake, and produce warnings in darkplaces (use developer 1 to see them) -//changes compared to tenebrae (because they're too 'leet' for standards): -//note: networking should send entities with PFLAGS_FULLDYNAMIC set even if they have no model (lights in general do not have a model, nor should they) -//EF_FULLDYNAMIC effects flag replaced by PFLAGS_FULLDYNAMIC flag (EF_FULLDYNAMIC conflicts with EF_NODRAW) - -//TW_SV_STEPCONTROL -//idea: Transfusion -//darkplaces implementation: LordHavoc -//cvars: -//sv_jumpstep (0/1, default 1) -//sv_stepheight (default 18) -//description: -//sv_jumpstep allows stepping up onto stairs while airborn, sv_stepheight controls how high a single step can be. - -//FTE_QC_CHECKPVS -//idea: Urre -//darkplaces implementation: divVerent -//builtin definitions: -float checkpvs(vector viewpos, entity viewee) = #240; -//description: -//returns true if viewee can be seen from viewpos according to PVS data - -//FTE_STRINGS -//idea: many -//darkplaces implementation: KrimZon -//builtin definitions: -float(string str, string sub, float startpos) strstrofs = #221; // returns the offset into a string of the matching text, or -1 if not found, case sensitive -float(string str, float ofs) str2chr = #222; // returns the character at the specified offset as an integer, or 0 if an invalid index, or byte value - 256 if the engine supports UTF8 and the byte is part of an extended character -string(float c, ...) chr2str = #223; // returns a string representing the character given, if the engine supports UTF8 this may be a multi-byte sequence (length may be more than 1) for characters over 127. -string(float ccase, float calpha, float cnum, string s, ...) strconv = #224; // reformat a string with special color characters in the font, DO NOT USE THIS ON UTF8 ENGINES (if you are lucky they will emit ^4 and such color codes instead), the parameter values are 0=same/1=lower/2=upper for ccase, 0=same/1=white/2=red/5=alternate/6=alternate-alternate for redalpha, 0=same/1=white/2=red/3=redspecial/4=whitespecial/5=alternate/6=alternate-alternate for rednum. -string(float chars, string s, ...) strpad = #225; // pad string with spaces to a specified length, < 0 = left padding, > 0 = right padding -string(string info, string key, string value, ...) infoadd = #226; // sets or adds a key/value pair to an infostring - note: forbidden characters are \ and " -string(string info, string key) infoget = #227; // gets a key/value pair in an infostring, returns value or null if not found -float(string s1, string s2, float len) strncmp = #228; // compare two strings up to the specified number of characters, if their length differs and is within the specified limit the result will be negative, otherwise it is the difference in value of their first non-matching character. -float(string s1, string s2) strcasecmp = #229; // compare two strings with case-insensitive matching, characters a-z are considered equivalent to the matching A-Z character, no other differences, and this does not consider special characters equal even if they look similar -float(string s1, string s2, float len) strncasecmp = #230; // same as strcasecmp but with a length limit, see strncmp -//string(string s, float start, float length) substring = #116; // see note below -//description: -//various string manipulation functions -//note: substring also exists in FRIK_FILE but this extension adds negative start and length as valid cases (see note above), substring is consistent with the php 5.2.0 substr function (not 5.2.3 behavior) -//substring returns a section of a string as a tempstring, if given negative -// start the start is measured back from the end of the string, if given a -// negative length the length is the offset back from the end of the string to -// stop at, rather than being relative to start, if start is negative and -// larger than length it is treated as 0. -// examples of substring: -// substring("blah", -3, 3) returns "lah" -// substring("blah", 3, 3) returns "h" -// substring("blah", -10, 3) returns "bla" -// substring("blah", -10, -3) returns "b" - -//DP_CON_BESTWEAPON -//idea: many -//darkplaces implementation: divVerent -//description: -//allows QC to register weapon properties for use by the bestweapon command, for mods that change required ammo count or type for the weapons -//it is done using console commands sent via stuffcmd: -// register_bestweapon quake -// register_bestweapon clear -// register_bestweapon <shortname> <impulse> <itemcode> <activeweaponcode> <ammostat> <ammomin> -//for example, this is what Quake uses: -// register_bestweapon 1 1 4096 4096 6 0 // STAT_SHELLS is 6 -// register_bestweapon 2 2 1 1 6 1 -// register_bestweapon 3 3 2 2 6 1 -// register_bestweapon 4 4 4 4 7 1 // STAT_NAILS is 7 -// register_bestweapon 5 5 8 8 7 1 -// register_bestweapon 6 6 16 16 8 1 // STAT_ROCKETS is 8 -// register_bestweapon 7 7 32 32 8 1 -// register_bestweapon 8 8 64 64 9 1 // STAT_CELLS is 9 -//after each map client initialization, this is reset back to Quake settings. So you should send these data in ClientConnect. -//also, this extension introduces a new "cycleweapon" command to the user. - -//DP_QC_STRINGBUFFERS -//idea: ?? -//darkplaces implementation: LordHavoc -//functions to manage string buffer objects - that is, arbitrary length string arrays that are handled by the engine -float() buf_create = #460; -void(float bufhandle) buf_del = #461; -float(float bufhandle) buf_getsize = #462; -void(float bufhandle_from, float bufhandle_to) buf_copy = #463; -void(float bufhandle, float sortpower, float backward) buf_sort = #464; -string(float bufhandle, string glue) buf_implode = #465; -string(float bufhandle, float string_index) bufstr_get = #466; -void(float bufhandle, float string_index, string str) bufstr_set = #467; -float(float bufhandle, string str, float order) bufstr_add = #468; -void(float bufhandle, float string_index) bufstr_free = #469; - -//DP_QC_STRINGBUFFERS_CVARLIST -//idea: divVerent -//darkplaces implementation: divVerent -//functions to list cvars and store their names into a stringbuffer -//cvars that start with pattern but not with antipattern will be stored into the buffer -void(float bufhandle, string pattern, string antipattern) buf_cvarlist = #517; - -//DP_QC_STRREPLACE -//idea: Sajt -//darkplaces implementation: Sajt -//builtin definitions: -string(string search, string replace, string subject) strreplace = #484; -string(string search, string replace, string subject) strireplace = #485; -//description: -//strreplace replaces all occurrences of 'search' with 'replace' in the string 'subject', and returns the result as a tempstring. -//strireplace does the same but uses case-insensitive matching of the 'search' term -// -//DP_QC_CRC16 -//idea: divVerent -//darkplaces implementation: divVerent -//Some hash function to build hash tables with. This has to be be the CRC-16-CCITT that is also required for the QuakeWorld download protocol. -//When caseinsensitive is set, the CRC is calculated of the lower cased string. -float(float caseinsensitive, string s, ...) crc16 = #494; - -//DP_SV_SHUTDOWN -//idea: divVerent -//darkplaces implementation: divVerent -//A function that gets called just before progs exit. To save persistent data from. -//It is not called on a crash or error. -//void SV_Shutdown(); - -//EXT_CSQC -// #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC) -void(float index, float type, ...) addstat = #232; - -//ZQ_PAUSE -//idea: ZQuake -//darkplaces implementation: GreEn`mArine -//builtin definitions: -void(float pause) setpause = #531; -//function definitions: -//void(float elapsedtime) SV_PausedTic; -//description: -//during pause the world is not updated (time does not advance), SV_PausedTic is the only function you can be sure will be called at regular intervals during the pause, elapsedtime is the current system time in seconds since the pause started (not affected by slowmo or anything else). -// -//calling setpause(0) will end a pause immediately. -// -//Note: it is worth considering that network-related functions may be called during the pause (including customizeentityforclient for example), and it is also important to consider the continued use of the KRIMZON_SV_PARSECLIENTCOMMAND extension while paused (chatting players, etc), players may also join/leave during the pause. In other words, the only things that are not called are think and other time-related functions. - - - - -// EXPERIMENTAL (not finalized) EXTENSIONS: - -//DP_PHYSICS -//idea: LordHavoc -//darkplaces implementation: LordHavoc, divVerent -//constant definitions: -float SOLID_PHYSICS_BOX = 32; -float SOLID_PHYSICS_SPHERE = 33; -float SOLID_PHYSICS_CAPSULE = 34; -float MOVETYPE_PHYSICS = 32; -float JOINTTYPE_POINT = 1; // point; uses origin (anchor) -float JOINTTYPE_HINGE = 2; // hinge; uses origin (anchor) and angles (axis) -float JOINTTYPE_SLIDER = 3; // slider; uses angles (axis) -float JOINTTYPE_UNIVERSAL = 4; // universal; uses origin (anchor) and angles (forward is axis1, up is axis2) -float JOINTTYPE_HINGE2 = 5; // hinge2; uses origin (anchor), angles (axis1), velocity (axis2) -//field definitions: -.float mass; -.float jointtype; // see JOINTTYPE_ definitions above -// common joint properties: -// .entity aiment, enemy; // connected objects -// .vector movedir; -// for a spring: -// movedir_x = spring constant (force multiplier, must be > 0) -// movedir_y = spring dampening constant to prevent oscillation (must be > 0) -// movedir_z = spring stop position (+/-) -// for a motor: -// movedir_x = desired motor velocity -// movedir_y = -1 * max motor force to use -// movedir_z = stop position (+/-), set to 0 for no stop -// note that ODE does not support both in one anyway -//description: -//various physics properties can be defined in an entity and are executed via -//ODE - -//DP_CRYPTO -//idea: divVerent -//darkplaces implementation: divVerent -//field definitions: (SVQC) -.string crypto_keyfp; // fingerprint of CA key the player used to authenticate, or string_null if not verified -.string crypto_mykeyfp; // fingerprint of CA key the server used to authenticate to the player, or string_null if not verified -.string crypto_idfp; // fingerprint of ID used by the player entity, or string_null if not identified -.string crypto_encryptmethod; // the string "AES128" if encrypting, and string_null if plaintext -.string crypto_signmethod; // the string "HMAC-SHA256" if signing, and string_null if plaintext -// there is no field crypto_myidfp, as that info contains no additional information the QC may have a use for -//builtin definitions: (SVQC) -float(string url, float id, string content_type, string delim, float buf, float keyid) crypto_uri_postbuf = #513; -//description: -//use -1 as buffer handle to justs end delim as postdata diff --git a/qcsrc/server/frags.txt b/qcsrc/server/frags.txt deleted file mode 100644 index 1daf099356..0000000000 --- a/qcsrc/server/frags.txt +++ /dev/null @@ -1,7 +0,0 @@ -TODO: remove the .frags field, except for the following values: - -0 = regular player --2 = ???, used by arena --666 = spectator - -Anything else shall go through PlayerScore! diff --git a/qcsrc/server/func_breakable.qc b/qcsrc/server/func_breakable.qc index 44605ddeee..4d29b014fa 100644 --- a/qcsrc/server/func_breakable.qc +++ b/qcsrc/server/func_breakable.qc @@ -37,7 +37,7 @@ void func_breakable_damage(entity inflictor, entity attacker, float damage, floa // func_breakable // - basically func_assault_destructible for general gameplay use // -void LaunchDebris (string debrisname, vector force) = +void LaunchDebris (string debrisname, vector force) { local entity dbr; @@ -65,7 +65,7 @@ void LaunchDebris (string debrisname, vector force) = if(dbr.damageforcescale) dbr.takedamage = DAMAGE_YES; SUB_SetFade(dbr, time + self.debristime + crandom() * self.debristimejitter, self.debrisfadetime); -}; +} void func_breakable_colormod() { @@ -83,7 +83,7 @@ void func_breakable_colormod() void func_breakable_look_destroyed() { - local float floor_z; + float floor_z; if(self.solid == SOLID_BSP) // in case a misc_follow moved me, save the current origin first self.dropped_origin = self.origin; @@ -114,6 +114,7 @@ void func_breakable_behave_destroyed() { self.health = self.max_health; self.takedamage = DAMAGE_NO; + self.bot_attack = FALSE; self.event_damage = SUB_Null; self.state = 1; func_breakable_colormod(); @@ -122,9 +123,16 @@ void func_breakable_behave_destroyed() void func_breakable_behave_restore() { self.health = self.max_health; + if(self.sprite) + { + WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health); + WaypointSprite_UpdateHealth(self.sprite, self.health); + } self.takedamage = DAMAGE_AIM; + self.bot_attack = TRUE; self.event_damage = func_breakable_damage; self.state = 0; + self.nextthink = 0; // cancel auto respawn func_breakable_colormod(); } @@ -156,7 +164,7 @@ void func_breakable_destroy() { func_breakable_destroyed(); if(self.noise) - sound (self, CHAN_AUTO, self.noise, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTN_NORM); if(self.dmg) RadiusDamage(self, activator, self.dmg, self.dmg_edge, self.dmg_radius, self, self.dmg_force, DEATH_HURTTRIGGER, world); @@ -164,6 +172,12 @@ void func_breakable_destroy() { if(self.cnt) pointparticles(self.cnt, self.absmin * 0.5 + self.absmax * 0.5, '0 0 0', self.count); + if(self.respawntime) + { + self.think = func_breakable_restore; + self.nextthink = time + self.respawntime + crandom() * self.respawntimejitter; + } + oldmsg = self.message; self.message = ""; SUB_UseTargets(); @@ -180,9 +194,12 @@ void func_breakable_damage(entity inflictor, entity attacker, float damage, floa if(self.team) if(attacker.team == self.team) return; + self.health = self.health - damage; if(self.sprite) + { WaypointSprite_Ping(self.sprite); - self.health = self.health - damage; + WaypointSprite_UpdateHealth(self.sprite, self.health); + } func_breakable_colormod(); if(self.health <= 0) @@ -252,3 +269,8 @@ void spawnfunc_func_breakable() { self.reset = func_breakable_reset; func_breakable_reset(); } + +// for use in maps with a "model" key set +void spawnfunc_misc_breakablemodel() { + spawnfunc_func_breakable(); +} diff --git a/qcsrc/server/g_damage.qc b/qcsrc/server/g_damage.qc index 6ab29006d2..bd4426c3aa 100644 --- a/qcsrc/server/g_damage.qc +++ b/qcsrc/server/g_damage.qc @@ -41,8 +41,6 @@ void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad Net_LinkEntity(e, FALSE, 0.2, Damage_DamageInfo_SendEntity); } -#define DAMAGE_CENTERPRINT_SPACER NEWLINES - float checkrules_firstblood; float yoda; @@ -61,7 +59,7 @@ float damage_headshotbonus; // bonus multiplier for head shots, set to 0 after u float IsDifferentTeam(entity a, entity b) { - if(teams_matter) + if(teamplay) { if(a.team == b.team) return 0; @@ -102,7 +100,7 @@ void UpdateFrags(entity player, float f) // NOTE: f=0 means still count as a (positive) kill, but count no frags for it void W_SwitchWeapon_Force(entity e, float w); -void GiveFrags (entity attacker, entity targ, float f) +void GiveFrags (entity attacker, entity targ, float f, float deathtype) { float w; @@ -120,14 +118,14 @@ void GiveFrags (entity attacker, entity targ, float f) { // teamkill PlayerScore_Add(attacker, SP_KILLS, -1); // or maybe add a teamkills field? - PlayerStats_Event(attacker, PLAYERSTATS_KILLS, -1); } } else { // regular frag PlayerScore_Add(attacker, SP_KILLS, 1); - PlayerStats_Event(attacker, PLAYERSTATS_KILLS, 1); + if(targ.playerid) + PlayerStats_Event(attacker, sprintf("kills-%d", targ.playerid), 1); } PlayerScore_Add(targ, SP_DEATHS, 1); @@ -139,19 +137,36 @@ void GiveFrags (entity attacker, entity targ, float f) if(targ != attacker) // not for suicides if(g_weaponarena_random) { - // after a frag, choose another random weapon set - if(inWarmupStage) - w = warmup_start_weapons; - else - w = start_weapons; + // after a frag, exchange the current weapon (or the culprit, if detectable) by a new random weapon + float culprit; + culprit = DEATH_WEAPONOF(deathtype); + if(!culprit || !(attacker.weapons & W_WeaponBit(culprit))) + culprit = attacker.weapon; - attacker.weapons = randombits(w - (w & W_WeaponBit(attacker.weapon)), g_weaponarena_random, TRUE); - if(attacker.weapons < 0) + if(g_weaponarena_random_with_laser && culprit == WEPBIT_LASER) { - // error from randombits: no weapon available - // this means we can just give ALL weapons - attacker.weapons = w; + // no exchange } + else + { + if(inWarmupStage) + w = warmup_start_weapons; + else + w = start_weapons; + + // all others (including the culprit): remove + w &~= attacker.weapons; + + // among the remaining ones, choose one by random + w = randombits(w, 1, FALSE); + if(w) + { + attacker.weapons |= w; + attacker.weapons &~= W_WeaponBit(culprit); + } + } + + // after a frag, choose another random weapon set if not(attacker.weapons & W_WeaponBit(attacker.weapon)) W_SwitchWeapon_Force(attacker, w_getbestweapon(attacker)); } @@ -186,6 +201,8 @@ void GiveFrags (entity attacker, entity targ, float f) { if(!lms_next_place) lms_next_place = player_count; + else + lms_next_place = min(lms_next_place, player_count); PlayerScore_Add(targ, SP_LMS_RANK, lms_next_place); // won't ever spawn again --lms_next_place; } @@ -204,6 +221,44 @@ void GiveFrags (entity attacker, entity targ, float f) UpdateFrags(attacker, f); } +string Obituary_ExtraFragInfo(entity player) // Extra fragmessage information +{ + string health_output; + string ping_output; + string handicap_output; + string output; + + if(autocvar_sv_fraginfo && ((autocvar_sv_fraginfo == 2) || inWarmupStage)) + { + // health/armor of attacker (person who killed you) + if(autocvar_sv_fraginfo_stats && (player.health >= 1)) + health_output = strcat("^7(Health ^1", ftos(rint(player.health)), "^7 / Armor ^2", ftos(rint(player.armorvalue)), "^7)"); + + // ping display + if(autocvar_sv_fraginfo_ping) + ping_output = ((clienttype(player) == CLIENTTYPE_BOT) ? "^2Bot" : strcat("Ping ", ((player.ping >= 150) ? "^1" : "^2"), ftos(rint(player.ping)), "ms")); + + // handicap display + if(autocvar_sv_fraginfo_handicap) + { + if(autocvar_sv_fraginfo_handicap == 2) + handicap_output = strcat(output, strcat("Handicap ^2", ((player.cvar_cl_handicap <= 1) ? "Off" : ftos(rint(player.cvar_cl_handicap))))); + else if(player.cvar_cl_handicap) // with _handicap 1, only show this if there actually is a handicap enabled. + handicap_output = strcat("Handicap ^2", ftos(rint(player.cvar_cl_handicap))); + } + + // format the string + output = strcat(health_output, (health_output ? ((ping_output || handicap_output) ? " ^7(" : "") : ((ping_output || handicap_output) ? "^7(" : "")), + ping_output, (handicap_output ? "^7 / " : ""), + handicap_output, ((ping_output || handicap_output) ? "^7)" : "")); + + // add new line to the beginning if there is a message + if(output) { output = strcat("\n", output); } + } + + return output; +} + string AppendItemcodes(string s, entity player) { float w; @@ -250,8 +305,7 @@ void LogDeath(string mode, float deathtype, entity killer, entity killed) void Send_KillNotification (string s1, string s2, string s3, float msg, float type) { WriteByte(MSG_ALL, SVC_TEMPENTITY); - WriteByte(MSG_ALL, TE_CSQC_NOTIFY); - WriteByte(MSG_ALL, CSQC_KILLNOTIFY); + WriteByte(MSG_ALL, TE_CSQC_KILLNOTIFY); WriteString(MSG_ALL, s1); WriteString(MSG_ALL, s2); WriteString(MSG_ALL, s3); @@ -260,15 +314,14 @@ void Send_KillNotification (string s1, string s2, string s3, float msg, float ty } // Function is used to send a generic centerprint whose content CSQC gets to decide (gentle version or not in the below cases) -void Send_CSQC_Centerprint(entity e, string s1, string s2, float msg, float type) +void Send_CSQC_KillCenterprint(entity e, string s1, string s2, float msg, float type) { if (clienttype(e) == CLIENTTYPE_REAL) { msg_entity = e; WRITESPECTATABLE_MSG_ONE({ WriteByte(MSG_ONE, SVC_TEMPENTITY); - WriteByte(MSG_ONE, TE_CSQC_NOTIFY); - WriteByte(MSG_ONE, CSQC_CENTERPRINT); + WriteByte(MSG_ONE, TE_CSQC_KILLCENTERPRINT); WriteString(MSG_ONE, s1); WriteString(MSG_ONE, s2); WriteShort(MSG_ONE, msg); @@ -282,13 +335,9 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype) string s, a, msg; float w, type; - if (targ.classname == "player" || targ.classname == "corpse") + if (targ.classname == "player") { - if (targ.classname == "corpse") - s = "A corpse"; - else - s = targ.netname; - + s = targ.netname; a = attacker.netname; if (targ == attacker) // suicides @@ -296,17 +345,17 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype) if (deathtype == DEATH_TEAMCHANGE || deathtype == DEATH_AUTOTEAMCHANGE) msg = ColoredTeamName(targ.team); // TODO: check if needed? if(!g_cts) // no "killed your own dumb self" message in CTS - Send_CSQC_Centerprint(targ, msg, "", deathtype, MSG_SUICIDE); + Send_CSQC_KillCenterprint(targ, msg, "", deathtype, MSG_SUICIDE); if(deathtype != DEATH_TEAMCHANGE && deathtype != DEATH_QUIET) { LogDeath("suicide", deathtype, targ, targ); - GiveFrags(attacker, targ, -1); + GiveFrags(attacker, targ, -1, deathtype); } if (targ.killcount > 2) msg = ftos(targ.killcount); - if(teams_matter && deathtype == DEATH_MIRRORDAMAGE) + if(teamplay && deathtype == DEATH_MIRRORDAMAGE) { if(attacker.team == COLOR_TEAM1) deathtype = KILL_TEAM_RED; @@ -316,18 +365,18 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype) Send_KillNotification(s, msg, ftos(w), deathtype, MSG_SUICIDE); } - else if (attacker.classname == "player" || attacker.classname == "gib") + else if (attacker.classname == "player") { - if(teams_matter && attacker.team == targ.team) + if(!IsDifferentTeam(attacker, targ)) { if(attacker.team == COLOR_TEAM1) type = KILL_TEAM_RED; else type = KILL_TEAM_BLUE; - GiveFrags(attacker, targ, -1); + GiveFrags(attacker, targ, -1, deathtype); - Send_CSQC_Centerprint(attacker, s, "", type, MSG_KILL); + Send_CSQC_KillCenterprint(attacker, s, "", type, MSG_KILL); if (targ.killcount > 2) { msg = ftos(targ.killcount); @@ -350,16 +399,18 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype) checkrules_firstblood = TRUE; Send_KillNotification(a, "", "", KILL_FIRST_BLOOD, MSG_KILL); // TODO: make these print a newline if they dont - Send_CSQC_Centerprint(attacker, "", "", KILL_FIRST_BLOOD, MSG_KILL); - Send_CSQC_Centerprint(targ, "", "", KILL_FIRST_VICTIM, MSG_KILL); + Send_CSQC_KillCenterprint(attacker, "", "", KILL_FIRST_BLOOD, MSG_KILL); + Send_CSQC_KillCenterprint(targ, "", "", KILL_FIRST_VICTIM, MSG_KILL); + PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD, 1); + PlayerStats_Event(targ, PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM, 1); } - if((autocvar_sv_fragmessage_information_typefrag) && (targ.BUTTON_CHAT)) { - Send_CSQC_Centerprint(attacker, s, GetAdvancedDeathReports(targ), KILL_TYPEFRAG, MSG_KILL); - Send_CSQC_Centerprint(targ, a, GetAdvancedDeathReports(attacker), KILL_TYPEFRAGGED, MSG_KILL); + if(targ.BUTTON_CHAT) { + Send_CSQC_KillCenterprint(attacker, s, Obituary_ExtraFragInfo(targ), KILL_TYPEFRAG, MSG_KILL); + Send_CSQC_KillCenterprint(targ, a, Obituary_ExtraFragInfo(attacker), KILL_TYPEFRAGGED, MSG_KILL); } else { - Send_CSQC_Centerprint(attacker, s, GetAdvancedDeathReports(targ), KILL_FRAG, MSG_KILL); - Send_CSQC_Centerprint(targ, a, GetAdvancedDeathReports(attacker), KILL_FRAGGED, MSG_KILL); + Send_CSQC_KillCenterprint(attacker, s, Obituary_ExtraFragInfo(targ), KILL_FRAG, MSG_KILL); + Send_CSQC_KillCenterprint(targ, a, Obituary_ExtraFragInfo(attacker), KILL_FRAGGED, MSG_KILL); } attacker.taunt_soundtime = time + 1; @@ -379,10 +430,10 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype) { UpdateFrags(attacker, ctf_score_value("score_kill")); PlayerScore_Add(attacker, SP_CTF_FCKILLS, 1); - GiveFrags(attacker, targ, 0); // for logging + GiveFrags(attacker, targ, 0, deathtype); // for logging } else - GiveFrags(attacker, targ, 1); + GiveFrags(attacker, targ, 1, deathtype); if (targ.killcount > 2) { Send_KillNotification(s, ftos(targ.killcount), a, KILL_END_SPREE, MSG_SPREE); @@ -397,43 +448,50 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype) { Send_KillNotification(a, "", "", KILL_SPREE_3, MSG_SPREE); AnnounceTo(attacker, "03kills"); + PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_3, 1); } else if (attacker.killcount == 5) { Send_KillNotification(a, "", "", KILL_SPREE_5, MSG_SPREE); AnnounceTo(attacker, "05kills"); + PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_5, 1); } else if (attacker.killcount == 10) { Send_KillNotification(a, "", "", KILL_SPREE_10, MSG_SPREE); AnnounceTo(attacker, "10kills"); + PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_10, 1); } else if (attacker.killcount == 15) { Send_KillNotification(a, "", "", KILL_SPREE_15, MSG_SPREE); AnnounceTo(attacker, "15kills"); + PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_15, 1); } else if (attacker.killcount == 20) { Send_KillNotification(a, "", "", KILL_SPREE_20, MSG_SPREE); AnnounceTo(attacker, "20kills"); + PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_20, 1); } else if (attacker.killcount == 25) { Send_KillNotification(a, "", "", KILL_SPREE_25, MSG_SPREE); AnnounceTo(attacker, "25kills"); + PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_25, 1); } else if (attacker.killcount == 30) { Send_KillNotification(a, "", "", KILL_SPREE_30, MSG_SPREE); AnnounceTo(attacker, "30kills"); + PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_30, 1); } LogDeath("frag", deathtype, attacker, targ); } } else { - Send_CSQC_Centerprint(targ, "", "", deathtype, MSG_KILL_ACTION); + Send_CSQC_KillCenterprint(targ, "", "", deathtype, MSG_KILL_ACTION); if (deathtype == DEATH_HURTTRIGGER && inflictor.message != "") msg = inflictor.message; else if (deathtype == DEATH_CUSTOM) @@ -441,9 +499,10 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype) if(strstrofs(msg, "%", 0) < 0) msg = strcat("%s ", msg); - GiveFrags(targ, targ, -1); + GiveFrags(targ, targ, -1, deathtype); if(PlayerScore_Add(targ, SP_SCORE, 0) == -5) { AnnounceTo(targ, "botlike"); + PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_BOTLIKE, 1); } Send_KillNotification(s, msg, "", deathtype, MSG_KILL_ACTION); @@ -467,7 +526,6 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype) entity damage_targ; entity damage_inflictor; entity damage_attacker; -.float prevhitsound; void Damage (entity targ, entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) { @@ -481,7 +539,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float if (gameover || targ.killcount == -666) return; - local entity oldself; + entity oldself; oldself = self; self = targ; damage_targ = targ; @@ -523,12 +581,15 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float } else { + /* + skill based bot damage? gtfo. (tZork) if (targ.classname == "player") if (attacker.classname == "player") if (!targ.isbot) if (attacker.isbot) damage = damage * bound(0.1, (skill + 5) * 0.1, 1); - + */ + // nullify damage if teamplay is on if(deathtype != DEATH_TELEFRAG) if(attacker.classname == "player") @@ -538,7 +599,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float damage = 0; force = '0 0 0'; } - else if(teams_matter && attacker.team == targ.team) + else if(!IsDifferentTeam(attacker, targ)) { if(autocvar_teamplay_mode == 1) damage = 0; @@ -565,6 +626,31 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float else damage = autocvar_g_friendlyfire * damage; // mirrordamage will be used LATER + + if(autocvar_g_mirrordamage_virtual) + { + vector v; + v = healtharmor_applydamage(attacker.armorvalue, autocvar_g_balance_armor_blockpercent, mirrordamage); + v_z = 0; // fteqcc sucks + attacker.dmg_take += v_x; + attacker.dmg_save += v_y; + attacker.dmg_inflictor = inflictor; + mirrordamage = 0; + mirrorforce = 0; + } + + if(autocvar_g_friendlyfire_virtual) + { + vector v; + v = healtharmor_applydamage(targ.armorvalue, autocvar_g_balance_armor_blockpercent, damage); + v_z = 0; // fteqcc sucks + targ.dmg_take += v_x; + targ.dmg_save += v_y; + targ.dmg_inflictor = inflictor; + damage = 0; + if(!autocvar_g_friendlyfire_virtual_force) + force = '0 0 0'; + } } else damage = 0; @@ -598,7 +684,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float if (targ.armorvalue && (deathtype == WEP_MINSTANEX) && damage) { targ.armorvalue -= 1; - centerprint(targ, strcat(DAMAGE_CENTERPRINT_SPACER, "^3Remaining extra lives: ",ftos(targ.armorvalue))); + centerprint(targ, strcat("^3Remaining extra lives: ",ftos(targ.armorvalue))); damage = 0; targ.hitsound += 1; attacker.hitsound += 1; // TODO change this to a future specific hitsound for armor hit @@ -606,12 +692,11 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float if (DEATH_ISWEAPON(deathtype, WEP_LASER)) { damage = 0; + mirrordamage = 0; if (targ != attacker) { if ((targ.health >= 1) && (targ.classname == "player")) - centerprint(attacker, strcat(DAMAGE_CENTERPRINT_SPACER, "Secondary fire inflicts no damage!")); - damage = 0; - mirrordamage = 0; + centerprint(attacker, "Secondary fire inflicts no damage!"); force = '0 0 0'; // keep mirrorforce attacker = targ; @@ -713,40 +798,48 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float if(targ.takedamage == DAMAGE_AIM) if(targ != attacker) { - if(targ.classname == "player") + if(damage_headshotbonus > 0) { - // HEAD SHOT: - // find height of hit on player axis - // if above view_ofs and below maxs, and also in the middle half of the bbox, it is head shot - vector headmins, headmaxs, org; - org = antilag_takebackorigin(targ, time - ANTILAG_LATENCY(attacker)); - headmins = org + GetHeadshotMins(targ); - headmaxs = org + GetHeadshotMaxs(targ); - if(trace_hits_box(railgun_start, railgun_end, headmins, headmaxs)) + if(targ.classname == "player") + { + // HEAD SHOT: + // find height of hit on player axis + // if above view_ofs and below maxs, and also in the middle half of the bbox, it is head shot + vector headmins, headmaxs, org; + org = antilag_takebackorigin(targ, time - ANTILAG_LATENCY(attacker)); + headmins = org + GetHeadshotMins(targ); + headmaxs = org + GetHeadshotMaxs(targ); + if(trace_hits_box(railgun_start, railgun_end, headmins, headmaxs)) + { + deathtype |= HITTYPE_HEADSHOT; + } + } + else if(targ.classname == "turret_head") { deathtype |= HITTYPE_HEADSHOT; } + if(deathtype & HITTYPE_HEADSHOT) + damage *= 1 + damage_headshotbonus; } - else if(targ.classname == "turret_head") - { - deathtype |= HITTYPE_HEADSHOT; - } - if(deathtype & HITTYPE_HEADSHOT) - damage *= 1 + damage_headshotbonus; - if(targ.classname == "player") + entity victim; + if((targ.vehicle_flags & VHF_ISVEHICLE) && targ.owner) + victim = targ.owner; + else + victim = targ; + + if(victim.classname == "player" || victim.turrcaps_flags & TFL_TURRCAPS_ISTURRET) { - if(IsDifferentTeam(targ, attacker)) + if(IsDifferentTeam(victim, attacker)) { if(damage > 0) { - if(attacker.weapon != WEP_ELECTRO && attacker.weapon != WEP_LASER || ((attacker.weapon == WEP_ELECTRO && autocvar_g_balance_electro_lightning || attacker.weapon == WEP_LASER) && attacker.prevhitsound + autocvar_sv_hitsound_antispam_time < time)) + if(deathtype != DEATH_FIRE) { - if(targ.BUTTON_CHAT) + if(victim.BUTTON_CHAT) attacker.typehitsound += 1; else attacker.hitsound += 1; - attacker.prevhitsound = time; } damage_goodhits += 1; @@ -754,12 +847,13 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float if not(DEATH_ISSPECIAL(deathtype)) { + if(targ.classname == "player") // don't do this for vehicles if(!g_minstagib) - if(IsFlying(targ)) + if(IsFlying(victim)) yoda = 1; if(g_minstagib) - if(targ.items & IT_STRENGTH) + if(victim.items & IT_STRENGTH) yoda = 1; if(deathtype & HITTYPE_HEADSHOT) @@ -772,7 +866,9 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float else { if(deathtype != DEATH_FIRE) + { attacker.typehitsound += 1; + } if(mirrordamage > 0) if(time > attacker.teamkill_complain) { @@ -790,7 +886,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float if (vlen(force)) if (self.classname != "player" || time >= self.spawnshieldtime || g_midair) { - self.velocity = self.velocity + self.damageforcescale * force; + self.velocity = self.velocity + damage_explosion_calcpush(self.damageforcescale * force, self.velocity, autocvar_g_balance_damagepush_speedfactor); self.flags &~= FL_ONGROUND; UpdateCSQCProjectile(self); } @@ -841,17 +937,18 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float { attacker = attacker_save; if(g_minstagib) - if(mirrordamage > 0) + if(mirrordamage > 0) + { + // just lose extra LIVES, don't kill the player for mirror damage + if(attacker.armorvalue > 0) { - // just lose extra LIVES, don't kill the player for mirror damage - if(attacker.armorvalue > 0) - { - attacker.armorvalue = attacker.armorvalue - 1; - centerprint(attacker, strcat(DAMAGE_CENTERPRINT_SPACER, "^3Remaining extra lives: ",ftos(attacker.armorvalue))); - attacker.hitsound += 1; - } - mirrordamage = 0; + attacker.armorvalue = attacker.armorvalue - 1; + centerprint(attacker, strcat("^3Remaining extra lives: ",ftos(attacker.armorvalue))); + attacker.hitsound += 1; } + mirrordamage = 0; + } + force = normalize(attacker.origin + attacker.view_ofs - hitloc) * mirrorforce; Damage(attacker, inflictor, attacker, mirrordamage, DEATH_MIRRORDAMAGE, attacker.origin, force); } @@ -906,7 +1003,7 @@ float RadiusDamage (entity inflictor, entity attacker, float coredamage, float e stat_damagedone = 0; - targ = WarpZone_FindRadius (blastorigin, rad, FALSE); + targ = WarpZone_FindRadius (blastorigin, rad + MAX_DAMAGEEXTRARADIUS, FALSE); while (targ) { next = targ.chain; @@ -919,7 +1016,7 @@ float RadiusDamage (entity inflictor, entity attacker, float coredamage, float e diff = targ.WarpZone_findradius_dist; // round up a little on the damage to ensure full damage on impacts // and turn the distance into a fraction of the radius - power = 1 - ((vlen (diff) - 2) / rad); + power = 1 - ((vlen (diff) - bound(MIN_DAMAGEEXTRARADIUS, targ.damageextraradius, MAX_DAMAGEEXTRARADIUS)) / rad); //bprint(" "); //bprint(ftos(power)); //if (targ == attacker) @@ -931,13 +1028,13 @@ float RadiusDamage (entity inflictor, entity attacker, float coredamage, float e finaldmg = coredamage * power + edgedamage * (1 - power); if (finaldmg > 0) { - local float a; - local float c; - local float hits; - local float total; - local float hitratio; - local vector hitloc; - local vector myblastorigin; + float a; + float c; + float hits; + float total; + float hitratio; + vector hitloc; + vector myblastorigin; myblastorigin = WarpZone_TransformOrigin(targ, blastorigin); center = targ.origin + (targ.mins + targ.maxs) * 0.5; // if it's a player, use the view origin as reference @@ -981,33 +1078,47 @@ float RadiusDamage (entity inflictor, entity attacker, float coredamage, float e // laser force adjustments :P if(DEATH_WEAPONOF(deathtype) == WEP_LASER) { - vector vel; - - float force_zscale; - float force_velocitybiasramp; - float force_velocitybias; - - force_velocitybiasramp = autocvar_sv_maxspeed; - if(deathtype & HITTYPE_SECONDARY) - { - force_zscale = autocvar_g_balance_laser_secondary_force_zscale; - force_velocitybias = autocvar_g_balance_laser_secondary_force_velocitybias; - } - else - { - force_zscale = autocvar_g_balance_laser_primary_force_zscale; - force_velocitybias = autocvar_g_balance_laser_primary_force_velocitybias; - } - - vel = targ.velocity; - vel_z = 0; - vel = normalize(vel) * bound(0, vlen(vel) / force_velocitybiasramp, 1) * force_velocitybias; - force = - vlen(force) - * - normalize(normalize(force) + vel); - - force_z *= force_zscale; + if (targ == attacker) + { + vector vel; + + float force_zscale; + float force_velocitybiasramp; + float force_velocitybias; + + force_velocitybiasramp = autocvar_sv_maxspeed; + if(deathtype & HITTYPE_SECONDARY) + { + force_zscale = autocvar_g_balance_laser_secondary_force_zscale; + force_velocitybias = autocvar_g_balance_laser_secondary_force_velocitybias; + } + else + { + force_zscale = autocvar_g_balance_laser_primary_force_zscale; + force_velocitybias = autocvar_g_balance_laser_primary_force_velocitybias; + } + + vel = targ.velocity; + vel_z = 0; + vel = normalize(vel) * bound(0, vlen(vel) / force_velocitybiasramp, 1) * force_velocitybias; + force = + vlen(force) + * + normalize(normalize(force) + vel); + + force_z *= force_zscale; + } + else + { + if(deathtype & HITTYPE_SECONDARY) + { + force *= autocvar_g_balance_laser_secondary_force_other_scale; + } + else + { + force *= autocvar_g_balance_laser_primary_force_other_scale; + } + } } //if (targ == attacker) @@ -1180,6 +1291,10 @@ void Fire_ApplyDamage(entity e) if(e.watertype != CONTENT_LAVA) e.fire_endtime = 0; + // ice stops fire + if(e.freezetag_frozen) + e.fire_endtime = 0; + t = min(frametime, e.fire_endtime - time); d = e.fire_damagepersec * t; diff --git a/qcsrc/server/g_hook.qc b/qcsrc/server/g_hook.qc index ef379b9bc5..370f2fb987 100644 --- a/qcsrc/server/g_hook.qc +++ b/qcsrc/server/g_hook.qc @@ -47,43 +47,6 @@ And you should be done! ============================================*/ -.string aiment_classname; -.float aiment_deadflag; -void SetMovetypeFollow(entity ent, entity e) -{ - // FIXME this may not be warpzone aware - ent.movetype = MOVETYPE_FOLLOW; // make the hole follow - ent.solid = SOLID_NOT; // MOVETYPE_FOLLOW is always non-solid - this means this cannot be teleported by warpzones any more! Instead, we must notice when our owner gets teleported. - ent.aiment = e; // make the hole follow bmodel - ent.punchangle = e.angles; // the original angles of bmodel - ent.view_ofs = ent.origin - e.origin; // relative origin - ent.v_angle = ent.angles - e.angles; // relative angles - ent.aiment_classname = strzone(e.classname); - ent.aiment_deadflag = e.deadflag; -} -void UnsetMovetypeFollow(entity ent) -{ - ent.movetype = MOVETYPE_FLY; - PROJECTILE_MAKETRIGGER(ent); - ent.aiment = world; -} -float LostMovetypeFollow(entity ent) -{ -/* - if(ent.movetype != MOVETYPE_FOLLOW) - if(ent.aiment) - error("???"); -*/ - if(ent.aiment) - { - if(ent.aiment.classname != ent.aiment_classname) - return 1; - if(ent.aiment.deadflag != ent.aiment_deadflag) - return 1; - } - return 0; -} - .float hook_length; .float hook_switchweapon; @@ -99,11 +62,19 @@ void RemoveGrapplingHook(entity pl) //pl.disableclientprediction = FALSE; } +void GrapplingHookReset(void) +{ + if(self.realowner.hook == self) + RemoveGrapplingHook(self.owner); + else // in any case: + remove(self); +} + void GrapplingHookThink(); void GrapplingHook_Stop() { pointparticles(particleeffectnum("grapple_impact"), self.origin, '0 0 0', 1); - sound (self, CHAN_PROJECTILE, "weapons/hook_impact.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_SHOTS, "weapons/hook_impact.wav", VOL_BASE, ATTN_NORM); self.state = 1; self.think = GrapplingHookThink; @@ -119,12 +90,12 @@ float GrapplingHookSend(entity to, float sf) { WriteByte(MSG_ENTITY, ENT_CLIENT_HOOK); sf = sf & 0x7F; - if(sound_allowed(MSG_BROADCAST, self.owner)) + if(sound_allowed(MSG_BROADCAST, self.realowner)) sf |= 0x80; WriteByte(MSG_ENTITY, sf); if(sf & 1) { - WriteByte(MSG_ENTITY, num_for_edict(self.owner)); + WriteByte(MSG_ENTITY, num_for_edict(self.realowner)); } if(sf & 2) { @@ -145,14 +116,14 @@ void GrapplingHookThink() { float spd, dist, minlength, pullspeed, ropestretch, ropeairfriction, rubberforce, newlength, rubberforce_overstretch, s; vector dir, org, end, v0, dv, v, myorg, vs; - if(self.owner.health <= 0 || self.owner.hook != self) // how did that happen? - { // well, better fix it anyway - remove(self); + if(self.realowner.hook != self) // how did that happen? + { + error("Owner lost the hook!\n"); return; } - if(LostMovetypeFollow(self)) + if(LostMovetypeFollow(self) || intermission_running) { - RemoveGrapplingHook(self.owner); + RemoveGrapplingHook(self.realowner); return; } if(self.aiment) @@ -160,15 +131,15 @@ void GrapplingHookThink() self.nextthink = time; - s = self.owner.cvar_cl_gunalign; + s = self.realowner.cvar_cl_gunalign; if(s != 1 && s != 2 && s != 4) s = 3; // default value --s; vs = hook_shotorigin[s]; - makevectors(self.owner.v_angle); - org = self.owner.origin + self.owner.view_ofs + v_forward * vs_x + v_right * -vs_y + v_up * vs_z; - myorg = WarpZone_RefSys_TransformOrigin(self.owner, self, org); + makevectors(self.realowner.v_angle); + org = self.realowner.origin + self.realowner.view_ofs + v_forward * vs_x + v_right * -vs_y + v_up * vs_z; + myorg = WarpZone_RefSys_TransformOrigin(self.realowner, self, org); if(self.hook_length < 0) self.hook_length = vlen(myorg - self.origin); @@ -202,10 +173,10 @@ void GrapplingHookThink() if(autocvar_g_grappling_hook_tarzan) { - v = v0 = WarpZone_RefSys_TransformVelocity(self.owner, self, self.owner.velocity); + v = v0 = WarpZone_RefSys_TransformVelocity(self.realowner, self, self.realowner.velocity); // first pull the rope... - if(self.owner.hook_state & HOOK_PULLING) + if(self.realowner.hook_state & HOOK_PULLING) { newlength = self.hook_length; newlength = max(newlength - pullspeed * frametime, minlength); @@ -220,7 +191,7 @@ void GrapplingHookThink() self.hook_length = newlength; } - if(self.owner.hook_state & HOOK_RELEASING) + if(self.realowner.hook_state & HOOK_RELEASING) { newlength = dist; self.hook_length = newlength; @@ -240,15 +211,15 @@ void GrapplingHookThink() v = v - dv * 0.5; self.aiment.velocity = self.aiment.velocity - dv * 0.5; self.aiment.flags &~= FL_ONGROUND; - self.aiment.pusher = self.owner; + self.aiment.pusher = self.realowner; self.aiment.pushltime = time + autocvar_g_maxpushtime; } } - self.owner.flags &~= FL_ONGROUND; + self.realowner.flags &~= FL_ONGROUND; } - self.owner.velocity = WarpZone_RefSys_TransformVelocity(self, self.owner, v); + self.realowner.velocity = WarpZone_RefSys_TransformVelocity(self, self.realowner, v); } else { @@ -260,15 +231,15 @@ void GrapplingHookThink() spd = pullspeed; if(spd < 50) spd = 0; - self.owner.velocity = dir*spd; - self.owner.movetype = MOVETYPE_FLY; + self.realowner.velocity = dir*spd; + self.realowner.movetype = MOVETYPE_FLY; - self.owner.flags &~= FL_ONGROUND; + self.realowner.flags &~= FL_ONGROUND; } } makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0'); - myorg = WarpZone_RefSys_TransformOrigin(self, self.owner, self.origin); // + v_forward * (-9); + myorg = WarpZone_RefSys_TransformOrigin(self, self.realowner, self.origin); // + v_forward * (-9); if(myorg != self.hook_start) { @@ -284,13 +255,6 @@ void GrapplingHookThink() void GrapplingHookTouch (void) { - if(SUB_OwnerCheck()) - return; - if(SUB_NoImpactCheck()) - { - RemoveGrapplingHook(self.owner); - return; - } PROJECTILE_TOUCH; GrapplingHook_Stop(); @@ -302,36 +266,46 @@ void GrapplingHookTouch (void) WarpZone_RefSys_BeginAddingIncrementally(self, self.aiment); } - //self.owner.disableclientprediction = TRUE; + //self.realowner.disableclientprediction = TRUE; } void GrapplingHook_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) { - if(self.health > 0) + if(self.health <= 0) + return; + + if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions + return; // g_balance_projectiledamage says to halt + + self.health = self.health - damage; + + if (self.health <= 0) { - self.health = self.health - damage; - if (self.health <= 0) + if(attacker != self.realowner) { - if(attacker != self.owner) - { - self.owner.pusher = attacker; - self.owner.pushltime = time + autocvar_g_maxpushtime; - } - RemoveGrapplingHook(self.owner); + self.realowner.pusher = attacker; + self.realowner.pushltime = time + autocvar_g_maxpushtime; } + RemoveGrapplingHook(self.realowner); } } void FireGrapplingHook (void) { - local entity missile; - local vector org; + entity missile; + vector org; float s; vector vs; if((arena_roundbased && time < warmup) || (time < game_starttime)) return; + if(self.freezetag_frozen) + return; + + if(self.vehicle) + return; + makevectors(self.v_angle); s = self.cvar_cl_gunalign; @@ -340,8 +314,8 @@ void FireGrapplingHook (void) --s; vs = hook_shotorigin[s]; - // UGLY WORKAROUND: play this on CHAN_WEAPON2 so it can't cut off fire sounds - sound (self, CHAN_WEAPON2, "weapons/hook_fire.wav", VOL_BASE, ATTN_NORM); + // UGLY WORKAROUND: play this on CH_WEAPON_B so it can't cut off fire sounds + sound (self, CH_WEAPON_B, "weapons/hook_fire.wav", VOL_BASE, ATTN_NORM); org = self.origin + self.view_ofs + v_forward * vs_x + v_right * -vs_y + v_up * vs_z; tracebox(self.origin + self.view_ofs, '-3 -3 -3', '3 3 3', org, MOVE_NORMAL, self); @@ -350,9 +324,11 @@ void FireGrapplingHook (void) pointparticles(particleeffectnum("grapple_muzzleflash"), org, '0 0 0', 1); missile = WarpZone_RefSys_SpawnSameRefSys(self); - missile.owner = self; + missile.owner = missile.realowner = self; self.hook = missile; + missile.reset = GrapplingHookReset; missile.classname = "grapplinghook"; + missile.flags = FL_PROJECTILE; missile.movetype = MOVETYPE_FLY; PROJECTILE_MAKETRIGGER(missile); @@ -370,7 +346,7 @@ void FireGrapplingHook (void) //missile.glow_size = 120; missile.touch = GrapplingHookTouch; missile.think = GrapplingHookThink; - missile.nextthink = time + 0.1; + missile.nextthink = time; missile.effects = /*EF_FULLBRIGHT | EF_ADDITIVE |*/ EF_LOWPRECISION; @@ -378,6 +354,7 @@ void FireGrapplingHook (void) missile.event_damage = GrapplingHook_Damage; missile.takedamage = DAMAGE_AIM; missile.damageforcescale = 0; + missile.damagedbycontents = (autocvar_g_balance_grapplehook_damagedbycontents); missile.hook_start = missile.hook_end = missile.origin; @@ -405,7 +382,7 @@ void FireGrapplingHook (void) void GrapplingHookFrame() { - if(g_grappling_hook && timeoutStatus != 2 && self.weapon != WEP_HOOK) + if(g_grappling_hook && timeout_status != TIMEOUT_ACTIVE && self.weapon != WEP_HOOK) { // offhand hook controls if(self.BUTTON_HOOK) diff --git a/qcsrc/server/g_lights.qc b/qcsrc/server/g_lights.qc index d5cc657bff..b5f4bcf844 100644 --- a/qcsrc/server/g_lights.qc +++ b/qcsrc/server/g_lights.qc @@ -34,10 +34,10 @@ void dynlight_think() remove(self); self.nextthink = time + 0.1; -}; +} void dynlight_find_aiment() { - local entity targ; + entity targ; if (!self.target) objerror ("dynlight: no target to follow"); @@ -50,10 +50,10 @@ void dynlight_find_aiment() self.v_angle = self.angles - targ.angles; self.think = dynlight_think; self.nextthink = time + 0.1; -}; +} void dynlight_find_path() { - local entity targ; + entity targ; if (!self.target) objerror ("dynlight: no target to follow"); @@ -62,10 +62,10 @@ void dynlight_find_path() setorigin (self, targ.origin); self.think = train_next; self.nextthink = time + 0.1; -}; +} void dynlight_find_target() { - local entity targ; + entity targ; if (!self.target) objerror ("dynlight: no target to follow"); @@ -81,7 +81,7 @@ void dynlight_use() self.light_lev = self.lefty; else self.light_lev = 0; -}; +} void spawnfunc_dynlight() { local entity targ; @@ -125,4 +125,4 @@ void spawnfunc_dynlight() InitializeEntity(self, dynlight_find_path, INITPRIO_FINDTARGET); return; } -}; +} diff --git a/qcsrc/server/g_models.qc b/qcsrc/server/g_models.qc index bc996fd321..befdb9bcc4 100644 --- a/qcsrc/server/g_models.qc +++ b/qcsrc/server/g_models.qc @@ -2,7 +2,7 @@ void g_model_setcolormaptoactivator (void) { - if(teams_matter) + if(teamplay) { if(activator.team) self.colormap = (activator.team - 1) * 0x11; @@ -128,15 +128,15 @@ float g_clientmodel_genericsendentity (entity to, float sf) #define G_MODEL_INIT(sol) \ - SetBrushEntityModel(); \ if(!self.scale) self.scale = self.modelscale; \ + SetBrushEntityModel(); \ self.use = g_model_setcolormaptoactivator; \ InitializeEntity(self, g_model_dropbyspawnflags, INITPRIO_DROPTOFLOOR); \ if(!self.solid) self.solid = (sol); else if(self.solid < 0) self.solid = SOLID_NOT; #define G_CLIENTMODEL_INIT(sol) \ - SetBrushEntityModel(); \ if(!self.scale) self.scale = self.modelscale; \ + SetBrushEntityModel(); \ self.use = g_clientmodel_setcolormaptoactivator; \ InitializeEntity(self, g_clientmodel_dropbyspawnflags, INITPRIO_DROPTOFLOOR); \ if(!self.solid) self.solid = (sol); else if(self.solid < 0) self.solid = SOLID_NOT; \ diff --git a/qcsrc/server/g_subs.qc b/qcsrc/server/g_subs.qc index 47f3a5a699..e119e5aba4 100644 --- a/qcsrc/server/g_subs.qc +++ b/qcsrc/server/g_subs.qc @@ -1,4 +1,4 @@ -void SUB_Null() {}; +void SUB_Null() {} float SUB_True() { return 1; } float SUB_False() { return 0; } @@ -16,6 +16,9 @@ void spawnfunc_info_null (void) void setanim(entity e, vector anim, float looping, float override, float restart) { + if (!anim) + return; // no animation was given to us! We can't use this. + if (anim_x == e.animstate_startframe) if (anim_y == e.animstate_numframes) if (anim_z == e.animstate_framerate) @@ -38,7 +41,7 @@ void setanim(entity e, vector anim, float looping, float override, float restart e.animstate_override = override; e.frame = e.animstate_startframe; e.frame1time = servertime; -}; +} void updateanim(entity e) { @@ -53,31 +56,20 @@ void updateanim(entity e) } e.frame = e.animstate_startframe + bound(0, (time - e.animstate_starttime) * e.animstate_framerate, e.animstate_numframes - 1); //print(ftos(time), " -> ", ftos(e.frame), "\n"); -}; - -float animparseerror; -vector animparseline(float animfile) -{ - local string line; - local float c; - local vector anim; - if (animfile < 0) - return '0 1 2'; - line = fgets(animfile); - c = tokenize_console(line); - if (c < 3) +} + +vector animfixfps(entity e, vector a) +{ + // multi-frame anim: keep as-is + if(a_y == 1) { - animparseerror = TRUE; - return '0 1 2'; + float dur; + dur = frameduration(e.modelindex, a_x); + if(dur > 0) + a_z = 1.0 / dur; } - anim_x = stof(argv(0)); - anim_y = stof(argv(1)); - anim_z = stof(argv(2)); - // don't allow completely bogus values - if (anim_x < 0 || anim_y < 1 || anim_z < 0.001) - anim = '0 1 2'; - return anim; -}; + return a; +} /* ================== @@ -118,7 +110,7 @@ void SUB_VanishOrRemove (entity ent) if (ent.flags & FL_CLIENT) { // vanish - ent.model = ""; + ent.alpha = -1; ent.effects = 0; ent.glow_size = 0; ent.pflags = 0; @@ -132,12 +124,15 @@ void SUB_VanishOrRemove (entity ent) void SUB_SetFade_Think (void) { + if(self.alpha == 0) + self.alpha = 1; self.think = SUB_SetFade_Think; - self.nextthink = self.fade_time; - self.alpha = 1 - (time - self.fade_time) * self.fade_rate; + self.nextthink = time; + self.alpha -= frametime * self.fade_rate; if (self.alpha < 0.01) SUB_VanishOrRemove(self); - self.alpha = bound(0.01, self.alpha, 1); + else + self.nextthink = time; } /* @@ -153,7 +148,6 @@ void SUB_SetFade (entity ent, float when, float fadetime) // return; //ent.alpha = 1; ent.fade_rate = 1/fadetime; - ent.fade_time = when; ent.think = SUB_SetFade_Think; ent.nextthink = when; } @@ -177,10 +171,51 @@ void SUB_CalcMoveDone (void) self.think1 (); } +void SUB_CalcMove_controller_think (void) +{ + entity oldself; + float traveltime; + float phasepos; + float nexttick; + vector delta; + vector veloc; + vector nextpos; + if(time < self.animstate_endtime) { + delta = self.destvec; + nexttick = time + sys_frametime; + + if(nexttick < self.animstate_endtime) { + traveltime = self.animstate_endtime - self.animstate_starttime; + phasepos = (nexttick - self.animstate_starttime) / traveltime; // range: [0, 1] + phasepos = 3.14159265 + (phasepos * 3.14159265); // range: [pi, 2pi] + phasepos = cos(phasepos); // cos [pi, 2pi] is in [-1, 1] + phasepos = phasepos + 1; // correct range to [0, 2] + phasepos = phasepos / 2; // correct range to [0, 1] + nextpos = self.origin + (delta * phasepos); + + veloc = nextpos - self.owner.origin; + veloc = veloc * (1 / sys_frametime); // so it arrives for the next frame + + } else { + veloc = self.finaldest - self.owner.origin; + veloc = veloc * (1 / sys_frametime); // so it arrives for the next frame + } + self.owner.velocity = veloc; + self.nextthink = nexttick; + } else { + oldself = self; + self.owner.think = self.think1; + self = self.owner; + remove(oldself); + self.think(); + } +} + void SUB_CalcMove (vector tdest, float tspeed, void() func) { vector delta; float traveltime; + entity controller; if (!tspeed) objerror ("No speed is defined!"); @@ -206,9 +241,36 @@ void SUB_CalcMove (vector tdest, float tspeed, void() func) return; } - self.velocity = delta * (1/traveltime); // QuakeC doesn't allow vector/float division + // Very short animations don't really show off the effect + // of controlled animation, so let's just use linear movement. + // Alternatively entities can choose to specify non-controlled movement. + // The only currently implemented alternative movement is linear (value 1) + if (traveltime < 0.15 || self.platmovetype == 1) + { + self.velocity = delta * (1/traveltime); // QuakeC doesn't allow vector/float division + self.nextthink = self.ltime + traveltime; + return; + } + controller = spawn(); + controller.classname = "SUB_CalcMove_controller"; + controller.owner = self; + controller.origin = self.origin; // starting point + controller.finaldest = (tdest + '0 0 0.125'); // where do we want to end? Offset to overshoot a bit. + controller.destvec = delta; + controller.animstate_starttime = time; + controller.animstate_endtime = time + traveltime; + controller.think = SUB_CalcMove_controller_think; + controller.think1 = self.think; + + // the thinking is now done by the controller + self.think = SUB_Null; self.nextthink = self.ltime + traveltime; + + // invoke controller + self = controller; + self.think(); + self = self.owner; } void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeed, void() func) @@ -310,8 +372,8 @@ Additionally it moves players back into the past before the trace and restores t */ void tracebox_antilag_force_wz (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag, float wz) { - local entity player; - local float oldsolid; + entity player; + float oldsolid; // check whether antilagged traces are enabled if (lag < 0.001) @@ -329,12 +391,9 @@ void tracebox_antilag_force_wz (entity source, vector v1, vector mi, vector ma, if (lag) { // take players back into the past - player = player_list; - while (player) - { - antilag_takeback(player, time - lag); - player = player.nextplayer; - } + FOR_EACH_PLAYER(player) + if(player != forent) + antilag_takeback(player, time - lag); } // do the trace @@ -346,12 +405,9 @@ void tracebox_antilag_force_wz (entity source, vector v1, vector mi, vector ma, // restore players to current positions if (lag) { - player = player_list; - while (player) - { - antilag_restore(player); - player = player.nextplayer; - } + FOR_EACH_PLAYER(player) + if(player != forent) + antilag_restore(player); } // restore shooter solid type @@ -698,6 +754,33 @@ void LODmodel_attach() SetCustomizer(self, LOD_customize, LOD_uncustomize); } +void ApplyMinMaxScaleAngles(entity e) +{ + if(e.angles_x != 0 || e.angles_z != 0 || self.avelocity_x != 0 || self.avelocity_z != 0) // "weird" rotation + { + e.maxs = '1 1 1' * vlen( + '1 0 0' * max(-e.mins_x, e.maxs_x) + + '0 1 0' * max(-e.mins_y, e.maxs_y) + + '0 0 1' * max(-e.mins_z, e.maxs_z) + ); + e.mins = -e.maxs; + } + else if(e.angles_y != 0 || self.avelocity_y != 0) // yaw only is a bit better + { + e.maxs_x = vlen( + '1 0 0' * max(-e.mins_x, e.maxs_x) + + '0 1 0' * max(-e.mins_y, e.maxs_y) + ); + e.maxs_y = e.maxs_x; + e.mins_x = -e.maxs_x; + e.mins_y = -e.maxs_x; + } + if(e.scale) + setsize(e, e.mins * e.scale, e.maxs * e.scale); + else + setsize(e, e.mins, e.maxs); +} + void SetBrushEntityModel() { if(self.model != "") @@ -707,10 +790,7 @@ void SetBrushEntityModel() InitializeEntity(self, LODmodel_attach, INITPRIO_FINDTARGET); } setorigin(self, self.origin); - if(self.scale) - setsize(self, self.mins * self.scale, self.maxs * self.scale); - else - setsize(self, self.mins, self.maxs); + ApplyMinMaxScaleAngles(self); } void SetBrushEntityModelNoLOD() @@ -721,10 +801,7 @@ void SetBrushEntityModelNoLOD() setmodel(self, self.model); // no precision needed } setorigin(self, self.origin); - if(self.scale) - setsize(self, self.mins * self.scale, self.maxs * self.scale); - else - setsize(self, self.mins, self.maxs); + ApplyMinMaxScaleAngles(self); } /* @@ -744,7 +821,7 @@ void SetMovedir() } self.angles = '0 0 0'; -}; +} void InitTrigger() { @@ -756,7 +833,7 @@ void InitTrigger() self.movetype = MOVETYPE_NONE; self.modelindex = 0; self.model = ""; -}; +} void InitSolidBSPTrigger() { @@ -768,7 +845,7 @@ void InitSolidBSPTrigger() self.movetype = MOVETYPE_NONE; // why was this PUSH? -div0 // self.modelindex = 0; self.model = ""; -}; +} float InitMovingBrushTrigger() { @@ -783,4 +860,4 @@ float InitMovingBrushTrigger() return 0; } return 1; -}; +} diff --git a/qcsrc/server/g_swamp.qc b/qcsrc/server/g_swamp.qc deleted file mode 100644 index fe64e7c006..0000000000 --- a/qcsrc/server/g_swamp.qc +++ /dev/null @@ -1,8 +0,0 @@ -/* -* t_swamp.c -* Adds spawnfunc_trigger_swamp and suppoart routines for xonotic 1.2.1+ -* Author tZork (Jakob MG) -* jakob@games43.se -* 2005 11 29 -*/ - diff --git a/qcsrc/server/g_tetris.qc b/qcsrc/server/g_tetris.qc index 21208a2a19..d194c94314 100644 --- a/qcsrc/server/g_tetris.qc +++ b/qcsrc/server/g_tetris.qc @@ -56,7 +56,7 @@ float SVC_CENTERPRINTa = 26; float Tetris_Level() { return ((floor((self.tet_lines / 10)) + 1)); -}; +} void tetsnd(string snd) { @@ -75,7 +75,7 @@ void SetLine(float ln, string vl) if(ln < 1 || ln > TET_LINES) error("WTF"); bufstr_set(tet_line_buf, ln + TET_LINES * num_for_edict(self), vl); -}; +} string GetLine(float ln) { @@ -84,14 +84,14 @@ string GetLine(float ln) if(ln < 1 || ln > TET_LINES) return TET_EMPTY_LINE; return bufstr_get(tet_line_buf, ln + TET_LINES * num_for_edict(self)); -}; +} float GetXBlock(float x, string dat) { if(x < 1 || x > TET_WIDTH) error("WTF"); return stof(substring(dat, x-1, 1)); -}; +} string SetXBlock(float x, string dat, float new) { @@ -100,13 +100,13 @@ string SetXBlock(float x, string dat, float new) ftos(new), substring(dat, x, -1) ); -}; +} float GetSquare(float x, float y) { return GetXBlock(x, GetLine(y)); -}; +} void SetSquare(float x, float y, float val) { @@ -114,7 +114,7 @@ void SetSquare(float x, float y, float val) dat = GetLine(y); dat = SetXBlock(x, dat, val); SetLine(y, dat); -}; +} float PieceColor(float pc) { @@ -235,7 +235,7 @@ float PieceMetric(float x, float y, float rot, float pc) return !!(ce_y & pow(4, x-1)); // second row else return 0; // illegal parms -}; +} vector tet_piecemins; vector tet_piecemaxs; void PieceMinsMaxs(float rot, float pc) @@ -343,7 +343,7 @@ void WriteTetrisString(string s) float pnum(float num, float dig) { - local float f, i; + float f, i; if (num < 0) { WriteChar(MSG_ONE, 173); @@ -361,7 +361,7 @@ float pnum(float num, float dig) } WriteChar(MSG_ONE, 176 + num); return dig; -}; +} void DrawLine(float ln) { @@ -523,7 +523,7 @@ void ResetTetris() self.piece_type = 0; self.next_piece = self.tet_lines = self.tet_score = 0; self.tet_piece_bucket = 0; -}; +} void Tet_GameExit() { @@ -532,7 +532,7 @@ void Tet_GameExit() self.tet_vs_id = 0; ResetTetris(); self.movetype = MOVETYPE_WALK; -}; +} void PrintField() { @@ -800,14 +800,14 @@ float RandomPiece() self.tet_piece_bucket = b; return p + 1; } -}; +} void TetAddScore(float n) { self.tet_score = self.tet_score + n * Tetris_Level(); if (self.tet_score > tet_high_score) tet_high_score = self.tet_score; -}; +} float CheckMetrics(float piece, float orgx, float orgy, float rot) /*FIXDECL*/ { // check to see if the piece, if moved to the locations will overlap @@ -954,7 +954,7 @@ void CompletedLines() tetsnd("tetline"); else tetsnd("tetland"); -}; +} void HandleGame(float keyss) { @@ -1087,7 +1087,7 @@ void HandleGame(float keyss) return; } CementPiece(self.piece_type, self.piece_pos_x, self.piece_pos_y, self.piece_pos_z); -}; +} /* ********************************* @@ -1127,7 +1127,7 @@ void TetrisImpulse() Tet_GameExit(); self.impulse = 0; } -}; +} float TetrisPreFrame() @@ -1144,24 +1144,24 @@ float TetrisPreFrame() else self.tet_drawtime = time + 0.5; return 1; -}; +} float frik_anglemoda(float v) { return v - floor(v/360) * 360; -}; +} float angcompa(float y1, float y2) { y1 = frik_anglemoda(y1); y2 = frik_anglemoda(y2); - local float answer; + float answer; answer = y1 - y2; if (answer > 180) answer = answer - 360; else if (answer < -180) answer = answer + 360; return answer; -}; +} .float tetkey_down, tetkey_rotright, tetkey_left, tetkey_right, tetkey_rotleft, tetkey_drop; @@ -1240,7 +1240,7 @@ float TetrisPostFrame() } return 1; -}; +} #else diff --git a/qcsrc/server/g_triggers.qc b/qcsrc/server/g_triggers.qc index 0a70de75f8..4e97136ce8 100644 --- a/qcsrc/server/g_triggers.qc +++ b/qcsrc/server/g_triggers.qc @@ -10,7 +10,7 @@ void DelayThink() activator = self.enemy; SUB_UseTargets (); remove(self); -}; +} /* ============================== @@ -33,7 +33,7 @@ match (string)self.target and call their .use function */ void SUB_UseTargets() { - local entity t, stemp, otemp, act; + entity t, stemp, otemp, act; string s; float i; @@ -88,6 +88,9 @@ void SUB_UseTargets() stemp = self; otemp = other; + if(stemp.target_random) + RandomSelection_Init(); + for(i = 0; i < 4; ++i) { switch(i) @@ -103,19 +106,33 @@ void SUB_UseTargets() for(t = world; (t = find(t, targetname, s)); ) if(t.use) { - //print(stemp.classname, " ", stemp.targetname, " -> ", t.classname, " ", t.targetname, "\n"); - self = t; - other = stemp; - activator = act; - self.use(); + if(stemp.target_random) + { + RandomSelection_Add(t, 0, string_null, 1, 0); + } + else + { + self = t; + other = stemp; + activator = act; + self.use(); + } } } } + if(stemp.target_random && RandomSelection_chosen_ent) + { + self = RandomSelection_chosen_ent; + other = stemp; + activator = act; + self.use(); + } + activator = act; self = stemp; other = otemp; -}; +} //============================================================================= @@ -132,7 +149,7 @@ void multi_wait() self.takedamage = DAMAGE_YES; self.solid = SOLID_BBOX; } -}; +} // the trigger was just touched/killed/used @@ -154,7 +171,7 @@ void multi_trigger() } if (self.noise) - sound (self.enemy, CHAN_AUTO, self.noise, VOL_BASE, ATTN_NORM); + sound (self.enemy, CH_TRIGGER, self.noise, VOL_BASE, ATTN_NORM); // don't trigger again until reset self.takedamage = DAMAGE_NO; @@ -177,14 +194,14 @@ void multi_trigger() // called wheil C code is looping through area links... self.touch = SUB_Null; } -}; +} void multi_use() { self.goalentity = other; self.enemy = activator; multi_trigger(); -}; +} void multi_touch() { @@ -209,7 +226,7 @@ void multi_touch() self.enemy = other; self.goalentity = other; multi_trigger (); -}; +} void multi_eventdamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) { @@ -301,7 +318,7 @@ void spawnfunc_trigger_multiple() setorigin (self, self.origin); // make sure it links into the world } } -}; +} /*QUAKED spawnfunc_trigger_once (.5 .5 .5) ? notouch @@ -321,7 +338,7 @@ void spawnfunc_trigger_once() { self.wait = -1; spawnfunc_trigger_multiple(); -}; +} //============================================================================= @@ -332,7 +349,7 @@ void spawnfunc_trigger_relay() { self.use = SUB_UseTargets; self.reset = spawnfunc_trigger_relay; // this spawnfunc resets fully -}; +} void delay_use() { @@ -385,7 +402,7 @@ void counter_use() centerprint(activator, "Sequence completed!"); self.enemy = activator; multi_trigger (); -}; +} void counter_reset() { @@ -409,7 +426,15 @@ void spawnfunc_trigger_counter() self.use = counter_use; self.reset = counter_reset; -}; +} + +void trigger_hurt_use() +{ + if(activator.classname == "player") + self.enemy = activator; + else + self.enemy = world; // let's just destroy it, if taking over is too much work +} .float triggerhurttime; void trigger_hurt_touch() @@ -429,7 +454,16 @@ void trigger_hurt_touch() { EXACTTRIGGER_TOUCH; other.triggerhurttime = time + 1; - Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0'); + + entity own; + own = self.enemy; + if(own.classname != "player") + { + own = self; + self.enemy = world; // I still hate you all + } + + Damage (other, self, own, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0'); } } else @@ -450,7 +484,7 @@ void trigger_hurt_touch() } return; -}; +} /*QUAKED spawnfunc_trigger_hurt (.5 .5 .5) ? Any object touching this will be hurt @@ -465,6 +499,8 @@ void spawnfunc_trigger_hurt() EXACTTRIGGER_INIT; self.active = ACTIVE_ACTIVE; self.touch = trigger_hurt_touch; + self.use = trigger_hurt_use; + self.enemy = world; // I hate you all if (!self.dmg) self.dmg = 1000; if (!self.message) @@ -478,7 +514,7 @@ void spawnfunc_trigger_hurt() if(trigger_hurt_last) trigger_hurt_last.trigger_hurt_next = self; trigger_hurt_last = self; -}; +} float tracebox_hits_trigger_hurt(vector start, vector mi, vector ma, vector end) { @@ -518,11 +554,11 @@ void trigger_heal_touch() { other.health = min(other.health + self.health, self.max_health); other.pauserothealth_finished = max(other.pauserothealth_finished, time + autocvar_g_balance_pause_health_rot); - sound (other, CHAN_AUTO, self.noise, VOL_BASE, ATTN_NORM); + sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTN_NORM); } } } -}; +} void spawnfunc_trigger_heal() { @@ -537,7 +573,7 @@ void spawnfunc_trigger_heal() if(self.noise == "") self.noise = "misc/mediumhealth.wav"; precache_sound(self.noise); -}; +} ////////////////////////////////////////////////////////////// @@ -579,12 +615,12 @@ void trigger_gravity_check_think() self.count -= 1; self.nextthink = time; } -}; +} void trigger_gravity_use() { self.state = !self.state; -}; +} void trigger_gravity_touch() { @@ -629,10 +665,10 @@ void trigger_gravity_touch() { other.gravity = g; if(self.noise != "") - sound (other, CHAN_AUTO, self.noise, VOL_BASE, ATTN_NORM); + sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTN_NORM); UpdateCSQCProjectile(self.owner); } -}; +} void spawnfunc_trigger_gravity() { @@ -651,7 +687,7 @@ void spawnfunc_trigger_gravity() if(self.spawnflags & 2) self.state = FALSE; } -}; +} //============================================================================= @@ -685,7 +721,7 @@ void target_speaker_use_activator() else snd = self.noise; msg_entity = activator; - soundto(MSG_ONE, self, CHAN_TRIGGER, snd, VOL_BASE * self.volume, self.atten); + soundto(MSG_ONE, self, CH_TRIGGER, snd, VOL_BASE * self.volume, self.atten); } void target_speaker_use_on() { @@ -711,13 +747,13 @@ void target_speaker_use_on() } else snd = self.noise; - sound(self, CHAN_TRIGGER, snd, VOL_BASE * self.volume, self.atten); + sound(self, CH_TRIGGER_SINGLE, snd, VOL_BASE * self.volume, self.atten); if(self.spawnflags & 3) self.use = target_speaker_use_off; } void target_speaker_use_off() { - sound(self, CHAN_TRIGGER, "misc/null.wav", VOL_BASE * self.volume, self.atten); + sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASE * self.volume, self.atten); self.use = target_speaker_use_on; } void target_speaker_reset() @@ -786,7 +822,7 @@ void spawnfunc_target_speaker() ambientsound (self.origin, self.noise, VOL_BASE * self.volume, self.atten); remove(self); } -}; +} void spawnfunc_func_stardust() { @@ -989,7 +1025,7 @@ float rainsnow_SendEntity(entity to, float sf) WriteShort(MSG_ENTITY, self.count); WriteByte(MSG_ENTITY, self.cnt); return 1; -}; +} /*QUAKED spawnfunc_func_rain (0 .5 .8) ? This is an invisible area like a trigger, which rain falls inside of. @@ -1026,7 +1062,7 @@ void spawnfunc_func_rain() self.Version = 1; Net_LinkEntity(self, FALSE, 0, rainsnow_SendEntity); -}; +} /*QUAKED spawnfunc_func_snow (0 .5 .8) ? @@ -1064,7 +1100,7 @@ void spawnfunc_func_snow() self.Version = 1; Net_LinkEntity(self, FALSE, 0, rainsnow_SendEntity); -}; +} void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, float deathtype); @@ -1341,24 +1377,7 @@ void trigger_impulse_touch1() if (self.active != ACTIVE_ACTIVE) return; - // FIXME: Better checking for what to push and not. - if not(other.iscreature) - if (other.classname != "corpse") - if (other.classname != "body") - if (other.classname != "gib") - if (other.classname != "missile") - if (other.classname != "rocket") - if (other.classname != "casing") - if (other.classname != "grenade") - if (other.classname != "plasma") - if (other.classname != "plasma_prim") - if (other.classname != "plasma_chain") - if (other.classname != "droppedweapon") - if (other.classname != "nexball_basketball") - if (other.classname != "nexball_football") - return; - - if (other.deadflag && other.iscreature) + if (!isPushable(other)) return; EXACTTRIGGER_TOUCH; @@ -1396,24 +1415,7 @@ void trigger_impulse_touch2() if (self.active != ACTIVE_ACTIVE) return; - // FIXME: Better checking for what to push and not. - if not(other.iscreature) - if (other.classname != "corpse") - if (other.classname != "body") - if (other.classname != "gib") - if (other.classname != "missile") - if (other.classname != "rocket") - if (other.classname != "casing") - if (other.classname != "grenade") - if (other.classname != "plasma") - if (other.classname != "plasma_prim") - if (other.classname != "plasma_chain") - if (other.classname != "droppedweapon") - if (other.classname != "nexball_basketball") - if (other.classname != "nexball_football") - return; - - if (other.deadflag && other.iscreature) + if (!isPushable(other)) return; EXACTTRIGGER_TOUCH; @@ -1437,24 +1439,7 @@ void trigger_impulse_touch3() if (self.active != ACTIVE_ACTIVE) return; - // FIXME: Better checking for what to push and not. - if not(other.iscreature) - if (other.classname != "corpse") - if (other.classname != "body") - if (other.classname != "gib") - if (other.classname != "missile") - if (other.classname != "rocket") - if (other.classname != "casing") - if (other.classname != "grenade") - if (other.classname != "plasma") - if (other.classname != "plasma_prim") - if (other.classname != "plasma_chain") - if (other.classname != "droppedweapon") - if (other.classname != "nexball_basketball") - if (other.classname != "nexball_football") - return; - - if (other.deadflag && other.iscreature) + if (!isPushable(other)) return; EXACTTRIGGER_TOUCH; @@ -1657,7 +1642,7 @@ void spawnfunc_trigger_multivibrator() self.state = 0; self.use = multivibrator_toggle; self.think = multivibrator_send; - self.nextthink = time; + self.nextthink = max(1, time); IFTARGETED multivibrator_reset(); @@ -1703,6 +1688,7 @@ void follow_init() attach_sameorigin(dst, src, self.message); } + dst.solid = SOLID_NOT; // solid doesn't work with attachment remove(self); } else @@ -1922,19 +1908,54 @@ void spawnfunc_trigger_disablerelay() } float magicear_matched; +float W_Tuba_HasPlayed(entity pl, string melody, float instrument, float ignorepitch, float mintempo, float maxtempo); string trigger_magicear_processmessage(entity ear, entity source, float teamsay, entity privatesay, string msgin) { float domatch, dotrigger, matchstart, l; string s, msg; entity oldself; + string savemessage; magicear_matched = FALSE; - dotrigger = ((self.classname == "player") && (self.deadflag == DEAD_NO) && ((ear.radius == 0) || (vlen(source.origin - ear.origin) <= ear.radius))); + dotrigger = ((source.classname == "player") && (source.deadflag == DEAD_NO) && ((ear.radius == 0) || (vlen(source.origin - ear.origin) <= ear.radius))); domatch = ((ear.spawnflags & 32) || dotrigger); + if not(domatch) return msgin; + if not(msgin) + { + // we are in TUBA mode! + if not(ear.spawnflags & 256) + return msgin; + + if(!W_Tuba_HasPlayed(source, ear.message, ear.movedir_x, !(ear.spawnflags & 512), ear.movedir_y, ear.movedir_z)) + return msgin; + + magicear_matched = TRUE; + + if(dotrigger) + { + oldself = self; + activator = source; + self = ear; + savemessage = self.message; + self.message = string_null; + SUB_UseTargets(); + self.message = savemessage; + self = oldself; + } + + if(ear.netname != "") + return ear.netname; + + return msgin; + } + + if(ear.spawnflags & 256) // ENOTUBA + return msgin; + if(privatesay) { if(ear.spawnflags & 4) @@ -1956,7 +1977,7 @@ string trigger_magicear_processmessage(entity ear, entity source, float teamsay, matchstart = -1; l = strlen(ear.message); - if(self.spawnflags & 128) + if(ear.spawnflags & 128) msg = msgin; else msg = strdecolorize(msgin); @@ -2007,9 +2028,13 @@ string trigger_magicear_processmessage(entity ear, entity source, float teamsay, if(dotrigger) { - oldself = activator = self; + oldself = self; + activator = source; self = ear; + savemessage = self.message; + self.message = string_null; SUB_UseTargets(); + self.message = savemessage; self = oldself; } @@ -2055,13 +2080,16 @@ void spawnfunc_trigger_magicear() // actually handled in "say" processing // spawnflags: - // 1 = ignore say - // 2 = ignore teamsay - // 4 = ignore tell - // 8 = ignore tell to unknown player + // 1 = ignore say + // 2 = ignore teamsay + // 4 = ignore tell + // 8 = ignore tell to unknown player // 16 = let netname replace the whole message (otherwise, netname is a word replacement if set) // 32 = perform the replacement even if outside the radius or dead // 64 = continue replacing/triggering even if this one matched + // 128 = don't decolorize message before matching + // 256 = message is a tuba note sequence (pitch.duration pitch.duration ...) + // 512 = tuba notes must be exact right pitch, no transposing // message: either // *pattern* // or @@ -2076,6 +2104,10 @@ void spawnfunc_trigger_magicear() // "hearing distance" // target: // what to trigger + // movedir: + // for spawnflags 256, defines 'instrument+1 mintempo maxtempo' (zero component doesn't matter) + + self.movedir_x -= 1; // map to tuba instrument numbers } void relay_activators_use() @@ -2132,9 +2164,9 @@ void spawnfunc_target_changelevel_use() localcmd("endmatch\n"); else localcmd(strcat("changelevel ", self.chmap, "\n")); -}; +} void spawnfunc_target_changelevel() { self.use = spawnfunc_target_changelevel_use; -}; +} diff --git a/qcsrc/server/g_world.qc b/qcsrc/server/g_world.qc index e2a123adc4..93cea80ffd 100644 --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@ -44,9 +44,9 @@ float world_initialized; string GetMapname(); string GetGametype(); -void GotoNextMap(); +void GotoNextMap(float reinit); void ShuffleMaplist() -float() DoNextMapOverride; +float(float reinit) DoNextMapOverride; void SetDefaultAlpha() { @@ -95,86 +95,6 @@ void fteqcc_testbugs() world.cnt = 0; } -/** - * Takes care of pausing and unpausing the game. - * Centerprints the information about an upcoming or active timeout to all active - * players. Also plays reminder sounds. - */ -void timeoutHandler_Think() { - local string timeStr; - local entity plr; - if (timeoutStatus == 1) { - if (remainingLeadTime > 0) { - //centerprint the information to every player - timeStr = getTimeoutText(0); - FOR_EACH_REALCLIENT(plr) { - if(plr.classname == "player") { - centerprint_atprio(plr, CENTERPRIO_SPAM, timeStr); - } - } - remainingLeadTime -= 1; - //think again in 1 second: - self.nextthink = time + 1; - } - else { - //now pause the game: - timeoutStatus = 2; - //reset all the flood variables - FOR_EACH_CLIENT(plr) { - plr.nickspamcount = plr.nickspamtime = plr.floodcontrol_chat = plr.floodcontrol_chatteam = plr.floodcontrol_chattell = plr.floodcontrol_voice = plr.floodcontrol_voiceteam = 0; - } - cvar_set("slowmo", ftos(TIMEOUT_SLOWMO_VALUE)); - //copy .v_angle to .lastV_angle for every player in order to fix their view during pause (see PlayerPreThink) - FOR_EACH_REALPLAYER(plr) { - plr.lastV_angle = plr.v_angle; - } - self.nextthink = time; - } - } - else if (timeoutStatus == 2) { - if (remainingTimeoutTime > 0) { - timeStr = getTimeoutText(0); - FOR_EACH_REALCLIENT(plr) { - if(plr.classname == "player") { - centerprint_atprio(plr, CENTERPRIO_SPAM, timeStr); - } - } - if(remainingTimeoutTime == autocvar_sv_timeout_resumetime) { //play a warning sound when only <sv_timeout_resumetime> seconds are left - Announce("prepareforbattle"); - } - remainingTimeoutTime -= 1; - self.nextthink = time + TIMEOUT_SLOWMO_VALUE; - } - else { - //unpause the game again - remainingTimeoutTime = timeoutStatus = 0; - cvar_set("slowmo", ftos(orig_slowmo)); - //and unlock the fixed view again once there is no timeout active anymore - FOR_EACH_REALPLAYER(plr) { - plr.fixangle = FALSE; - } - //get rid of the countdown message - FOR_EACH_REALCLIENT(plr) { - if(plr.classname == "player") { - centerprint_atprio(plr, CENTERPRIO_SPAM, ""); - } - } - remove(self); - return; - } - - } - else if (timeoutStatus == 0) { //if a player called the resumegame command (which set timeoutStatus to 0 already) - FOR_EACH_REALCLIENT(plr) { - if(plr.classname == "player") { - centerprint_atprio(plr, CENTERPRIO_SPAM, ""); - } - } - remove(self); - return; - } -} - void GotoFirstMap() { float n; @@ -192,8 +112,8 @@ void GotoFirstMap() MapInfo_Enumerate(); MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0); - if(!DoNextMapOverride()) - GotoNextMap(); + if(!DoNextMapOverride(1)) + GotoNextMap(1); return; } @@ -237,6 +157,10 @@ void cvar_changes_init() #define BADPREFIX(p) if(substring(k, 0, strlen(p)) == p) continue #define BADPRESUFFIX(p,s) if(substring(k, 0, strlen(p)) == p && substring(k, -strlen(s), -1) == s) continue #define BADCVAR(p) if(k == p) continue + + // general excludes and namespaces for server admin used cvars + BADPREFIX("help_"); // PN's server has this listed as changed, let's not rat him out for THAT + // internal BADPREFIX("csqc_"); BADPREFIX("cvar_check_"); @@ -252,6 +176,7 @@ void cvar_changes_init() BADPREFIX("con_"); BADPREFIX("scoreboard_"); BADPREFIX("g_campaign"); + BADPREFIX("g_waypointsprite_"); BADPREFIX("gl_"); BADPREFIX("joy"); BADPREFIX("hud_"); @@ -277,7 +202,6 @@ void cvar_changes_init() // private BADCVAR("developer"); - BADCVAR("g_banned_list"); BADCVAR("log_dest_udp"); BADCVAR("log_file"); BADCVAR("net_address"); @@ -285,57 +209,62 @@ void cvar_changes_init() BADCVAR("port"); BADCVAR("savedgamecfg"); BADCVAR("serverconfig"); + BADCVAR("sv_autoscreenshot"); BADCVAR("sv_heartbeatperiod"); BADCVAR("sv_vote_master_password"); BADCVAR("sys_colortranslation"); BADCVAR("sys_specialcharactertranslation"); + BADCVAR("timeformat"); BADCVAR("timestamps"); BADPREFIX("developer_"); BADPREFIX("g_ban_"); + BADPREFIX("g_banned_list"); BADPREFIX("g_chat_flood_"); + BADPREFIX("g_ghost_items"); + BADPREFIX("g_playerstats_"); + BADPREFIX("g_respawn_ghosts"); BADPREFIX("g_voice_flood_"); BADPREFIX("rcon_"); - BADPREFIX("settemp_"); - BADPREFIX("sv_allowdownloads_"); + BADPREFIX("sv_allowdownloads"); BADPREFIX("sv_autodemo"); BADPREFIX("sv_curl_"); BADPREFIX("sv_eventlog"); BADPREFIX("sv_logscores_"); BADPREFIX("sv_master"); BADPREFIX("sv_weaponstats_"); + BADPREFIX("sv_waypointsprite_"); + BADCVAR("rescan_pending"); // these can contain player IDs, so better hide - BADCVAR("g_forced_team_red"); - BADCVAR("g_forced_team_blue"); - BADCVAR("g_forced_team_yellow"); - BADCVAR("g_forced_team_pink"); + BADPREFIX("g_forced_team_"); // mapinfo - BADCVAR("timelimit"); BADCVAR("fraglimit"); - BADCVAR("leadlimit"); - BADCVAR("g_tdm_teams"); - BADCVAR("g_keyhunt_teams"); - BADCVAR("g_domination_default_teams"); - BADCVAR("g_race_qualifying_timelimit"); - BADCVAR("g_lms"); BADCVAR("g_arena"); - BADCVAR("g_ca"); BADCVAR("g_assault"); + BADCVAR("g_ca"); BADCVAR("g_ctf"); + BADCVAR("g_cts"); BADCVAR("g_dm"); BADCVAR("g_domination"); + BADCVAR("g_domination_default_teams"); BADCVAR("g_freezetag"); + BADCVAR("g_keepaway"); BADCVAR("g_keyhunt"); BADCVAR("g_keyhunt_teams"); + BADCVAR("g_keyhunt_teams"); + BADCVAR("g_lms"); + BADCVAR("g_nexball"); BADCVAR("g_onslaught"); BADCVAR("g_race"); - BADCVAR("g_cts"); + BADCVAR("g_race_qualifying_timelimit"); BADCVAR("g_runematch"); BADCVAR("g_tdm"); - BADCVAR("g_nexball"); - BADCVAR("g_keepaway"); + BADCVAR("g_tdm_teams"); + BADCVAR("leadlimit"); + BADCVAR("nextmap"); BADCVAR("teamplay"); + BADCVAR("timelimit"); // long BADCVAR("hostname"); @@ -363,24 +292,44 @@ void cvar_changes_init() // does nothing visible BADCVAR("captureleadlimit_override"); BADCVAR("g_arena_point_leadlimit"); + BADCVAR("g_balance_kill_delay"); BADCVAR("g_ca_point_leadlimit"); - BADCVAR("g_ctf_capture_leadlimit"); + BADCVAR("g_ctf_captimerecord_always"); + BADCVAR("g_ctf_flag_capture_effects"); + BADCVAR("g_ctf_flag_glowtrails"); + BADCVAR("g_ctf_flag_pickup_effects"); BADCVAR("g_domination_point_leadlimit"); + BADCVAR("g_forced_respawn"); BADCVAR("g_keyhunt_point_leadlimit"); BADCVAR("g_nexball_goalleadlimit"); BADCVAR("g_runematch_point_leadlimit"); BADCVAR("leadlimit_and_fraglimit"); BADCVAR("leadlimit_override"); - BADCVAR("sv_checkforpacketsduringsleep"); BADCVAR("pausable"); + BADCVAR("sv_allow_fullbright"); + BADCVAR("sv_checkforpacketsduringsleep"); + BADCVAR("sv_fraginfo"); BADCVAR("sv_timeout"); + BADPREFIX("sv_timeout_"); + BADCVAR("welcome_message_time"); BADPREFIX("crypto_"); BADPREFIX("g_chat_"); + BADPREFIX("g_ctf_captimerecord_"); + BADPREFIX("g_maplist_votable_"); BADPREFIX("net_"); BADPREFIX("prvm_"); - BADPREFIX("sv_fragmessage_"); + BADPREFIX("skill_"); + BADPREFIX("sv_cullentities_"); + BADPREFIX("sv_fraginfo_"); + BADPREFIX("sv_maxidle_"); BADPREFIX("sv_vote_"); BADPREFIX("timelimit_"); + BADCVAR("gameversion"); + BADPREFIX("gameversion_"); + BADCVAR("sv_namechangetimer"); +#ifndef NO_LEGACY_NETWORKING + BADCVAR("sv_use_csqc_players"); // transition +#endif // allowed changes to server admins (please sync this to server.cfg) // vi commands: @@ -389,6 +338,7 @@ void cvar_changes_init() // :%s,//\([^ ]*\).*,BADCVAR("\1");, // :%!sort // yes, this does contain some redundant stuff, don't really care + BADCVAR("bot_config_file"); BADCVAR("bot_number"); BADCVAR("bot_prefix"); BADCVAR("bot_suffix"); @@ -400,10 +350,9 @@ void cvar_changes_init() BADCVAR("g_balance_teams_force"); BADCVAR("g_ban_sync_trusted_servers"); BADCVAR("g_ban_sync_uri"); - BADCVAR("g_ctf_capture_limit"); BADCVAR("g_ctf_ignore_frags"); - BADCVAR("g_ctf_win_mode"); BADCVAR("g_domination_point_limit"); + BADCVAR("g_friendlyfire"); BADCVAR("g_fullbrightitems"); BADCVAR("g_fullbrightplayers"); BADCVAR("g_keyhunt_point_limit"); @@ -417,10 +366,14 @@ void cvar_changes_init() BADCVAR("g_maplist_votable_abstain"); BADCVAR("g_maplist_votable_nodetail"); BADCVAR("g_maplist_votable_suggestions"); + BADCVAR("g_maxplayers"); BADCVAR("g_minstagib"); + BADCVAR("g_mirrordamage"); BADCVAR("g_nexball_goallimit"); + BADCVAR("g_powerups"); BADCVAR("g_runematch_point_limit"); BADCVAR("g_start_delay"); + BADCVAR("g_warmup"); BADCVAR("g_weapon_stay"); BADPRESUFFIX("g_", "_weapon_stay"); BADCVAR("hostname"); BADCVAR("log_file"); @@ -434,6 +387,7 @@ void cvar_changes_init() BADCVAR("skill"); BADCVAR("sv_adminnick"); BADCVAR("sv_autoscreenshot"); + BADCVAR("sv_autotaunt"); BADCVAR("sv_curl_defaulturl"); BADCVAR("sv_defaultcharacter"); BADCVAR("sv_defaultplayercolors"); @@ -445,6 +399,7 @@ void cvar_changes_init() BADCVAR("sv_public"); BADCVAR("sv_ready_restart"); BADCVAR("sv_status_privacy"); + BADCVAR("sv_taunt"); BADCVAR("sv_vote_call"); BADCVAR("sv_vote_commands"); BADCVAR("sv_vote_majority_factor"); @@ -452,9 +407,12 @@ void cvar_changes_init() BADCVAR("sv_vote_master_commands"); BADCVAR("sv_vote_master_password"); BADCVAR("sv_vote_simple_majority_factor"); + BADCVAR("sys_ticrate"); + BADCVAR("teamplay_mode"); BADCVAR("timelimit_override"); - BADCVAR("g_warmup"); + BADCVAR("g_spawnshieldtime"); BADPREFIX("g_warmup_"); + BADPREFIX("sv_ready_restart_"); if(autocvar_g_minstagib) { @@ -574,6 +532,10 @@ void spawnfunc___init_dedicated_server(void) self.classname = "worldspawn"; // safeguard against various stuff ;) + // needs to be done so early because of the constants they create + RegisterWeapons(); + RegisterGametypes(); + MapInfo_Enumerate(); MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0); } @@ -608,7 +570,7 @@ void spawnfunc_worldspawn (void) allowed_to_spawn = TRUE; - local entity head; + entity head; head = nextent(world); maxclients = 0; while(head) @@ -617,10 +579,11 @@ void spawnfunc_worldspawn (void) head = nextent(head); } - // needs to be done so early as they would still spawn + // needs to be done so early because of the constants they create RegisterWeapons(); + RegisterGametypes(); - ServerProgsDB = db_load("server.db"); + ServerProgsDB = db_load(strcat("server.db", autocvar_sessionid)); TemporaryDB = db_create(); @@ -683,10 +646,6 @@ void spawnfunc_worldspawn (void) if(self.spawnflags & SPAWNFLAG_NO_WAYPOINTS_FOR_ITEMS) bot_waypoints_for_items = 0; - // for setting by mapinfo - q3acompat_machineshotgunswap = autocvar_sv_q3acompat_machineshotgunswap; - cvar_set("sv_q3acompat_machineshotgunswap", "0"); - precache(); WaypointSprite_Init(); @@ -695,10 +654,13 @@ void spawnfunc_worldspawn (void) // dom_init(); GameLogInit(); // prepare everything + // NOTE for matchid: + // changing the logic generating it is okay. But: + // it HAS to stay <= 64 chars + // character set: ASCII 33-126 without the following characters: : ; ' " \ $ if(autocvar_sv_eventlog) { - s = strcat(ftos(autocvar_sv_eventlog_files_counter), "."); - s = strcat(s, ftos(random())); + s = sprintf("%d.%s.%06d", ftos(autocvar_sv_eventlog_files_counter), strftime(FALSE, "%s"), floor(random() * 1000000)); matchid = strzone(s); GameLogEcho(strcat(":gamestart:", GetGametype(), "_", GetMapname(), ":", s)); @@ -717,8 +679,10 @@ void spawnfunc_worldspawn (void) s = strcat(s, ":no_use_ammunition"); // initialiation stuff, not good in the mutator system - if(!autocvar_g_pickup_items) + if(autocvar_g_pickup_items == 0) s = strcat(s, ":no_pickup_items"); + if(autocvar_g_pickup_items > 0) + s = strcat(s, ":pickup_items"); // initialiation stuff, not good in the mutator system if(autocvar_g_weaponarena != "0") @@ -736,6 +700,12 @@ void spawnfunc_worldspawn (void) if(autocvar_g_minstagib) s = strcat(s, ":minstagib"); + // TODO to mutator system + if(autocvar_g_powerups == 0) + s = strcat(s, ":no_powerups"); + if(autocvar_g_powerups > 0) + s = strcat(s, ":powerups"); + GameLogEcho(s); GameLogEcho(":gameinfo:end"); } @@ -768,22 +738,22 @@ void spawnfunc_worldspawn (void) continue; if(argv(0) == "cd") { - print("Found ^1DEPRECATED^7 cd loop command in .cfg file; put this line in mapinfo instead:\n"); + print("Found ^1UNSUPPORTED^7 cd loop command in .cfg file; put this line in mapinfo instead:\n"); print(" cdtrack ", argv(2), "\n"); } else if(argv(0) == "fog") { - print("Found ^1DEPRECATED^7 fog command in .cfg file; put this line in worldspawn in the .map/.bsp/.ent file instead:\n"); + print("Found ^1UNSUPPORTED^7 fog command in .cfg file; put this line in worldspawn in the .map/.bsp/.ent file instead:\n"); print(" \"fog\" \"", s, "\"\n"); } else if(argv(0) == "set") { - print("Found ^1DEPRECATED^7 set command in .cfg file; put this line in mapinfo instead:\n"); + print("Found ^1UNSUPPORTED^7 set command in .cfg file; put this line in mapinfo instead:\n"); print(" clientsettemp_for_type all ", argv(1), " ", argv(2), "\n"); } else if(argv(0) != "//") { - print("Found ^1DEPRECATED^7 set command in .cfg file; put this line in mapinfo instead:\n"); + print("Found ^1UNSUPPORTED^7 set command in .cfg file; put this line in mapinfo instead:\n"); print(" clientsettemp_for_type all ", argv(0), " ", argv(1), "\n"); } } @@ -795,6 +765,7 @@ void spawnfunc_worldspawn (void) addstat(STAT_WEAPONS, AS_INT, weapons); addstat(STAT_SWITCHWEAPON, AS_INT, switchweapon); + addstat(STAT_SWITCHINGWEAPON, AS_INT, switchingweapon); addstat(STAT_GAMESTARTTIME, AS_FLOAT, stat_game_starttime); addstat(STAT_ALLOW_OLDNEXBEAM, AS_INT, stat_allow_oldnexbeam); Nagger_Init(); @@ -805,12 +776,18 @@ void spawnfunc_worldspawn (void) addstat(STAT_FUEL, AS_INT, ammo_fuel); addstat(STAT_SHOTORG, AS_INT, stat_shotorg); addstat(STAT_LEADLIMIT, AS_FLOAT, stat_leadlimit); - addstat(STAT_BULLETS_LOADED, AS_INT, campingrifle_bulletcounter); + addstat(STAT_WEAPON_CLIPLOAD, AS_INT, clip_load); + addstat(STAT_WEAPON_CLIPSIZE, AS_INT, clip_size); addstat(STAT_LAST_PICKUP, AS_FLOAT, last_pickup); + addstat(STAT_HIT_TIME, AS_FLOAT, hit_time); + addstat(STAT_TYPEHIT_TIME, AS_FLOAT, typehit_time); + addstat(STAT_LAYED_MINES, AS_INT, minelayer_mines); addstat(STAT_NEX_CHARGE, AS_FLOAT, nex_charge); addstat(STAT_NEX_CHARGEPOOL, AS_FLOAT, nex_chargepool_ammo); + addstat(STAT_HAGAR_LOAD, AS_INT, hagar_load); + if(g_ca || g_freezetag) { addstat(STAT_REDALIVE, AS_INT, redalive_stat); @@ -829,11 +806,16 @@ void spawnfunc_worldspawn (void) addstat(STAT_MOVEVARS_MAXSPEED, AS_FLOAT, stat_sv_maxspeed); addstat(STAT_MOVEVARS_AIRACCEL_QW, AS_FLOAT, stat_sv_airaccel_qw); addstat(STAT_MOVEVARS_AIRSTRAFEACCEL_QW, AS_FLOAT, stat_sv_airstrafeaccel_qw); - + + // secrets + addstat(STAT_SECRETS_TOTAL, AS_FLOAT, stat_secrets_total); + addstat(STAT_SECRETS_FOUND, AS_FLOAT, stat_secrets_found); + next_pingtime = time + 5; detect_maptype(); - + + // set up information replies for clients and server to use lsmaps_reply = "^7Maps available: "; lsnewmaps_reply = "^7Maps without a record set: "; for(i = 0, j = 0; i < MapInfo_count; ++i) @@ -845,18 +827,20 @@ void spawnfunc_worldspawn (void) col = "^2"; else col = "^3"; + ++j; + lsmaps_reply = strcat(lsmaps_reply, col, MapInfo_Map_bspname, " "); + if(g_race && !stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, RACE_RECORD, "time")))) lsnewmaps_reply = strcat(lsnewmaps_reply, col, MapInfo_Map_bspname, " "); else if(g_cts && !stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, CTS_RECORD, "time")))) lsnewmaps_reply = strcat(lsnewmaps_reply, col, MapInfo_Map_bspname, " "); } } + lsmaps_reply = strzone(strcat(lsmaps_reply, "\n")); - if (!g_race && !g_cts) - lsnewmaps_reply = "Need to be playing race or CTS for lsnewmaps to work."; - lsnewmaps_reply = strzone(strcat(lsnewmaps_reply, "\n")); + lsnewmaps_reply = strzone(strcat(((!g_race && !g_cts) ? "Need to be playing race or CTS for lsnewmaps to work." : lsnewmaps_reply), "\n")); maplist_reply = "^7Maps in list: "; n = tokenize_console(autocvar_g_maplist); @@ -879,11 +863,12 @@ void spawnfunc_worldspawn (void) { records_reply[i] = strzone(getrecords(i)); } - if(g_cts) - ladder_reply = strzone(getladder()); + + ladder_reply = strzone(getladder()); rankings_reply = strzone(getrankings()); + // begin other init ClientInit_Spawn(); RandomSeed_Spawn(); PingPLReport_Spawn(); @@ -895,8 +880,21 @@ void spawnfunc_worldspawn (void) // fill sv_curl_serverpackages from .serverpackage files if(autocvar_sv_curl_serverpackages_auto) { - fd = search_begin("*.serverpackage", TRUE, FALSE); s = ""; + n = tokenize_console(cvar_string("sv_curl_serverpackages")); + for(i = 0; i < n; ++i) + if(substring(argv(i), -14, -1) != "-serverpackage.txt") + if(substring(argv(i), -14, -1) != ".serverpackage") // OLD legacy + s = strcat(s, " ", argv(i)); + fd = search_begin("*-serverpackage.txt", TRUE, FALSE); + if(fd >= 0) + { + j = search_getsize(fd); + for(i = 0; i < j; ++i) + s = strcat(s, " ", search_getfilename(fd, i)); + search_end(fd); + } + fd = search_begin("*.serverpackage", TRUE, FALSE); if(fd >= 0) { j = search_getsize(fd); @@ -918,22 +916,9 @@ void spawnfunc_light (void) remove(self); } -float TryFile( string pFilename ) -{ - local float lHandle; - dprint("TryFile(\"", pFilename, "\")\n"); - lHandle = fopen( pFilename, FILE_READ ); - if( lHandle != -1 ) { - fclose( lHandle ); - return TRUE; - } else { - return FALSE; - } -}; - string GetGametype() { - return GametypeNameFromType(game); + return MapInfo_Type_ToString(MapInfo_LoadedGametype); } string getmapname_stored; @@ -945,7 +930,7 @@ string GetMapname() float Map_Count, Map_Current; string Map_Current_Name; -// NOTE: this now expects the map list to be already tokenize()d and the count in Map_Count +// NOTE: this now expects the map list to be already tokenized and the count in Map_Count float GetMaplistPosition() { float pos, idx; @@ -974,14 +959,12 @@ float MapHasRightSize(string map) if(autocvar_g_maplist_check_waypoints) { dprint("checkwp "); dprint(map); - fh = fopen(strcat("maps/", map, ".waypoints"), FILE_READ); - if(fh < 0) + if(!fexists(strcat("maps/", map, ".waypoints"))) { dprint(": no waypoints\n"); return FALSE; } dprint(": has waypoints\n"); - fclose(fh); } // open map size restriction file @@ -1083,16 +1066,9 @@ void Map_Goto_SetFloat(float position) Map_Goto_SetStr(argv(position)); } -void GameResetCfg() -{ - // settings persist, except... - localcmd("\nsettemp_restore\n"); -}; - -void Map_Goto() +void Map_Goto(float reinit) { - GameResetCfg(); - MapInfo_LoadMap(getmapname_stored); + MapInfo_LoadMap(getmapname_stored, reinit); } // return codes of map selectors: @@ -1181,7 +1157,7 @@ void Maplist_Init() if(Map_Count == 0) { bprint( "Maplist is empty! Resetting it to default map list.\n" ); - cvar_set("g_maplist", MapInfo_ListAllowedMaps(MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags())); + cvar_set("g_maplist", MapInfo_ListAllAllowedMaps(MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags())); if(autocvar_g_maplist_shuffle) ShuffleMaplist(); localcmd("\nmenu_cmd sync\n"); @@ -1226,9 +1202,9 @@ string GetNextMap() } return ""; -}; +} -float DoNextMapOverride() +float DoNextMapOverride(float reinit) { if(autocvar_g_campaign) { @@ -1253,11 +1229,7 @@ float DoNextMapOverride() } if (autocvar_samelevel) // if samelevel is set, stay on same level { - // this does not work because it tries to exec maps/nexdm01.mapcfg (which doesn't exist, it should be trying maps/dm_nexdm01.mapcfg for example) - //localcmd(strcat("exec \"maps/", mapname, ".mapcfg\"\n")); - // so instead just restart the current map using the restart command (DOES NOT WORK PROPERLY WITH exit_cfg STUFF) localcmd("restart\n"); - //changelevel (mapname); alreadychangedlevel = TRUE; return TRUE; } @@ -1265,25 +1237,25 @@ float DoNextMapOverride() if(MapInfo_CheckMap(autocvar_nextmap)) { Map_Goto_SetStr(autocvar_nextmap); - Map_Goto(); + Map_Goto(reinit); alreadychangedlevel = TRUE; return TRUE; } if(autocvar_lastlevel) { - GameResetCfg(); - localcmd("set lastlevel 0\ntogglemenu\n"); + cvar_settemp_restore(); + localcmd("set lastlevel 0\ntogglemenu 1\n"); alreadychangedlevel = TRUE; return TRUE; } return FALSE; -}; +} -void GotoNextMap() +void GotoNextMap(float reinit) { - //local string nextmap; - //local float n, nummaps; - //local string s; + //string nextmap; + //float n, nummaps; + //string s; if (alreadychangedlevel) return; alreadychangedlevel = TRUE; @@ -1301,7 +1273,7 @@ void GotoNextMap() if(allowReset) { bprint( "Maplist contains no single playable map! Resetting it to default map list.\n" ); - cvar_set("g_maplist", MapInfo_ListAllowedMaps(MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags())); + cvar_set("g_maplist", MapInfo_ListAllAllowedMaps(MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags())); if(autocvar_g_maplist_shuffle) ShuffleMaplist(); localcmd("\nmenu_cmd sync\n"); @@ -1311,9 +1283,9 @@ void GotoNextMap() error("Everything is broken - not even the default map list works. Please report this to the developers."); } } - Map_Goto(); + Map_Goto(reinit); } -}; +} /* @@ -1330,14 +1302,15 @@ float mapvote_initialized; void IntermissionThink() { FixIntermissionClient(self); - - if(autocvar_sv_autoscreenshot) - if(self.autoscreenshot > 0) - if(time > self.autoscreenshot) + + float server_screenshot = (autocvar_sv_autoscreenshot && self.cvar_cl_autoscreenshot); + float client_screenshot = (self.cvar_cl_autoscreenshot == 2); + + if( (server_screenshot || client_screenshot) + && ((self.autoscreenshot > 0) && (time > self.autoscreenshot)) ) { self.autoscreenshot = -1; - if(clienttype(self) == CLIENTTYPE_REAL) - stuffcmd(self, "\nscreenshot\necho \"^5A screenshot has been taken at request of the server.\"\n"); + if(clienttype(self) == CLIENTTYPE_REAL) { stuffcmd(self, sprintf("\nscreenshot screenshots/autoscreenshot/%s-%s.jpg; echo \"^5A screenshot has been taken at request of the server.\"", GetMapname(), strftime(FALSE, "%s"))); } return; } @@ -1345,11 +1318,11 @@ void IntermissionThink() return; if(!mapvote_initialized) - if (time < intermission_exittime + 10 && !self.BUTTON_ATCK && !self.BUTTON_JUMP && !self.BUTTON_ATCK2 && !self.BUTTON_HOOK && !self.BUTTON_USE) + if (time < intermission_exittime + 10 && !(self.BUTTON_ATCK || self.BUTTON_JUMP || self.BUTTON_ATCK2 || self.BUTTON_HOOK || self.BUTTON_USE)) return; MapVote_Start(); -}; +} /* ============ @@ -1396,7 +1369,7 @@ entity FindIntermission() //objerror ("FindIntermission: no spot"); return world; -}; +} */ /* @@ -1415,7 +1388,6 @@ void DumpStats(float final) float to_eventlog; float to_file; float i; - entity e; to_console = autocvar_sv_logscores_console; to_eventlog = autocvar_sv_eventlog; @@ -1478,7 +1450,7 @@ void DumpStats(float final) } } - if(teams_matter) + if(teamplay) { s = strcat(":labels:teamscores:", GetTeamScoreString(0, 0)); if(to_console) @@ -1510,11 +1482,6 @@ void DumpStats(float final) fputs(file, ":end\n"); fclose(file); } - - // send statistics - FOR_EACH_CLIENT(e) - PlayerStats_AddGlobalInfo(e); - PlayerStats_Shutdown(); } void FixIntermissionClient(entity e) @@ -1522,8 +1489,6 @@ void FixIntermissionClient(entity e) string s; if(!e.autoscreenshot) // initial call { - e.angles = e.v_angle; - e.angles_x = -e.angles_x; e.autoscreenshot = time + 0.8; // used for autoscreenshot e.health = -2342; // first intermission phase; voting phase has positive health (used to decide whether to send SVC_FINALE or not) @@ -1546,11 +1511,6 @@ void FixIntermissionClient(entity e) WriteByte(MSG_ONE, SVC_INTERMISSION); } } - - //e.velocity = '0 0 0'; - //e.fixangle = TRUE; - - // TODO halt weapon animation } @@ -1583,6 +1543,14 @@ void NextLevel() DumpStats(TRUE); + // send statistics + entity e; + PlayerStats_EndMatch(1); + FOR_EACH_CLIENT(e) + PlayerStats_AddGlobalInfo(e); + PlayerStats_Shutdown(); + WeaponStats_Shutdown(); + if(autocvar_sv_eventlog) GameLogEcho(":gameover"); @@ -1617,7 +1585,7 @@ void CheckRules_Player() // fixme: don't check players; instead check spawnfunc_dom_team and spawnfunc_ctf_team entities // (div0: and that in CheckRules_World please) -}; +} float checkrules_equality; float checkrules_suddendeathwarning; @@ -1726,7 +1694,7 @@ void ClearWinners(void) float WinningCondition_Onslaught() { entity head; - local float t1, t2, t3, t4; + float t1, t2, t3, t4; WinningConditionHelper(); // set worldstatus @@ -1786,7 +1754,7 @@ float LMS_NewPlayerLives() void assault_new_round(); float WinningCondition_Assault() { - local float status; + float status; WinningConditionHelper(); // set worldstatus @@ -1801,7 +1769,7 @@ float WinningCondition_Assault() SetWinners(team, COLOR_TEAM1); } - local entity ent; + entity ent; ent = find(world, classname, "target_assault_roundend"); if(ent) { @@ -1818,7 +1786,7 @@ float WinningCondition_Assault() } else { - local entity oldself; + entity oldself; oldself = self; self = ent; assault_new_round(); @@ -1922,7 +1890,7 @@ float WinningCondition_Scores(float limit, float leadlimit) // TODO make everything use THIS winning condition (except LMS) WinningConditionHelper(); - if(teams_matter) + if(teamplay) { team1_score = TeamScore_GetCompareValue(COLOR_TEAM1); team2_score = TeamScore_GetCompareValue(COLOR_TEAM2); @@ -2010,7 +1978,6 @@ float WinningCondition_Race(float fraglimit) return wc; } -void ReadyRestart(); float WinningCondition_QualifyingThenRace(float limit) { float wc; @@ -2032,6 +1999,9 @@ float WinningCondition_RanOutOfSpawns() if(have_team_spawns <= 0) return WINNING_NO; + if(autocvar_g_spawn_useallspawns <= 0) + return WINNING_NO; + if(!some_spawn_has_been_used) return WINNING_NO; @@ -2097,6 +2067,7 @@ CheckRules_World Exit deathmatch games upon conditions ============ */ +void ReadyRestart(); void CheckRules_World() { float timelimit; @@ -2273,7 +2244,7 @@ void CheckRules_World() //print("WINNING\n"); NextLevel(); } -}; +} float mapvote_nextthink; float mapvote_initialized; @@ -2292,9 +2263,8 @@ string mapvote_maps_pakfile[MAPVOTE_COUNT]; float mapvote_maps_suggested[MAPVOTE_COUNT]; string mapvote_suggestions[MAPVOTE_COUNT]; float mapvote_suggestion_ptr; -float mapvote_maxlen; float mapvote_voters; -float mapvote_votes[MAPVOTE_COUNT]; +float mapvote_selections[MAPVOTE_COUNT]; float mapvote_run; float mapvote_detail; float mapvote_abstain; @@ -2354,8 +2324,10 @@ void MapVote_AddVotable(string nextMap, float isSuggestion) for(j = 0; j < mapvote_count; ++j) if(mapvote_maps[j] == nextMap) return; - if(strlen(nextMap) > mapvote_maxlen) - mapvote_maxlen = strlen(nextMap); + // suggestions might be no longer valid/allowed after gametype switch! + if(isSuggestion) + if(!MapInfo_CheckMap(nextMap)) + return; mapvote_maps[mapvote_count] = strzone(nextMap); mapvote_maps_suggested[mapvote_count] = isSuggestion; @@ -2417,7 +2389,7 @@ void MapVote_Init() if(mapvote_count == 0) { bprint( "Maplist contains no single playable map! Resetting it to default map list.\n" ); - cvar_set("g_maplist", MapInfo_ListAllowedMaps(MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags())); + cvar_set("g_maplist", MapInfo_ListAllAllowedMaps(MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags())); if(autocvar_g_maplist_shuffle) ShuffleMaplist(); localcmd("\nmenu_cmd sync\n"); @@ -2449,20 +2421,6 @@ void MapVote_SendPicture(float id) WritePicture(MSG_ONE, strcat(mapvote_screenshot_dirs[mapvote_maps_screenshot_dir[id]], "/", mapvote_maps[id]), 3072); } -float GameCommand_MapVote(string cmd) -{ - if(!intermission_running) - return FALSE; - - if(cmd == "mv_getpic") - { - MapVote_SendPicture(stof(argv(1))); - return TRUE; - } - - return FALSE; -} - float MapVote_GetMapMask() { float mask, i, power; @@ -2530,7 +2488,7 @@ float MapVote_SendEntity(entity to, float sf) if(mapvote_detail) for(i = 0; i < mapvote_count; ++i) if(mapvote_maps[i] != "") - WriteByte(MSG_ENTITY, mapvote_votes[i]); + WriteByte(MSG_ENTITY, mapvote_selections[i]); WriteByte(MSG_ENTITY, to.mapvote); } @@ -2562,16 +2520,16 @@ float MapVote_Finished(float mappos) if(autocvar_sv_eventlog) { result = strcat(":vote:finished:", mapvote_maps[mappos]); - result = strcat(result, ":", ftos(mapvote_votes[mappos]), "::"); + result = strcat(result, ":", ftos(mapvote_selections[mappos]), "::"); didntvote = mapvote_voters; for(i = 0; i < mapvote_count; ++i) if(mapvote_maps[i] != "") { - didntvote -= mapvote_votes[i]; + didntvote -= mapvote_selections[i]; if(i != mappos) { result = strcat(result, ":", mapvote_maps[i]); - result = strcat(result, ":", ftos(mapvote_votes[i])); + result = strcat(result, ":", ftos(mapvote_selections[i])); } } result = strcat(result, ":didn't vote:", ftos(didntvote)); @@ -2585,7 +2543,7 @@ float MapVote_Finished(float mappos) FixClientCvars(other); Map_Goto_SetStr(mapvote_maps[mappos]); - Map_Goto(); + Map_Goto(0); alreadychangedlevel = TRUE; return TRUE; } @@ -2596,7 +2554,7 @@ void MapVote_CheckRules_1() for(i = 0; i < mapvote_count; ++i) if(mapvote_maps[i] != "") { //dprint("Map ", ftos(i), ": "); dprint(mapvote_maps[i], "\n"); - mapvote_votes[i] = 0; + mapvote_selections[i] = 0; } mapvote_voters = 0; @@ -2607,7 +2565,7 @@ void MapVote_CheckRules_1() { i = other.mapvote - 1; //dprint("Player ", other.netname, " vote = ", ftos(other.mapvote - 1), "\n"); - mapvote_votes[i] = mapvote_votes[i] + 1; + mapvote_selections[i] = mapvote_selections[i] + 1; } } } @@ -2625,11 +2583,11 @@ float MapVote_CheckRules_2() mapvote_voters_real = mapvote_voters; if(mapvote_abstain) - mapvote_voters_real -= mapvote_votes[mapvote_count - 1]; + mapvote_voters_real -= mapvote_selections[mapvote_count - 1]; RandomSelection_Init(); for(i = 0; i < mapvote_count_real; ++i) if(mapvote_maps[i] != "") - RandomSelection_Add(world, i, string_null, 1, mapvote_votes[i]); + RandomSelection_Add(world, i, string_null, 1, mapvote_selections[i]); firstPlace = RandomSelection_chosen_float; firstPlaceVotes = RandomSelection_best_priority; //dprint("First place: ", ftos(firstPlace), "\n"); @@ -2638,7 +2596,7 @@ float MapVote_CheckRules_2() RandomSelection_Init(); for(i = 0; i < mapvote_count_real; ++i) if(mapvote_maps[i] != "") if(i != firstPlace) - RandomSelection_Add(world, i, string_null, 1, mapvote_votes[i]); + RandomSelection_Add(world, i, string_null, 1, mapvote_selections[i]); secondPlace = RandomSelection_chosen_float; secondPlaceVotes = RandomSelection_best_priority; //dprint("Second place: ", ftos(secondPlace), "\n"); @@ -2665,12 +2623,12 @@ float MapVote_CheckRules_2() for(i = 0; i < mapvote_count; ++i) if(mapvote_maps[i] != "") { - didntvote -= mapvote_votes[i]; + didntvote -= mapvote_selections[i]; if(i != firstPlace) if(i != secondPlace) { result = strcat(result, ":", mapvote_maps[i]); - result = strcat(result, ":", ftos(mapvote_votes[i])); + result = strcat(result, ":", ftos(mapvote_selections[i])); if(i < mapvote_count_real) { strunzone(mapvote_maps[i]); @@ -2781,18 +2739,18 @@ void MapVote_Think() } mapvote_initialized = TRUE; - if(DoNextMapOverride()) + if(DoNextMapOverride(0)) return; if(!autocvar_g_maplist_votable || player_count <= 0) { - GotoNextMap(); + GotoNextMap(0); return; } MapVote_Init(); } MapVote_Tick(); -}; +} string GotoMap(string m) { @@ -2802,7 +2760,7 @@ string GotoMap(string m) cvar_set("timelimit", "-1"); if(mapvote_initialized || alreadychangedlevel) { - if(DoNextMapOverride()) + if(DoNextMapOverride(0)) return "Map switch initiated."; else return "Hm... no. For some reason I like THIS map more."; @@ -2820,16 +2778,16 @@ void EndFrame() if(self.classname == "spectator") { if(self.enemy.typehitsound) - play2(self, "misc/typehit.wav"); - else if(self.enemy.hitsound && self.cvar_cl_hitsound) - play2(self, "misc/hit.wav"); + self.typehit_time = time; + else if(self.enemy.hitsound) + self.hit_time = time; } else { if(self.typehitsound) - play2(self, "misc/typehit.wav"); - else if(self.hitsound && self.cvar_cl_hitsound) - play2(self, "misc/hit.wav"); + self.typehit_time = time; + else if(self.hitsound) + self.hit_time = time; } } altime = time + frametime * (1 + autocvar_g_antilag_nudge); @@ -2901,7 +2859,7 @@ void RestoreGame() // some things then break, so let's work around them... // Progs DB (capture records) - ServerProgsDB = db_load("server.db"); + ServerProgsDB = db_load(strcat("server.db", autocvar_sessionid)); // Mapinfo MapInfo_Shutdown(); @@ -2912,14 +2870,11 @@ void RestoreGame() TargetMusic_RestoreGame(); } -void SV_Shutdown() +void Shutdown() { entity e; - if(gameover > 1) // shutting down already? - return; - - gameover = 2; // 2 = server shutting down + gameover = 2; if(world_initialized > 0) { @@ -2927,6 +2882,7 @@ void SV_Shutdown() print("Saving persistent data...\n"); Ban_SaveBans(); + PlayerStats_EndMatch(0); FOR_EACH_CLIENT(e) PlayerStats_AddGlobalInfo(e); PlayerStats_Shutdown(); @@ -2934,9 +2890,9 @@ void SV_Shutdown() if(!cheatcount_total) { if(autocvar_sv_db_saveasdump) - db_dump(ServerProgsDB, "server.db"); + db_dump(ServerProgsDB, strcat("server.db", autocvar_sessionid)); else - db_save(ServerProgsDB, "server.db"); + db_save(ServerProgsDB, strcat("server.db", autocvar_sessionid)); } if(autocvar_developer) { diff --git a/qcsrc/server/gamecommand.qc b/qcsrc/server/gamecommand.qc deleted file mode 100644 index 5957e82bc1..0000000000 --- a/qcsrc/server/gamecommand.qc +++ /dev/null @@ -1,1384 +0,0 @@ -string GotoMap(string m); -void race_deleteTime(string map, float pos); - -float FullTraceFraction(vector a, vector mi, vector ma, vector b) -{ - vector c; - float white, black; - - white = 0.001; - black = 0.001; - - c = a; - - float n, m; - n = m = 0; - - while(vlen(c - b) > 1) - { - ++m; - - tracebox(c, mi, ma, b, MOVE_WORLDONLY, world); - ++n; - - if(!trace_startsolid) - { - black += vlen(trace_endpos - c); - c = trace_endpos; - } - - n += tracebox_inverted(c, mi, ma, b, MOVE_WORLDONLY, world); - - white += vlen(trace_endpos - c); - c = trace_endpos; - } - - if(n > 200) - dprint("HOLY SHIT! FullTraceFraction: ", ftos(n), " total traces, ", ftos(m), " iterations\n"); - - return white / (black + white); -} - -float RadarMapAtPoint_Trace(float x, float y, float w, float h, float zmin, float zsize, float q) -{ - vector a, b, mi, ma; - - mi = '0 0 0'; - ma = '1 0 0' * w + '0 1 0' * h; - a = '1 0 0' * x + '0 1 0' * y + '0 0 1' * zmin; - b = '1 0 0' * x + '0 1 0' * y + '0 0 1' * (zsize + zmin); - - return FullTraceFraction(a, mi, ma, b); -} -float RadarMapAtPoint_LineBlock(float x, float y, float w, float h, float zmin, float zsize, float q) -{ - vector o, mi, ma; - float i, r; - vector dz; - - q = 256 * q - 1; - // 256q-1 is the ideal sample count to map equal amount of sample values to one pixel value - - mi = '0 0 0'; - dz = (zsize / q) * '0 0 1'; - ma = '1 0 0' * w + '0 1 0' * h + dz; - o = '1 0 0' * x + '0 1 0' * y + '0 0 1' * zmin; - - if(x < world.absmin_x - w) - return 0; - if(y < world.absmin_y - h) - return 0; - if(x > world.absmax_x) - return 0; - if(y > world.absmax_y) - return 0; - - r = 0; - for(i = 0; i < q; ++i) - { - vector v1, v2; - v1 = v2 = o + dz * i + mi; - v1_x += random() * (ma_x - mi_x); - v1_y += random() * (ma_y - mi_y); - v1_z += random() * (ma_z - mi_z); - v2_x += random() * (ma_x - mi_x); - v2_y += random() * (ma_y - mi_y); - v2_z += random() * (ma_z - mi_z); - traceline(v1, v2, MOVE_WORLDONLY, world); - if(trace_startsolid || trace_fraction < 1) - ++r; - } - return r / q; -} -float RadarMapAtPoint_Block(float x, float y, float w, float h, float zmin, float zsize, float q) -{ - vector o, mi, ma; - float i, r; - vector dz; - - q = 256 * q - 1; - // 256q-1 is the ideal sample count to map equal amount of sample values to one pixel value - - mi = '0 0 0'; - dz = (zsize / q) * '0 0 1'; - ma = '1 0 0' * w + '0 1 0' * h + dz; - o = '1 0 0' * x + '0 1 0' * y + '0 0 1' * zmin; - - if(x < world.absmin_x - w) - return 0; - if(y < world.absmin_y - h) - return 0; - if(x > world.absmax_x) - return 0; - if(y > world.absmax_y) - return 0; - - r = 0; - for(i = 0; i < q; ++i) - { - tracebox(o + dz * i, mi, ma, o + dz * i, MOVE_WORLDONLY, world); - if(trace_startsolid) - ++r; - } - return r / q; -} -float RadarMapAtPoint_Sample(float x, float y, float w, float h, float zmin, float zsize, float q) -{ - vector a, b, mi, ma; - - q *= 4; // choose q so it matches the regular algorithm in speed - - q = 256 * q - 1; - // 256q-1 is the ideal sample count to map equal amount of sample values to one pixel value - - mi = '0 0 0'; - ma = '1 0 0' * w + '0 1 0' * h; - a = '1 0 0' * x + '0 1 0' * y + '0 0 1' * zmin; - b = '1 0 0' * w + '0 1 0' * h + '0 0 1' * zsize; - - float c, i; - c = 0; - - for(i = 0; i < q; ++i) - { - vector v; - v_x = a_x + random() * b_x; - v_y = a_y + random() * b_y; - v_z = a_z + random() * b_z; - traceline(v, v, MOVE_WORLDONLY, world); - if(trace_startsolid) - ++c; - } - - return c / q; -} - -// FF is contained twice, to map 256 to FF too -// removes the need to bound() -string doublehex = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFFFF"; - -float RADAR_WIDTH_MAX = 2048; -float RADAR_HEIGHT_MAX = 2048; -float sharpen_buffer[RADAR_WIDTH_MAX * 3]; - -void sharpen_set(float x, float v) -{ - sharpen_buffer[x + 2 * RADAR_WIDTH_MAX] = v; -} - -float sharpen_getpixel(float x, float y) -{ - if(x < 0) - return 0; - if(x >= RADAR_WIDTH_MAX) - return 0; - if(y < 0) - return 0; - if(y > 2) - return 0; - return sharpen_buffer[x + y * RADAR_WIDTH_MAX]; -} - -float sharpen_get(float x, float a) -{ - float sum; - sum = sharpen_getpixel(x, 1); - if(a == 0) - return sum; - sum *= (8 + 1/a); - sum -= sharpen_getpixel(x - 1, 0); - sum -= sharpen_getpixel(x - 1, 1); - sum -= sharpen_getpixel(x - 1, 2); - sum -= sharpen_getpixel(x + 1, 0); - sum -= sharpen_getpixel(x + 1, 1); - sum -= sharpen_getpixel(x + 1, 2); - sum -= sharpen_getpixel(x, 0); - sum -= sharpen_getpixel(x, 2); - return bound(0, sum * a, 1); -} - -void sharpen_shift(float w) -{ - float i; - for(i = 0; i < w; ++i) - { - sharpen_buffer[i] = sharpen_buffer[i + RADAR_WIDTH_MAX]; - sharpen_buffer[i + RADAR_WIDTH_MAX] = sharpen_buffer[i + 2 * RADAR_WIDTH_MAX]; - sharpen_buffer[i + 2 * RADAR_WIDTH_MAX] = 0; - } -} - -void sharpen_init(float w) -{ - float i; - for(i = 0; i < w; ++i) - { - sharpen_buffer[i] = 0; - sharpen_buffer[i + RADAR_WIDTH_MAX] = 0; - sharpen_buffer[i + 2 * RADAR_WIDTH_MAX] = 0; - } -} - -entity radarmapper; -void RadarMap_Next() -{ - if(radarmapper.count & 4) - { - localcmd("quit\n"); - } - else if(radarmapper.count & 2) - { - localcmd(strcat("defer 1 \"sv_cmd radarmap --flags ", ftos(radarmapper.count), strcat(" --res ", ftos(radarmapper.size_x), " ", ftos(radarmapper.size_y), " --sharpen ", ftos(radarmapper.ltime), " --qual ", ftos(radarmapper.size_z)), "\"\n")); - GotoNextMap(); - } - remove(radarmapper); - radarmapper = world; -} - -// rough map entity -// cnt: current line -// size: pixel width/height -// maxs: cell width/height -// frame: counter -void RadarMap_Think() -{ - float i, x, l; - string si; - - if(self.frame == 0) - { - // initialize - get_mi_min_max_texcoords(1); - self.mins = mi_picmin; - self.maxs_x = (mi_picmax_x - mi_picmin_x) / self.size_x; - self.maxs_y = (mi_picmax_y - mi_picmin_y) / self.size_y; - self.maxs_z = mi_max_z - mi_min_z; - print("Picture mins/maxs: ", ftos(self.maxs_x), " and ", ftos(self.maxs_y), " should match\n"); - self.netname = strzone(strcat("gfx/", mi_shortname, "_radar.xpm")); - if(!(self.count & 1)) - { - self.cnt = fopen(self.netname, FILE_READ); - if(self.cnt < 0) - self.cnt = fopen(strcat("gfx/", mi_shortname, "_radar.tga"), FILE_READ); - if(self.cnt < 0) - self.cnt = fopen(strcat("gfx/", mi_shortname, "_radar.png"), FILE_READ); - if(self.cnt < 0) - self.cnt = fopen(strcat("gfx/", mi_shortname, "_radar.jpg"), FILE_READ); - if(self.cnt < 0) - self.cnt = fopen(strcat("gfx/", mi_shortname, "_mini.tga"), FILE_READ); - if(self.cnt < 0) - self.cnt = fopen(strcat("gfx/", mi_shortname, "_mini.png"), FILE_READ); - if(self.cnt < 0) - self.cnt = fopen(strcat("gfx/", mi_shortname, "_mini.jpg"), FILE_READ); - if(self.cnt >= 0) - { - fclose(self.cnt); - - print(self.netname, " already exists, aborting (you may want to specify --force)\n"); - RadarMap_Next(); - return; - } - } - self.cnt = fopen(self.netname, FILE_WRITE); - if(self.cnt < 0) - { - print("Error writing ", self.netname, "\n"); - remove(self); - radarmapper = world; - return; - } - print("Writing to ", self.netname, "...\n"); - fputs(self.cnt, "/* XPM */\n"); - fputs(self.cnt, "static char *RadarMap[] = {\n"); - fputs(self.cnt, "/* columns rows colors chars-per-pixel */\n"); - fputs(self.cnt, strcat("\"", ftos(self.size_x), " ", ftos(self.size_y), " 256 2\",\n")); - for(i = 0; i < 256; ++i) - { - si = substring(doublehex, i*2, 2); - fputs(self.cnt, strcat("\"", si, " c #", si, si, si, "\",\n")); - } - self.frame += 1; - self.nextthink = time; - sharpen_init(self.size_x); - } - else if(self.frame <= self.size_y) - { - // fill the sharpen buffer with this line - sharpen_shift(self.size_x); - i = self.count & 24; - - switch(i) - { - case 0: - default: - for(x = 0; x < self.size_x; ++x) - { - l = RadarMapAtPoint_Block(self.mins_x + x * self.maxs_x, self.mins_y + (self.size_y - self.frame) * self.maxs_y, self.maxs_x, self.maxs_y, self.mins_z, self.maxs_z, self.size_z); - sharpen_set(x, l); - } - break; - case 8: - for(x = 0; x < self.size_x; ++x) - { - l = RadarMapAtPoint_Trace(self.mins_x + x * self.maxs_x, self.mins_y + (self.size_y - self.frame) * self.maxs_y, self.maxs_x, self.maxs_y, self.mins_z, self.maxs_z, self.size_z); - sharpen_set(x, l); - } - break; - case 16: - for(x = 0; x < self.size_x; ++x) - { - l = RadarMapAtPoint_Sample(self.mins_x + x * self.maxs_x, self.mins_y + (self.size_y - self.frame) * self.maxs_y, self.maxs_x, self.maxs_y, self.mins_z, self.maxs_z, self.size_z); - sharpen_set(x, l); - } - break; - case 24: - for(x = 0; x < self.size_x; ++x) - { - l = RadarMapAtPoint_LineBlock(self.mins_x + x * self.maxs_x, self.mins_y + (self.size_y - self.frame) * self.maxs_y, self.maxs_x, self.maxs_y, self.mins_z, self.maxs_z, self.size_z); - sharpen_set(x, l); - } - break; - } - - // do we have enough lines? - if(self.frame >= 2) - { - // write a pixel line - fputs(self.cnt, "\""); - for(x = 0; x < self.size_x; ++x) - { - l = sharpen_get(x, self.ltime); - fputs(self.cnt, substring(doublehex, 2 * floor(l * 256.0), 2)); - } - if(self.frame == self.size_y) - fputs(self.cnt, "\"\n"); - else - { - fputs(self.cnt, "\",\n"); - print(ftos(self.size_y - self.frame), " lines left\n"); - } - } - - // is this the last line? then write back the missing line - if(self.frame == self.size_y) - { - sharpen_shift(self.size_x); - // write a pixel line - fputs(self.cnt, "\""); - for(x = 0; x < self.size_x; ++x) - { - l = sharpen_get(x, self.ltime); - fputs(self.cnt, substring(doublehex, 2 * floor(l * 256.0), 2)); - } - if(self.frame == self.size_y) - fputs(self.cnt, "\"\n"); - else - { - fputs(self.cnt, "\",\n"); - print(ftos(self.size_y - self.frame), " lines left\n"); - } - } - - self.frame += 1; - self.nextthink = time; - } - else - { - // close the file - fputs(self.cnt, "};\n"); - fclose(self.cnt); - print("Finished. Please edit data/", self.netname, " with an image editing application and place it in the TGA format in the gfx folder.\n"); - RadarMap_Next(); - } -} - -void RadarMap(float argc) -{ - if(radarmapper) - return; - float i; - radarmapper = spawn(); - radarmapper.classname = "radarmapper"; - radarmapper.think = RadarMap_Think; - radarmapper.nextthink = time; - radarmapper.count = 8; // default to the --trace method, as it is faster now - radarmapper.ltime = 1; - radarmapper.size_x = 512; - radarmapper.size_y = 512; - radarmapper.size_z = 1; - - for(i = 1; i < argc; ++i) - { - if(argv(i) == "--force") - radarmapper.count |= 1; - else if(argv(i) == "--loop") - radarmapper.count |= 2; - else if(argv(i) == "--quit") - radarmapper.count |= 4; - else if(argv(i) == "--block") - { - radarmapper.count &~= 24; - } - else if(argv(i) == "--trace") - { - radarmapper.count &~= 24; - radarmapper.count |= 8; - } - else if(argv(i) == "--sample") - { - radarmapper.count &~= 24; - radarmapper.count |= 16; - } - else if(argv(i) == "--lineblock") - { - radarmapper.count |= 24; - } - else if(argv(i) == "--flags") // for the recursive call - { - ++i; - radarmapper.count = stof(argv(i)); - } - else if(argv(i) == "--sharpen") // for the recursive call - { - ++i; - radarmapper.ltime = stof(argv(i)); - } - else if(argv(i) == "--res") // resolution - { - ++i; - radarmapper.size_x = stof(argv(i)); - ++i; - radarmapper.size_y = stof(argv(i)); - } - else if(argv(i) == "--qual") // quality multiplier - { - ++i; - radarmapper.size_z = stof(argv(i)); - } - else - { - remove(radarmapper); - radarmapper = world; - print("Usage: sv_cmd radarmap [--force] [--loop] [--quit] [--block | --trace | --sample | --lineblock] [--sharpen N] [--res W H] [--qual Q]\n"); - print("The quality factor Q is roughly proportional to the time taken.\n"); - print("--trace supports no quality factor; its result should look like --block with infinite quality factor.\n"); - print("--block \n"); - return; - } - } - - print("Radarmap entity spawned.\n"); -} - -void BBox() -{ - print("Original size: ", ftos(world.absmin_x), " ", ftos(world.absmin_y), " ", ftos(world.absmin_z)); - print(" ", ftos(world.absmax_x), " ", ftos(world.absmax_y), " ", ftos(world.absmax_z), "\n"); - print("Currently set size: ", ftos(world.mins_x), " ", ftos(world.mins_y), " ", ftos(world.mins_z)); - print(" ", ftos(world.maxs_x), " ", ftos(world.maxs_y), " ", ftos(world.maxs_z), "\n"); - print("Solid bounding box size:"); - - tracebox('1 0 0' * world.absmin_x, - '0 1 0' * world.absmin_y + '0 0 1' * world.absmin_z, - '0 1 0' * world.absmax_y + '0 0 1' * world.absmax_z, - '1 0 0' * world.absmax_x, - MOVE_WORLDONLY, - world); - if(trace_startsolid) - print(" ", ftos(world.absmin_x)); - else - print(" ", ftos(trace_endpos_x)); - - tracebox('0 1 0' * world.absmin_y, - '1 0 0' * world.absmin_x + '0 0 1' * world.absmin_z, - '1 0 0' * world.absmax_x + '0 0 1' * world.absmax_z, - '0 1 0' * world.absmax_y, - MOVE_WORLDONLY, - world); - if(trace_startsolid) - print(" ", ftos(world.absmin_y)); - else - print(" ", ftos(trace_endpos_y)); - - tracebox('0 0 1' * world.absmin_z, - '1 0 0' * world.absmin_x + '0 1 0' * world.absmin_y, - '1 0 0' * world.absmax_x + '0 1 0' * world.absmax_y, - '0 0 1' * world.absmax_z, - MOVE_WORLDONLY, - world); - if(trace_startsolid) - print(" ", ftos(world.absmin_z)); - else - print(" ", ftos(trace_endpos_z)); - - tracebox('1 0 0' * world.absmax_x, - '0 1 0' * world.absmin_y + '0 0 1' * world.absmin_z, - '0 1 0' * world.absmax_y + '0 0 1' * world.absmax_z, - '1 0 0' * world.absmin_x, - MOVE_WORLDONLY, - world); - if(trace_startsolid) - print(" ", ftos(world.absmax_x)); - else - print(" ", ftos(trace_endpos_x)); - - tracebox('0 1 0' * world.absmax_y, - '1 0 0' * world.absmin_x + '0 0 1' * world.absmin_z, - '1 0 0' * world.absmax_x + '0 0 1' * world.absmax_z, - '0 1 0' * world.absmin_y, - MOVE_WORLDONLY, - world); - if(trace_startsolid) - print(" ", ftos(world.absmax_y)); - else - print(" ", ftos(trace_endpos_y)); - - tracebox('0 0 1' * world.absmax_z, - '1 0 0' * world.absmin_x + '0 1 0' * world.absmin_y, - '1 0 0' * world.absmax_x + '0 1 0' * world.absmax_y, - '0 0 1' * world.absmin_z, - MOVE_WORLDONLY, - world); - if(trace_startsolid) - print(" ", ftos(world.absmax_z)); - else - print(" ", ftos(trace_endpos_z)); - - print("\n"); -} - -void EffectIndexDump() -{ - float d; - float fh; - string s; - - d = db_create(); - - print("begin of effects list\n"); - db_put(d, "TE_GUNSHOT", "1"); print("effect TE_GUNSHOT is ", ftos(particleeffectnum("TE_GUNSHOT")), "\n"); - db_put(d, "TE_GUNSHOTQUAD", "1"); print("effect TE_GUNSHOTQUAD is ", ftos(particleeffectnum("TE_GUNSHOTQUAD")), "\n"); - db_put(d, "TE_SPIKE", "1"); print("effect TE_SPIKE is ", ftos(particleeffectnum("TE_SPIKE")), "\n"); - db_put(d, "TE_SPIKEQUAD", "1"); print("effect TE_SPIKEQUAD is ", ftos(particleeffectnum("TE_SPIKEQUAD")), "\n"); - db_put(d, "TE_SUPERSPIKE", "1"); print("effect TE_SUPERSPIKE is ", ftos(particleeffectnum("TE_SUPERSPIKE")), "\n"); - db_put(d, "TE_SUPERSPIKEQUAD", "1"); print("effect TE_SUPERSPIKEQUAD is ", ftos(particleeffectnum("TE_SUPERSPIKEQUAD")), "\n"); - db_put(d, "TE_WIZSPIKE", "1"); print("effect TE_WIZSPIKE is ", ftos(particleeffectnum("TE_WIZSPIKE")), "\n"); - db_put(d, "TE_KNIGHTSPIKE", "1"); print("effect TE_KNIGHTSPIKE is ", ftos(particleeffectnum("TE_KNIGHTSPIKE")), "\n"); - db_put(d, "TE_EXPLOSION", "1"); print("effect TE_EXPLOSION is ", ftos(particleeffectnum("TE_EXPLOSION")), "\n"); - db_put(d, "TE_EXPLOSIONQUAD", "1"); print("effect TE_EXPLOSIONQUAD is ", ftos(particleeffectnum("TE_EXPLOSIONQUAD")), "\n"); - db_put(d, "TE_TAREXPLOSION", "1"); print("effect TE_TAREXPLOSION is ", ftos(particleeffectnum("TE_TAREXPLOSION")), "\n"); - db_put(d, "TE_TELEPORT", "1"); print("effect TE_TELEPORT is ", ftos(particleeffectnum("TE_TELEPORT")), "\n"); - db_put(d, "TE_LAVASPLASH", "1"); print("effect TE_LAVASPLASH is ", ftos(particleeffectnum("TE_LAVASPLASH")), "\n"); - db_put(d, "TE_SMALLFLASH", "1"); print("effect TE_SMALLFLASH is ", ftos(particleeffectnum("TE_SMALLFLASH")), "\n"); - db_put(d, "TE_FLAMEJET", "1"); print("effect TE_FLAMEJET is ", ftos(particleeffectnum("TE_FLAMEJET")), "\n"); - db_put(d, "EF_FLAME", "1"); print("effect EF_FLAME is ", ftos(particleeffectnum("EF_FLAME")), "\n"); - db_put(d, "TE_BLOOD", "1"); print("effect TE_BLOOD is ", ftos(particleeffectnum("TE_BLOOD")), "\n"); - db_put(d, "TE_SPARK", "1"); print("effect TE_SPARK is ", ftos(particleeffectnum("TE_SPARK")), "\n"); - db_put(d, "TE_PLASMABURN", "1"); print("effect TE_PLASMABURN is ", ftos(particleeffectnum("TE_PLASMABURN")), "\n"); - db_put(d, "TE_TEI_G3", "1"); print("effect TE_TEI_G3 is ", ftos(particleeffectnum("TE_TEI_G3")), "\n"); - db_put(d, "TE_TEI_SMOKE", "1"); print("effect TE_TEI_SMOKE is ", ftos(particleeffectnum("TE_TEI_SMOKE")), "\n"); - db_put(d, "TE_TEI_BIGEXPLOSION", "1"); print("effect TE_TEI_BIGEXPLOSION is ", ftos(particleeffectnum("TE_TEI_BIGEXPLOSION")), "\n"); - db_put(d, "TE_TEI_PLASMAHIT", "1"); print("effect TE_TEI_PLASMAHIT is ", ftos(particleeffectnum("TE_TEI_PLASMAHIT")), "\n"); - db_put(d, "EF_STARDUST", "1"); print("effect EF_STARDUST is ", ftos(particleeffectnum("EF_STARDUST")), "\n"); - db_put(d, "TR_ROCKET", "1"); print("effect TR_ROCKET is ", ftos(particleeffectnum("TR_ROCKET")), "\n"); - db_put(d, "TR_GRENADE", "1"); print("effect TR_GRENADE is ", ftos(particleeffectnum("TR_GRENADE")), "\n"); - db_put(d, "TR_BLOOD", "1"); print("effect TR_BLOOD is ", ftos(particleeffectnum("TR_BLOOD")), "\n"); - db_put(d, "TR_WIZSPIKE", "1"); print("effect TR_WIZSPIKE is ", ftos(particleeffectnum("TR_WIZSPIKE")), "\n"); - db_put(d, "TR_SLIGHTBLOOD", "1"); print("effect TR_SLIGHTBLOOD is ", ftos(particleeffectnum("TR_SLIGHTBLOOD")), "\n"); - db_put(d, "TR_KNIGHTSPIKE", "1"); print("effect TR_KNIGHTSPIKE is ", ftos(particleeffectnum("TR_KNIGHTSPIKE")), "\n"); - db_put(d, "TR_VORESPIKE", "1"); print("effect TR_VORESPIKE is ", ftos(particleeffectnum("TR_VORESPIKE")), "\n"); - db_put(d, "TR_NEHAHRASMOKE", "1"); print("effect TR_NEHAHRASMOKE is ", ftos(particleeffectnum("TR_NEHAHRASMOKE")), "\n"); - db_put(d, "TR_NEXUIZPLASMA", "1"); print("effect TR_NEXUIZPLASMA is ", ftos(particleeffectnum("TR_NEXUIZPLASMA")), "\n"); - db_put(d, "TR_GLOWTRAIL", "1"); print("effect TR_GLOWTRAIL is ", ftos(particleeffectnum("TR_GLOWTRAIL")), "\n"); - db_put(d, "SVC_PARTICLE", "1"); print("effect SVC_PARTICLE is ", ftos(particleeffectnum("SVC_PARTICLE")), "\n"); - - fh = fopen("effectinfo.txt", FILE_READ); - while((s = fgets(fh))) - { - tokenize(s); // tokenize_console would hit the loop counter :( - if(argv(0) == "effect") - { - if(db_get(d, argv(1)) != "1") - { - if(particleeffectnum(argv(1)) >= 0) - print("effect ", argv(1), " is ", ftos(particleeffectnum(argv(1))), "\n"); - db_put(d, argv(1), "1"); - } - } - } - print("end of effects list\n"); - - db_close(d); -} - -void make_mapinfo_Think() -{ - if(MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, 0, 1)) - { - print("Done rebuiling mapinfos.\n"); - MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0); - remove(self); - } - else - { - self.think = make_mapinfo_Think; - self.nextthink = time; - } -} - -void GameCommand(string command) -{ - float argc; - entity client, e; - vector v; - float entno, i, n; - string s; - argc = tokenize_console(command); - - if(argv(0) == "help" || argc == 0) - { - print("Usage: sv_cmd COMMAND..., where possible commands are:\n"); - print(" adminmsg clientnumber \"message\"\n"); - print(" teamstatus\n"); - print(" printstats\n"); - print(" make_mapinfo\n"); - print(" gametype dm|ctf|...\n"); - print(" savedb filename\n"); - print(" dumpdb filename\n"); - print(" loaddb filename\n"); - print(" allready\n"); - print(" effectindexdump\n"); - print(" radarmap [--force] [--quit | --loop] [sharpness]\n"); - print(" bbox\n"); - print(" cvar_changes\n"); - print(" cvar_purechanges\n"); - print(" find classname\n"); - GameCommand_Vote("help", world); - GameCommand_Ban("help"); - GameCommand_Generic("help"); - return; - } - - if(GameCommand_Vote(command, world)) - return; - - if(GameCommand_Ban(command)) - return; - - if(GameCommand_Generic(command)) - return; - - if(argv(0) == "printstats") - { - DumpStats(FALSE); - return; - } - - if(argv(0) == "make_mapinfo") - { - e = spawn(); - e.classname = "make_mapinfo"; - e.think = make_mapinfo_Think; - e.nextthink = time; - MapInfo_Enumerate(); - return; - } - - if(argv(0) == "gotomap") if(argc == 2) - { - print(GotoMap(argv(1)), "\n"); - return; - } - - if(argv(0) == "gametype") if(argc == 2) - { - float t, tsave; - s = argv(1); - t = MapInfo_Type_FromString(s); - tsave = MapInfo_CurrentGametype(); - if(t) - { - MapInfo_SwitchGameType(t); - MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0); - if(MapInfo_count > 0) - { - bprint("Game type successfully switched to ", s, "\n"); - } - else - { - bprint("Cannot use this game type: no map for it found\n"); - MapInfo_SwitchGameType(tsave); - MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0); - } - } - else - bprint("Game type switch to ", s, " failed: this type does not exist!\n"); - return; - } - - if(argv(0) == "adminmsg") - if(argc == 3) - { - entno = stof(argv(1)); - - if((entno < 1) | (entno > maxclients)) { - print("Player ", argv(1), " doesn't exist\n"); - return; - } - - client = edict_num(entno); - - if(client.flags & FL_CLIENT) - { - centerprint_atprio(client, CENTERPRIO_ADMIN, strcat("^3", admin_name(), ":\n\n^7", argv(2))); - sprint(client, strcat("\{1}\{13}^3", admin_name(), "^7: ", argv(2), "\n")); - print("Message sent to ", client.netname, "\n"); - } - else - print("Client not found\n"); - - return; - } - - if(argv(0) == "savedb") if(argc == 2) - { - db_save(ServerProgsDB, argv(1)); - print("DB saved.\n"); - return; - } - - if(argv(0) == "dumpdb") if(argc == 2) - { - db_dump(ServerProgsDB, argv(1)); - print("DB dumped.\n"); - return; - } - - if(argv(0) == "loaddb") if(argc == 2) - { - db_close(ServerProgsDB); - ServerProgsDB = db_load(argv(1)); - print("DB loaded.\n"); - return; - } - - if (argv(0) == "nospectators") - { - blockSpectators = 1; - local entity plr; - FOR_EACH_CLIENT(plr) //give every spectator <g_maxplayers_spectator_blocktime> seconds time to become a player - { - if(plr.classname == "spectator" || plr.classname == "observer") - { - plr.spectatortime = time; - sprint(plr, strcat("^7You have to become a player within the next ", ftos(autocvar_g_maxplayers_spectator_blocktime), " seconds, otherwise you will be kicked, because spectators aren't allowed at this time!\n")); - } - } - bprint(strcat("^7All spectators will be automatically kicked when not joining the game after ", ftos(autocvar_g_maxplayers_spectator_blocktime), " seconds!\n")); - return; - } - - if (argv(0) == "lockteams") - { - if(teams_matter) - { - lockteams = 1; - bprint("^1The teams are now locked.\n"); - } - else - bprint("That command can only be used in a team-based gamemode.\n"); - return; - } - - if (argv(0) == "unlockteams") - { - if(teams_matter) - { - lockteams = 0; - bprint("^1The teams are now unlocked.\n"); - } - else - bprint("That command can only be used in a team-based gamemode.\n"); - return; - } - if(argv(0) == "movetoteam") if(argc == 3 || argc == 4) { - // sv_cmd movetoteam player_id team_colour - // sv_cmd movetoteam player_id team_colour type_of_move - - // type of move - // 0 (00) automove centerprint, admin message - // 1 (01) automove centerprint, no admin message - // 2 (10) no centerprint, admin message - // 3 (11) no centerprint, no admin message - - if(!teams_matter) { // death match - print("Currently not playing a team game\n"); - return; - } - - entno = stof(argv(1)); - - // player_id is out of range - if((entno < 1) | (entno > maxclients)) { - print("Player ", argv(1), " doesn't exist\n"); - return; - } - - client = edict_num(entno); - - // player entity is not a client - if not(client.flags & FL_CLIENT) { - print("Player ", argv(1), " doesn't exist\n"); - return; - } - - // find the team to move the player to - float team_colour; - float save; - - save = client.team_forced; - client.team_forced = 0; - - team_colour = ColourToNumber(argv(2)); - - if(team_colour == client.team) { // player already on the team - print("Player ", argv(1), " (", client.netname, ") is already on the ", ColoredTeamName(client.team), "\n"); - // keep the forcing undone - return; - } else if(team_colour == 0) // auto team - team_colour = NumberToTeamNumber(FindSmallestTeam(client, FALSE)); - else - CheckAllowedTeams(client); - - client.team_forced = save; - - switch(team_colour) { - case COLOR_TEAM1: - if(c1 == -1) { - print("Sorry, there isn't a red team\n"); - return; - } - break; - - case COLOR_TEAM2: - if(c2 == -1) { - print("Sorry, there isn't a blue team\n"); - return; - } - break; - - case COLOR_TEAM3: - if(c3 == -1) { - print("Sorry, there isn't a yellow team\n"); - return; - } - break; - - case COLOR_TEAM4: - if(c4 == -1) { - print("Sorry, there isn't a pink team\n"); - return; - } - break; - - default: - print("Sorry, team ", argv(2), " doesn't exist\n"); - return; - } - print("Player ", argv(1), " (", client.netname, ") has been moved to the ", ColoredTeamName(team_colour), "\n"); - - client.team_forced = 0; - MoveToTeam(client, team_colour, 6, stof(argv(3))); - - return; - } - if (argv(0) == "teamstatus") - { - Score_NicePrint(world); - return; - } - if (argv(0) == "allready") - { - ReadyRestart(); - return; - } - if (argv(0) == "effectindexdump") - { - EffectIndexDump(); - return; - } - if (argv(0) == "radarmap") - { - RadarMap(argc); - return; - } - if (argv(0) == "bbox") - { - BBox(); - return; - } - if (argv(0) == "cvar_changes") - { - print(cvar_changes); - return; - } - if (argv(0) == "cvar_purechanges") - { - print(cvar_purechanges); - return; - } - if (argv(0) == "find") if(argc == 2) - { - for(client = world; (client = find(client, classname, argv(1))); ) - print(etos(client), "\n"); - return; - } - if (argv(0) == "records") - { - for (i = 0; i < 10; ++i) - print(records_reply[i]); - return; - } - if (argv(0) == "ladder") - { - print(ladder_reply); - return; - } - if (argv(0) == "rankings") - { - strunzone(rankings_reply); - rankings_reply = strzone(getrankings()); - print(rankings_reply); - return; - } - - if(argv(0) == "cointoss") - { - bprint("^3Throwing coin... Result: "); - if (random() > 0.5) - bprint("^1heads ^3!\n"); - else - bprint("^1tails ^3!\n"); - return; - } - - if(argv(0) == "__FORCE_READY_RESTART") - { - reset_map(FALSE); - return; - } - - if(argv(0) == "debug_shotorg") - { - debug_shotorg = stov(argv(1)); - debug_shotorg_y = -debug_shotorg_y; - return; - } - - if(argv(0) == "gettaginfo") if(argc >= 4) - { - e = spawn(); - if(argv(1) == "w") - setmodel(e, (nextent(world)).weaponentity.model); - else - { - precache_model(argv(1)); - setmodel(e, argv(1)); - } - e.frame = stof(argv(2)); - if(substring(argv(3), 0, 1) == "#") - i = stof(substring(argv(3), 1, -1)); - else - i = gettagindex(e, argv(3)); - if(i) - { - v = gettaginfo(e, i); - print("model ", e.model, " frame ", ftos(e.frame), " tag ", gettaginfo_name); - print(" index ", ftos(i), " parent ", ftos(gettaginfo_parent), "\n"); - print(" vector = ", ftos(v_x), " ", ftos(v_y), " ", ftos(v_z), "\n"); - print(" offset = ", ftos(gettaginfo_offset_x), " ", ftos(gettaginfo_offset_y), " ", ftos(gettaginfo_offset_z), "\n"); - print(" forward = ", ftos(gettaginfo_forward_x), " ", ftos(gettaginfo_forward_y), " ", ftos(gettaginfo_forward_z), "\n"); - print(" right = ", ftos(gettaginfo_right_x), " ", ftos(gettaginfo_right_y), " ", ftos(gettaginfo_right_z), "\n"); - print(" up = ", ftos(gettaginfo_up_x), " ", ftos(gettaginfo_up_y), " ", ftos(gettaginfo_up_z), "\n"); - if(argc >= 6) - { - v_y = -v_y; - localcmd(strcat(argv(4), vtos(v), argv(5), "\n")); - } - } - else - print("bone not found\n"); - remove(e); - return; - } - - if(argv(0) == "time") - { - print("time = ", ftos(time), "\n"); - print("frame start = ", ftos(gettime(GETTIME_FRAMESTART)), "\n"); - print("realtime = ", ftos(gettime(GETTIME_REALTIME)), "\n"); - print("hires = ", ftos(gettime(GETTIME_HIRES)), "\n"); - print("uptime = ", ftos(gettime(GETTIME_UPTIME)), "\n"); - print("localtime = ", strftime(TRUE, "%a %b %e %H:%M:%S %Z %Y"), "\n"); - print("gmtime = ", strftime(FALSE, "%a %b %e %H:%M:%S %Z %Y"), "\n"); - return; - } - - if(argv(0) == "tracebug") - { - print("TEST CASE. If this returns the runaway loop counter error, possibly everything is oaky.\n"); - for(;;) - { - vector org, delta, start, end, p, q, q0, pos; - float safe, unsafe, dq, dqf; - - org = world.mins; - delta = world.maxs - world.mins; - - start_x = org_x + random() * delta_x; - start_y = org_y + random() * delta_y; - start_z = org_z + random() * delta_z; - - end_x = org_x + random() * delta_x; - end_y = org_y + random() * delta_y; - end_z = org_z + random() * delta_z; - - start = stov(vtos(start)); - end = stov(vtos(end)); - - tracebox(start, PL_MIN, PL_MAX, end, MOVE_NOMONSTERS, world); - if(!trace_startsolid) - { - p = trace_endpos; - tracebox(p, PL_MIN, PL_MAX, p, MOVE_NOMONSTERS, world); - if(trace_startsolid || trace_fraction == 1) - { - rint(42); // do an engine breakpoint on VM_rint so you can get the trace that errnoeously returns startsolid - tracebox(start, PL_MIN, PL_MAX, end, MOVE_NOMONSTERS, world); - tracebox(p, PL_MIN, PL_MAX, q, MOVE_NOMONSTERS, world); - - if(trace_startsolid) - { - // how much do we need to back off? - safe = 1; - unsafe = 0; - for(;;) - { - pos = p * (1 - (safe + unsafe) * 0.5) + start * ((safe + unsafe) * 0.5); - tracebox(pos, PL_MIN, PL_MAX, pos, MOVE_NOMONSTERS, world); - if(trace_startsolid) - { - if((safe + unsafe) * 0.5 == unsafe) - break; - unsafe = (safe + unsafe) * 0.5; - } - else - { - if((safe + unsafe) * 0.5 == safe) - break; - safe = (safe + unsafe) * 0.5; - } - } - - print("safe distance to back off: ", ftos(safe * vlen(p - start)), "qu\n"); - print("unsafe distance to back off: ", ftos(unsafe * vlen(p - start)), "qu\n"); - - tracebox(p, PL_MIN + '0.1 0.1 0.1', PL_MAX - '0.1 0.1 0.1', p, MOVE_NOMONSTERS, world); - if(trace_startsolid) - print("trace_endpos much in solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p), "\n"); - else - print("trace_endpos just in solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p), "\n"); - break; - } - - q0 = p; - dq = 0; - dqf = 1; - for(;;) - { - q = p + normalize(end - p) * (dq + dqf); - if(q == q0) - break; - tracebox(p, PL_MIN, PL_MAX, q, MOVE_NOMONSTERS, world); - if(trace_startsolid) - error("THIS ONE cannot happen"); - if(trace_fraction > 0) - dq += dqf * trace_fraction; - dqf *= 0.5; - q0 = q; - } - if(dq > 0) - { - print("trace_endpos still before solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p), "\n"); - print("could go ", ftos(dq), " units further to ", vtos(q), "\n"); - break; - } - } - } - } - } - - if(argv(0) == "tracebug2") - { - e = nextent(world); - float f; - vector vv, dv; - tracebox(e.origin + '0 0 32', e.mins, e.maxs, e.origin + '0 0 -1024', MOVE_NORMAL, e); - vv = trace_endpos; - if(trace_fraction == 1) - { - print("not above ground, aborting\n"); - return; - } - f = 0; - for(i = 0; i < 100000; ++i) - { - dv = randomvec(); - if(dv_z > 0) - dv = -1 * dv; - tracebox(vv, e.mins, e.maxs, vv + dv, MOVE_NORMAL, e); - if(trace_startsolid) - print("bug 1\n"); - if(trace_fraction == 1) - if(dv_z < f) - { - print("bug 2: ", ftos(dv_x), " ", ftos(dv_y), " ", ftos(dv_z)); - print(" (", ftos(asin(dv_z / vlen(dv)) * 180 / M_PI), " degrees)\n"); - f = dv_z; - } - } - print("highest possible dist: ", ftos(f), "\n"); - return; - } - - if(argv(0) == "tracewalk") - { - e = nextent(world); - if(tracewalk(e, stov(argv(1)), e.mins, e.maxs, stov(argv(2)), MOVE_NORMAL)) - print("can walk\n"); - else - print("cannot walk\n"); - return; - } - - if(argv(0) == "onslaught_updatelinks") - { - onslaught_updatelinks(); - print("ONS links updated\n"); - return; - } - - if(argv(0) == "bot_cmd") - { - local entity bot; - - if(argv(1) == "help") - { - if(argc==2) - { - bot_list_commands(); - print("\nsv_cmd bot_cmd reset #Clear the cmd queues of all bots\n"); - print("sv_cmd bot_cmd load <file> #Load script file\n"); - print("\nUse sv_cmd bot_cmd help <command> for more\n\n"); - return; - } - - bot_cmdhelp(argv(2)); - return; - } - - // Clear all bot queues - if(argv(1) == "reset") - { - bot_resetqueues(); - return; - } - - // Load cmds from file - if(argv(1) == "load" && argc == 3) - { - float fh; - fh = fopen(argv(2), FILE_READ); - if(fh < 0) - { - print("cannot open the file\n"); - return; - } - - i = 0; - while((s = fgets(fh))) - { - argc = tokenize_console(s); - - if(argc >= 3 && argv(0) == "sv_cmd" && argv(1) == "bot_cmd") - { - // let's start at token 2 so we can skip sv_cmd bot_cmd - bot = find_bot_by_number(stof(argv(2))); - if(bot == world) - bot = find_bot_by_name(argv(2)); - if(bot) - bot_queuecommand(bot, strcat(argv(3), " ", argv(4))); - } - else - localcmd(strcat(s, "\n")); - - ++i; - } - - print(ftos(i), " commands read\n"); - - fclose(fh); - - return; - } - - if(argc < 3) - { - print("Usage: sv_cmd bot_cmd <bot name or number> <command> [argument]\n"); - print("Examples: bot_cmd <id> cc \"say something\"\n"); - print(" bot_cmd <id> presskey jump\n"); - print(" .. or sv_cmd bot_cmd help <command> for more\n"); - return; - } - - bot = find_bot_by_number(stof(argv(1))); - if(bot == world) - bot = find_bot_by_name(argv(1)); - - if(bot) - bot_queuecommand(bot, strcat(argv(2), " ", argv(3))); - else - print(strcat("Error: Unable to find a bot with the name or number '",argv(1),"'\n")); - - return; - } - - if(argv(0) == "playerdemo") - { - if(argv(1) == "read") - { - entno = stof(argv(2)); - if((entno < 1) | (entno > maxclients)) { - print("Player ", argv(2), " doesn't exist\n"); - return; - } - client = edict_num(entno); - if(clienttype(client) != CLIENTTYPE_BOT) { - print("Player ", client.netname, " is not a bot\n"); - return; - } - self = client; - playerdemo_open_read(argv(3)); - return; - } - else if(argv(1) == "write") - { - entno = stof(argv(2)); - if((entno < 1) | (entno > maxclients)) { - print("Player ", argv(2), " doesn't exist\n"); - return; - } - client = edict_num(entno); - self = client; - playerdemo_open_write(argv(3)); - return; - } - else if(argv(1) == "auto_read_and_write") - { - s = argv(2); - n = stof(argv(3)); - cvar_set("bot_number", ftos(n)); - localcmd("wait; wait; wait\n"); - for(i = 0; i < n; ++i) - localcmd("sv_cmd playerdemo read ", ftos(i+2), " ", s, ftos(i+1), "\n"); - localcmd("sv_cmd playerdemo write 1 ", ftos(n+1), "\n"); - return; - } - else if(argv(1) == "auto_read") - { - s = argv(2); - n = stof(argv(3)); - cvar_set("bot_number", ftos(n)); - localcmd("wait; wait; wait\n"); - for(i = 0; i < n; ++i) - localcmd("sv_cmd playerdemo read ", ftos(i+2), " ", s, ftos(i+1), "\n"); - return; - } - } - - if(argv(0) == "anticheat") - { - entno = stof(argv(1)); - if((entno < 1) | (entno > maxclients)) { - print("Player ", argv(1), " doesn't exist\n"); - return; - } - client = edict_num(entno); - if(clienttype(client) != CLIENTTYPE_REAL && clienttype(client) != CLIENTTYPE_BOT) { - print("Player ", client.netname, " is not active\n"); - return; - } - self = client; - anticheat_report(); - return; - } - - if(argv(0) == "defer_clear") - if(argc == 2) - { - entno = stof(argv(1)); - - // player_id is out of range - if((entno < 1) | (entno > maxclients)) { - print("Player ", argv(1), " doesn't exist\n"); - return; - } - - client = edict_num(entno); - - if not(client.flags & FL_CLIENT) { - print("Player ", argv(1), " doesn't exist\n"); - return; - } - - if(clienttype(client) == CLIENTTYPE_BOT) { - print("Player ", argv(1), " (", client.netname, ") is a bot\n"); - return; - } - - stuffcmd(client, "defer clear\n"); - print("defer clear stuffed to ", argv(1), " (", client.netname, ")\n"); - return; - } - - if(argv(0) == "defer_clear_all") - { - FOR_EACH_CLIENTSLOT(client) - GameCommand(strcat("defer_clear ", ftos(num_for_edict(client)))); - - return; - } - if(argv(0) == "delrec") - { - if(argv(2) != "") - race_deleteTime(argv(2), stof(argv(1))); - else - race_deleteTime(GetMapname(), stof(argv(1))); - - return; - } - - if(argv(0) == "showtraceline") - { - vector src, dst; - src = stov(argv(1)); - dst = stov(argv(2)); - traceline(src, dst, MOVE_NORMAL, world); - trailparticles(world, particleeffectnum("TR_NEXUIZPLASMA"), src, trace_endpos); - trailparticles(world, particleeffectnum("TR_CRYLINKPLASMA"), trace_endpos, dst); - return; - } - - print("Invalid command. For a list of supported commands, try sv_cmd help.\n"); -} - diff --git a/qcsrc/server/ipban.qc b/qcsrc/server/ipban.qc index 66e5a97e5e..b40a1e3a28 100644 --- a/qcsrc/server/ipban.qc +++ b/qcsrc/server/ipban.qc @@ -317,17 +317,26 @@ void Ban_LoadBans() void Ban_View() { - float i; + float i, n; string msg; + + print("^2Listing all existing active bans:\n"); + for(i = 0; i < ban_count; ++i) { if(time > ban_expire[i]) continue; + + ++n; // total number of existing bans + msg = strcat("#", ftos(i), ": "); msg = strcat(msg, ban_ip[i], " is still banned for "); msg = strcat(msg, ftos(ban_expire[i] - time), " seconds"); - print(msg, "\n"); + + print(" ", msg, "\n"); } + + print("^2Done listing all active (", ftos(n), ") bans.\n"); } float Ban_GetClientIP(entity client) @@ -574,79 +583,3 @@ void Ban_KickBanClient(entity client, float bantime, float masksize, string reas dropclient(client); */ } - -float GameCommand_Ban(string command) -{ - float argc; - float bantime; - entity client; - float entno; - float masksize; - string reason; - float reasonarg; - - argc = tokenize_console(command); - if(argv(0) == "help") - { - print(" kickban # n m p reason - kickban player n for m seconds, using mask size p (1 to 4)\n"); - print(" ban ip m reason - ban an IP or range (incomplete IP, like 1.2.3) for m seconds\n"); - print(" bans - list all existing bans\n"); - print(" unban n - delete the entry #n from the bans list\n"); - return TRUE; - } - if(argv(0) == "kickban") - { -#define INITARG(c) reasonarg = c -#define GETARG(v,d) if((argc > reasonarg) && ((v = stof(argv(reasonarg))) != 0)) ++reasonarg; else v = d -#define RESTARG(v) if(argc > reasonarg) v = substring(command, argv_start_index(reasonarg), strlen(command) - argv_start_index(reasonarg)); else v = "" - if(argc >= 3) - { - entno = stof(argv(2)); - if(entno > maxclients || entno < 1) - return TRUE; - client = edict_num(entno); - - INITARG(3); - GETARG(bantime, autocvar_g_ban_default_bantime); - GETARG(masksize, autocvar_g_ban_default_masksize); - RESTARG(reason); - - Ban_KickBanClient(client, bantime, masksize, reason); - return TRUE; - } - } - else if(argv(0) == "ban") - { - if(argc >= 2) - { - string ip; - ip = argv(1); - - INITARG(2); - GETARG(bantime, autocvar_g_ban_default_bantime); - RESTARG(reason); - - Ban_Insert(ip, bantime, reason, 1); - return TRUE; - } -#undef INITARG -#undef GETARG -#undef RESTARG - } - else if(argv(0) == "bans") - { - Ban_View(); - return TRUE; - } - else if(argv(0) == "unban") - { - if(argc >= 2) - { - float who; - who = stof(argv(1)); - Ban_Delete(who); - return TRUE; - } - } - return FALSE; -} diff --git a/qcsrc/server/ipban.qh b/qcsrc/server/ipban.qh index 961ca05a80..15939464e0 100644 --- a/qcsrc/server/ipban.qh +++ b/qcsrc/server/ipban.qh @@ -1,6 +1,6 @@ void Ban_SaveBans(); void Ban_LoadBans(); float Ban_MaybeEnforceBan(entity client); -float GameCommand_Ban(string command); +float BanCommand(string command); void OnlineBanList_URI_Get_Callback(float id, float status, string data); diff --git a/qcsrc/server/item_key.qc b/qcsrc/server/item_key.qc new file mode 100644 index 0000000000..e39f281345 --- /dev/null +++ b/qcsrc/server/item_key.qc @@ -0,0 +1,423 @@ +/* +TODO: +- add an unlock sound (here to trigger_keylock and to func_door) +- display available keys on the HUD +- make more tests +- think about adding NOT_EASY/NOT_NORMAL/NOT_HARD for Q1 compatibility +- should keys have a trigger? +*/ + +float item_keys_usekey(entity l, entity p) { + float valid = l.itemkeys & p.itemkeys; + + if not(valid) { + // other has none of the needed keys + return FALSE; + } else if (l.itemkeys == valid) { + // ALL needed keys were given + l.itemkeys = 0; + return TRUE; + } else { + // only some of the needed keys were given + l.itemkeys &~= valid; + return TRUE; + } +} + +string item_keys_keylist(float keylist) { + float base, l; + string n; + + // no keys + if not(keylist) + return ""; + + // one key + if ((keylist & (keylist-1)) != 0) + return strcat("the ", item_keys_names[lowestbit(keylist)]); + + while (keylist) { + l = lowestbit(keylist); + if (n) + n = strcat(n, ", the ", item_keys_names[base + l]); + else + n = strcat("the ", item_keys_names[base + l]); + + keylist = bitshift(keylist, -(l + 1)); + base+= l + 1; + } + + return n; +} + + +/* +================================ +item_key +================================ +*/ + +/** + * Key touch handler. + */ +void item_key_touch(void) { + if (other.classname != "player") + return; + + // player already picked up this key + if (other.itemkeys & self.itemkeys) + return; + + other.itemkeys |= self.itemkeys; + play2(other, self.noise); + + centerprint(other, self.message); +}; + +/** + * Spawn a key with given model, key code and color. + */ +void spawn_item_key() { + precache_model(self.model); + + if (self.spawnflags & 1) // FLOATING + self.noalign = 1; + + if (self.noalign) + self.movetype = MOVETYPE_NONE; + else + self.movetype = MOVETYPE_TOSS; + + precache_sound(self.noise); + + self.mdl = self.model; + self.effects = EF_LOWPRECISION; + setmodel(self, self.model); + //setsize(self, '-16 -16 -24', '16 16 32'); + setorigin(self, self.origin + '0 0 32'); + setsize(self, '-16 -16 -56', '16 16 0'); + self.modelflags |= MF_ROTATE; + self.solid = SOLID_TRIGGER; + + if (!self.noalign) + { + // first nudge it off the floor a little bit to avoid math errors + setorigin(self, self.origin + '0 0 1'); + // note droptofloor returns FALSE if stuck/or would fall too far + droptofloor(); + } + + self.touch = item_key_touch; +}; + + +/*QUAKED item_key (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING +A key entity. +The itemkeys should contain one of the following key IDs: +1 - GOLD key - +2 - SILVER key +4 - BRONZE key +8 - RED keycard +16 - BLUE keycard +32 - GREEN keycard +Custom keys: +... - last key is 1<<23 +Keys with bigger Id than 32 don't have a default netname and model, if you use one of them, you MUST provide those. +-----------KEYS------------ +colormod: color of the key (default: '.9 .9 .9'). +itemkeys: a key Id. +message: message to print when player picks up this key. +model: custom key model to use. +netname: the display name of the key. +noise: custom sound to play when player picks up the key. +-------- SPAWNFLAGS -------- +FLOATING: the item will float in air, instead of aligning to the floor by falling +---------NOTES---------- +This is the only correct way to put keys on the map! + +itemkeys MUST always have exactly one bit set. +*/ +void spawnfunc_item_key() { + local string _model, _netname; + local vector _colormod; + + // reject this entity if more than one key was set! + if (self.itemkeys>0 && (self.itemkeys & (self.itemkeys-1)) != 0) { + objerror("item_key.itemkeys must contain only 1 bit set specifying the key it represents!"); + remove(self); + return; + } + + // find default netname and colormod + switch(self.itemkeys) { + case 1: + _netname = "GOLD key"; + _colormod = '1 .9 0'; + break; + + case 2: + _netname = "SILVER key"; + _colormod = '.9 .9 .9'; + break; + + case 4: + _netname = "BRONZE key"; + _colormod = '.6 .25 0'; + break; + + case 8: + _netname = "RED keycard"; + _colormod = '.9 0 0'; + break; + + case 16: + _netname = "BLUE keycard"; + _colormod = '0 0 .9'; + break; + + case 32: + _netname = "GREEN keycard"; + _colormod = '0 .9 0'; + break; + + default: + if (!self.netname) { + objerror("item_key doesn't have a default name for this key and a custom one was not specified!"); + remove(self); + return; + } else if (!self.colormod) { + _colormod = '1 1 1'; + } + break; + + } + + // find default model + if (self.itemkeys <= ITEM_KEY_BIT(2)) { + _model = "models/keys/key.md3"; + } else if (self.itemkeys >= ITEM_KEY_BIT(3) && self.itemkeys <= ITEM_KEY_BIT(5)) { + _model = "models/keys/key.md3"; // FIXME: replace it by a keycard model! + } else if (!self.model) { + objerror("item_key doesn't have a default model for this key and a custom one was not specified!"); + remove(self); + return; + } + + // set defailt netname + if (!self.netname) + self.netname = _netname; + + // set default colormod + if (!self.colormod) + self.colormod = _colormod; + + // set default model + if (!self.model) + self.model = _model; + + // set default pickup message + if (!self.message) + self.message = strzone(strcat("You've picked up the ", self.netname, "!")); + + if (!self.noise) + self.noise = "misc/itempickup.wav"; + + // save the name for later + item_keys_names[lowestbit(self.itemkeys)] = self.netname; + + // put the key on the map + spawn_item_key(); +} + +/*QUAKED item_key1 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING +SILVER key. +-----------KEYS------------ +colormod: color of the key (default: '.9 .9 .9'). +message: message to print when player picks up this key. +model: custom model to use. +noise: custom sound to play when player picks up the key. +-------- SPAWNFLAGS -------- +FLOATING: the item will float in air, instead of aligning to the floor by falling +---------NOTES---------- +Don't use this entity on new maps! Use item_key instead. +*/ +void spawnfunc_item_key1(void) { + self.classname = "item_key"; + self.itemkeys = ITEM_KEY_BIT(1); + spawnfunc_item_key(); +}; + +/*QUAKED item_key2 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING +GOLD key. +-----------KEYS------------ +colormod: color of the key (default: '1 .9 0'). +message: message to print when player picks up this key. +model: custom model to use. +noise: custom sound to play when player picks up the key. +-------- SPAWNFLAGS -------- +FLOATING: the item will float in air, instead of aligning to the floor by falling +---------NOTES---------- +Don't use this entity on new maps! Use item_key instead. +*/ +void spawnfunc_item_key2(void) { + self.classname = "item_key"; + self.itemkeys = ITEM_KEY_BIT(0); + spawnfunc_item_key(); +}; + + +/* +================================ +trigger_keylock +================================ +*/ + +/** + * trigger givent targets + */ +void trigger_keylock_trigger(string s) { + local entity t, stemp, otemp, atemp; + + stemp = self; + otemp = other; + atemp = activator; + + + for(t = world; (t = find(t, targetname, s)); ) + if (t.use) { + self = t; + other = stemp; + activator = atemp; + self.use(); + } + + self = stemp; + other = otemp; + activator = atemp; +}; + +/** + * kill killtarget of trigger keylock. + */ +void trigger_keylock_kill(string s) { + local entity t; + for(t = world; (t = find(t, targetname, s)); ) + remove(t); +}; + +void trigger_keylock_touch(void) { + local float key_used, started_delay; + + key_used = FALSE; + started_delay = FALSE; + + // only player may trigger the lock + if (other.classname != "player") + return; + + + // check silver key + if (self.itemkeys) + key_used = item_keys_usekey(self, other); + + activator = other; + + if (self.itemkeys) { + // at least one of the keys is missing + if (key_used) { + // one or more keys were given, but others are still missing! + play2(other, self.noise1); + centerprint(other, strcat("You also need ", item_keys_keylist(self.itemkeys), "!")); + other.key_door_messagetime = time + 2; + } else if (other.key_door_messagetime <= time) { + // no keys were given + play2(other, self.noise2); + centerprint(other, strcat("You need ", item_keys_keylist(self.itemkeys), "!")); + other.key_door_messagetime = time + 2; + } + + // trigger target2 + if (self.delay <= time || started_delay == TRUE) + if (self.target2) { + trigger_keylock_trigger(self.target2); + started_delay = TRUE; + self.delay = time + self.wait; + } + } else { + // all keys were given! + play2(other, self.noise); + centerprint(other, self.message); + + if (self.target) + trigger_keylock_trigger(self.target); + + if (self.killtarget) + trigger_keylock_kill(self.killtarget); + + remove(self); + } + +}; + +/*QUAKED trigger_keylock (.0 .5 .8) ? +Keylock trigger. Must target other entities. +This trigger will trigger target entities when all required keys are provided. +-------- KEYS -------- +itemkeys: A bit field with key IDs that are needed to open this lock. +sounds: 1 to play misc/secret.wav, 2 to play misc/talk.wav, 3 to play misc/trigger1.wav (3 is default) +target: trigger all entities with this targetname when triggered and all keys have been given to it, then remove this trigger +target2: trigger all entities with this targetname when triggered without giving it all the required keys. +killtarget: remove all entities with this targetname when triggered with all the needed keys. +message: print this message to the player who activated the trigger when all needed keys have been given. +message2: print this message to the player who activated the trigger when not all of the needed keys have been given. +noise: sound to play when lock gets unlocked (default: see sounds) +noise1: sound to play when only some of the needed key were used but not all (default: misc/decreasevalue.wav) +noise2: sound to play when a key is missing (default: misc/talk.wav) +wait: prevent triggering again for this amount of time (default: 5) - applies to target2, target3, target4. +---------NOTES---------- +If spawned without any key specified in itemkeys, this trigger will display an error and remove itself. +message2 and noise2 will be resent to the player every 2 seconds while he is in the trigger zone. +*/ +void spawnfunc_trigger_keylock(void) { + if (!self.itemkeys) { + remove(self); + return; + } + + // set unlocked message + if (!self.message) + self.message = "Unlocked!"; + + // set default unlock noise + if (!self.noise) { + if (self.sounds == 1) + self.noise = "misc/secret.wav"; + else if (self.sounds == 2) + self.noise = "misc/talk.wav"; + else //if (self.sounds == 3) { + self.noise = "misc/trigger1.wav"; + } + + // set default use key sound + if (!self.noise1) + self.noise1 = "misc/decreasevalue.wav"; + + // set closed sourd + if (!self.noise2) + self.noise2 = "misc/talk.wav"; + + // delay between triggering message2 and trigger2 + if (!self.wait) + self.wait = 5; + + // precache sounds + precache_sound(self.noise); + precache_sound(self.noise1); + precache_sound(self.noise2); + + EXACTTRIGGER_INIT; + + self.touch = trigger_keylock_touch; +}; + + diff --git a/qcsrc/server/item_key.qh b/qcsrc/server/item_key.qh new file mode 100644 index 0000000000..24ef1e935c --- /dev/null +++ b/qcsrc/server/item_key.qh @@ -0,0 +1,23 @@ +/** + * Returns the bit ID of a key + */ +#define ITEM_KEY_BIT(n) ( bitshift(1, n) ) + +#define ITEM_KEY_MAX 24 + +/** + * list of key names. + */ +string item_keys_names[ITEM_KEY_MAX]; + +/** + * Use keys from p on l. + * Returns TRUE if any new keys were given, FALSE otherwise. + */ +float item_keys_usekey(entity l, entity p); + +/** + * Returns a string with a comma separated list of key names, as specified in keylist. + */ +string item_keys_keylist(float keylist); + diff --git a/qcsrc/server/miscfunctions.qc b/qcsrc/server/miscfunctions.qc index 113e9f427d..4babf32b22 100644 --- a/qcsrc/server/miscfunctions.qc +++ b/qcsrc/server/miscfunctions.qc @@ -8,6 +8,21 @@ void crosshair_trace(entity pl) { traceline_antilag(pl, pl.cursor_trace_start, pl.cursor_trace_start + normalize(pl.cursor_trace_endpos - pl.cursor_trace_start) * MAX_SHOT_DISTANCE, MOVE_NORMAL, pl, ANTILAG_LATENCY(pl)); } +void crosshair_trace_plusvisibletriggers(entity pl) +{ + entity first; + entity e; + first = findchainfloat(solid, SOLID_TRIGGER); + + for (e = first; e; e = e.chain) + if (e.model != "") + e.solid = SOLID_BSP; + + crosshair_trace(pl); + + for (e = first; e; e = e.chain) + e.solid = SOLID_TRIGGER; +} void WarpZone_traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag); void WarpZone_crosshair_trace(entity pl) { @@ -79,48 +94,6 @@ string strcat1(string s) = #115; // FRIK_FILE float logfile_open; float logfile; -string GetAdvancedDeathReports(entity enPlayer) // Extra fragmessage information -{ - local float nPlayerHealth = rint(enPlayer.health); - local float nPlayerArmor = rint(enPlayer.armorvalue); - local float nPlayerHandicap = enPlayer.cvar_cl_handicap; - local float nPlayerPing = rint(enPlayer.ping); - local string strPlayerPingColor; - local string strMessage; - if(nPlayerPing >= 150) - strPlayerPingColor = "^1"; - else - strPlayerPingColor = "^2"; - - if((autocvar_sv_fragmessage_information_stats) && (enPlayer.health >= 1)) - strMessage = strcat(strMessage, "\n^7(Health ^1", ftos(nPlayerHealth), "^7 / Armor ^2", ftos(nPlayerArmor), "^7)"); - - if(autocvar_sv_fragmessage_information_ping) { - if(clienttype(enPlayer) == CLIENTTYPE_BOT) // Bots have no ping - strMessage = strcat(strMessage, " ^7(^2Bot"); - else - strMessage = strcat(strMessage, " ^7(Ping ", strPlayerPingColor, ftos(nPlayerPing), "ms"); - if(autocvar_sv_fragmessage_information_handicap) - if(autocvar_sv_fragmessage_information_handicap == 2) - if(nPlayerHandicap <= 1) - strMessage = strcat(strMessage, "^7 / Handicap ^2Off^7)"); - else - strMessage = strcat(strMessage, "^7 / Handicap ^2", ftos(nPlayerHandicap), "^7)"); - else if not(nPlayerHandicap <= 1) - strMessage = strcat(strMessage, "^7 / Handicap ^2", ftos(nPlayerHandicap), "^7)"); - else - strMessage = strcat(strMessage, "^7)"); - } else if(autocvar_sv_fragmessage_information_handicap) { - if(autocvar_sv_fragmessage_information_handicap == 2) - if(nPlayerHandicap <= 1) - strMessage = strcat(strMessage, "\n^7(Handicap ^2Off^7)"); - else - strMessage = strcat(strMessage, "\n^7(Handicap ^2", ftos(nPlayerHandicap), "^7)"); - else if(nPlayerHandicap > 1) - strMessage = strcat(strMessage, "\n^7(Handicap ^2", ftos(nPlayerHandicap), "^7)"); - } - return strMessage; -} void bcenterprint(string s) { // TODO replace by MSG_ALL (would show it to spectators too, though)? @@ -178,25 +151,9 @@ void GameLogClose() } } -vector PL_VIEW_OFS; -vector PL_MIN; -vector PL_MAX; -vector PL_HEAD; -vector PL_CROUCH_VIEW_OFS; -vector PL_CROUCH_MIN; -vector PL_CROUCH_MAX; - float spawnpoint_nag; void relocate_spawnpoint() { - PL_VIEW_OFS = stov(autocvar_sv_player_viewoffset); - PL_MIN = stov(autocvar_sv_player_mins); - PL_MAX = stov(autocvar_sv_player_maxs); - PL_HEAD = stov(autocvar_sv_player_headsize); - PL_CROUCH_VIEW_OFS = stov(autocvar_sv_player_crouch_viewoffset); - PL_CROUCH_MIN = stov(autocvar_sv_player_crouch_mins); - PL_CROUCH_MAX = stov(autocvar_sv_player_crouch_maxs); - // nudge off the floor setorigin(self, self.origin + '0 0 1'); @@ -236,6 +193,7 @@ void relocate_spawnpoint() if (have_team_spawns != 0) if (self.team) have_team_spawns = 1; + have_team_spawns_forteam[self.team] = 1; if (autocvar_r_showbboxes) { @@ -361,13 +319,13 @@ void spawnfunc_target_location() self.classname = "target_location"; // location name in netname // eventually support: count, teamgame selectors, line of sight? -}; +} void spawnfunc_info_location() { self.classname = "target_location"; self.message = self.netname; -}; +} string NearestLocation(vector p) { @@ -459,11 +417,6 @@ string formatmessage(string msg) replacement = cursor_ent.netname; if (!replacement || !cursor_ent) replacement = "nothing"; - } else if (escape == "p") { - if (self.last_selected_player) - replacement = self.last_selected_player.netname; - else - replacement = "(nobody)"; } else if (escape == "s") replacement = ftos(vlen(self.velocity - self.velocity_z * '0 0 1')); else if (escape == "S") @@ -582,11 +535,10 @@ void GetCvars(float f) get_cvars_s = s; MUTATOR_CALLHOOK(GetCvars); GetCvars_handleFloat(s, f, autoswitch, "cl_autoswitch"); - GetCvars_handleFloat(s, f, cvar_cl_playerdetailreduction, "cl_playerdetailreduction"); - GetCvars_handleFloat(s, f, cvar_scr_centertime, "scr_centertime"); - GetCvars_handleFloat(s, f, cvar_cl_shownames, "cl_shownames"); + GetCvars_handleFloat(s, f, cvar_cl_autoscreenshot, "cl_autoscreenshot"); GetCvars_handleString(s, f, cvar_g_xonoticversion, "g_xonoticversion"); GetCvars_handleFloat(s, f, cvar_cl_handicap, "cl_handicap"); + GetCvars_handleFloat(s, f, cvar_cl_clippedspectating, "cl_clippedspectating"); GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriority, "cl_weaponpriority", W_FixWeaponOrder_ForceComplete_AndBuildImpulseList); GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriorities[0], "cl_weaponpriority0", W_FixWeaponOrder_AllowIncomplete); GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriorities[1], "cl_weaponpriority1", W_FixWeaponOrder_AllowIncomplete); @@ -603,7 +555,6 @@ void GetCvars(float f) GetCvars_handleFloat(s, f, cvar_cl_noantilag, "cl_noantilag"); GetCvars_handleFloat(s, f, cvar_cl_voice_directional, "cl_voice_directional"); GetCvars_handleFloat(s, f, cvar_cl_voice_directional_taunt_attenuation, "cl_voice_directional_taunt_attenuation"); - GetCvars_handleFloat(s, f, cvar_cl_hitsound, "cl_hitsound"); GetCvars_handleFloat(s, f, cvar_cl_accuracy_data_share, "cl_accuracy_data_share"); GetCvars_handleFloat(s, f, cvar_cl_accuracy_data_receive, "cl_accuracy_data_receive"); @@ -616,25 +567,20 @@ void GetCvars(float f) #endif GetCvars_handleFloatOnce(s, f, cvar_cl_gunalign, "cl_gunalign"); GetCvars_handleFloat(s, f, cvar_cl_allow_uid2name, "cl_allow_uid2name"); + GetCvars_handleFloat(s, f, cvar_cl_allow_uidtracking, "cl_allow_uidtracking"); + GetCvars_handleFloat(s, f, cvar_cl_movement_track_canjump, "cl_movement_track_canjump"); + GetCvars_handleFloat(s, f, cvar_cl_newusekeysupported, "cl_newusekeysupported"); // fixup of switchweapon (needed for LMS or when spectating is disabled, as PutClientInServer comes too early) if (f > 0) { if (s == "cl_weaponpriority") self.switchweapon = w_getbestweapon(self); + if (s == "cl_allow_uidtracking") + PlayerStats_AddPlayer(self); } } -float fexists(string f) -{ - float fh; - fh = fopen(f, FILE_READ); - if (fh < 0) - return FALSE; - fclose(fh); - return TRUE; -} - void backtrace(string msg) { float dev, war; @@ -731,51 +677,11 @@ float NumberToTeamNumber(float number) return -1; } -#define CENTERPRIO_POINT 1 -#define CENTERPRIO_SPAM 2 -#define CENTERPRIO_VOTE 4 -#define CENTERPRIO_NORMAL 5 -#define CENTERPRIO_SHIELDING 7 -#define CENTERPRIO_MAPVOTE 9 -#define CENTERPRIO_IDLEKICK 50 -#define CENTERPRIO_ADMIN 99 -.float centerprint_priority; -.float centerprint_expires; -void centerprint_atprio(entity e, float prio, string s) -{ - if (intermission_running) - if (prio < CENTERPRIO_MAPVOTE) - return; - if (time > e.centerprint_expires) - e.centerprint_priority = 0; - if (prio >= e.centerprint_priority) - { - e.centerprint_priority = prio; - if (timeoutStatus == 2) - e.centerprint_expires = time + (e.cvar_scr_centertime * TIMEOUT_SLOWMO_VALUE); - else - e.centerprint_expires = time + e.cvar_scr_centertime; - centerprint_builtin(e, s); - } -} -void centerprint_expire(entity e, float prio) -{ - if (prio == e.centerprint_priority) - { - e.centerprint_priority = 0; - centerprint_builtin(e, ""); - } -} -void centerprint(entity e, string s) -{ - centerprint_atprio(e, CENTERPRIO_NORMAL, s); -} - // decolorizes and team colors the player name when needed string playername(entity p) { string t; - if (teams_matter && !intermission_running && p.classname == "player") + if (teamplay && !intermission_running && p.classname == "player") { t = Team_ColorCode(p.team); return strcat(t, strdecolorize(p.netname)); @@ -786,13 +692,13 @@ string playername(entity p) vector randompos(vector m1, vector m2) { - local vector v; + vector v; m2 = m2 - m1; v_x = m2_x * random() + m1_x; v_y = m2_y * random() + m1_y; v_z = m2_z * random() + m1_z; return v; -}; +} //#NO AUTOCVARS START @@ -915,8 +821,19 @@ void readplayerstartcvars() g_weaponarena = 0; s = cvar_string("g_weaponarena"); - if (s == "0") + if (s == "0" || s == "") { + if(g_lms || g_ca) + s = "most"; + } + + if (s == "0" || s == "") + { + // no arena + } + else if (s == "off") + { + // forcibly turn off weaponarena } else if (s == "all") { @@ -981,24 +898,8 @@ void readplayerstartcvars() if (g_weaponarena) { start_weapons = g_weaponarena; - for (j = WEP_FIRST; j <= WEP_LAST; ++j) - { - e = get_weaponinfo(j); - if(start_weapons & e.weapons) - { - if(e.items & IT_ROCKETS) - start_ammo_rockets = 999; - if(e.items & IT_SHELLS) - start_ammo_shells = 999; - if(e.items & IT_CELLS) - start_ammo_cells = 999; - if(e.items & IT_NAILS) - start_ammo_nails = 999; - if(e.items & IT_FUEL) - start_ammo_fuel = 999; - } - } - start_items |= IT_UNLIMITED_AMMO; + if(!(g_lms || g_ca)) + start_items |= IT_UNLIMITED_AMMO; } else if (g_minstagib) { @@ -1006,24 +907,46 @@ void readplayerstartcvars() start_armorvalue = 0; start_weapons = WEPBIT_MINSTANEX; weapon_action(WEP_MINSTANEX, WR_PRECACHE); - start_ammo_cells = cvar("g_minstagib_ammo_start"); g_minstagib_invis_alpha = cvar("g_minstagib_invis_alpha"); - start_ammo_fuel = cvar("g_start_ammo_fuel"); if (g_minstagib_invis_alpha <= 0) g_minstagib_invis_alpha = -1; } else { - if (g_lms || g_ca) + for (i = WEP_FIRST; i <= WEP_LAST; ++i) + { + e = get_weaponinfo(i); + if(want_weapon("g_start_weapon_", e, FALSE)) + start_weapons |= e.weapons; + } + } + + if(!cvar("g_use_ammunition")) + start_items |= IT_UNLIMITED_AMMO; + + if(g_minstagib) + { + start_ammo_cells = cvar("g_minstagib_ammo_start"); + start_ammo_fuel = cvar("g_start_ammo_fuel"); + } + else if(start_items & IT_UNLIMITED_WEAPON_AMMO) + { + start_ammo_rockets = 999; + start_ammo_shells = 999; + start_ammo_cells = 999; + start_ammo_nails = 999; + start_ammo_fuel = 999; + } + else + { + if(g_lms || g_ca) { start_ammo_shells = cvar("g_lms_start_ammo_shells"); start_ammo_nails = cvar("g_lms_start_ammo_nails"); start_ammo_rockets = cvar("g_lms_start_ammo_rockets"); start_ammo_cells = cvar("g_lms_start_ammo_cells"); start_ammo_fuel = cvar("g_lms_start_ammo_fuel"); - start_health = cvar("g_lms_start_health"); - start_armorvalue = cvar("g_lms_start_armor"); } else { @@ -1033,13 +956,12 @@ void readplayerstartcvars() start_ammo_cells = cvar("g_start_ammo_cells"); start_ammo_fuel = cvar("g_start_ammo_fuel"); } + } - for (i = WEP_FIRST; i <= WEP_LAST; ++i) - { - e = get_weaponinfo(i); - if(want_weapon("g_start_weapon_", e, FALSE)) - start_weapons |= e.weapons; - } + if (g_lms || g_ca) + { + start_health = cvar("g_lms_start_health"); + start_armorvalue = cvar("g_lms_start_armor"); } if (inWarmupStage) @@ -1080,39 +1002,9 @@ void readplayerstartcvars() warmup_start_ammo_fuel = max(warmup_start_ammo_fuel, cvar("g_balance_fuel_rotstable")); } - if(!cvar("g_use_ammunition")) - { - start_ammo_shells = cvar("g_pickup_shells_max"); - start_ammo_nails = cvar("g_pickup_nails_max"); - start_ammo_rockets = cvar("g_pickup_rockets_max"); - start_ammo_cells = cvar("g_pickup_cells_max"); - start_ammo_fuel = cvar("g_pickup_fuel_max"); - start_items |= IT_UNLIMITED_AMMO; - warmup_start_ammo_shells = cvar("g_pickup_shells_max"); - warmup_start_ammo_nails = cvar("g_pickup_nails_max"); - warmup_start_ammo_rockets = cvar("g_pickup_rockets_max"); - warmup_start_ammo_cells = cvar("g_pickup_cells_max"); - warmup_start_ammo_fuel = cvar("g_pickup_fuel_max"); - //warmup_start_items |= IT_UNLIMITED_AMMO; - } - if (g_jetpack) start_items |= IT_JETPACK; - if (g_weapon_stay == 2) - { - if (!start_ammo_shells) start_ammo_shells = g_pickup_shells; - if (!start_ammo_nails) start_ammo_nails = g_pickup_nails; - if (!start_ammo_cells) start_ammo_cells = g_pickup_cells; - if (!start_ammo_rockets) start_ammo_rockets = g_pickup_rockets; - if (!start_ammo_fuel) start_ammo_fuel = g_pickup_fuel; - if (!warmup_start_ammo_shells) warmup_start_ammo_shells = g_pickup_shells; - if (!warmup_start_ammo_nails) warmup_start_ammo_nails = g_pickup_nails; - if (!warmup_start_ammo_cells) warmup_start_ammo_cells = g_pickup_cells; - if (!warmup_start_ammo_rockets) warmup_start_ammo_rockets = g_pickup_rockets; - if (!warmup_start_ammo_fuel) warmup_start_ammo_fuel = g_pickup_fuel; - } - MUTATOR_CALLHOOK(SetStartItems); for (i = WEP_FIRST; i <= WEP_LAST; ++i) @@ -1168,6 +1060,8 @@ string GetGametype(); // g_world.qc void readlevelcvars(void) { // first load all the mutators + if(cvar("g_invincible_projectiles")) + MUTATOR_ADD(mutator_invincibleprojectiles); if(cvar("g_nix")) MUTATOR_ADD(mutator_nix); if(cvar("g_dodging")) @@ -1176,6 +1070,12 @@ void readlevelcvars(void) MUTATOR_ADD(mutator_rocketflying); if(cvar("g_vampire")) MUTATOR_ADD(mutator_vampire); + if(cvar("g_spawn_near_teammate")) + MUTATOR_ADD(mutator_spawn_near_teammate); + + // is this a mutator? is this a mode? + if(cvar("g_sandbox")) + MUTATOR_ADD(sandbox); if(cvar("sv_allow_fullbright")) serverflags |= SERVERFLAG_ALLOW_FULLBRIGHT; @@ -1205,11 +1105,6 @@ void readlevelcvars(void) #ifdef ALLOW_FORCEMODELS sv_clforceplayermodels = cvar("sv_clforceplayermodels"); #endif - sv_loddistance1 = cvar("sv_loddistance1"); - sv_loddistance2 = cvar("sv_loddistance2"); - - if(sv_loddistance2 <= sv_loddistance1) - sv_loddistance2 = 1073741824; // enough to turn off LOD 2 reliably sv_clones = cvar("sv_clones"); sv_gentle = cvar("sv_gentle"); @@ -1227,7 +1122,6 @@ void readlevelcvars(void) g_bloodloss = cvar("g_bloodloss"); sv_maxidle = cvar("sv_maxidle"); sv_maxidle_spectatorsareidle = cvar("sv_maxidle_spectatorsareidle"); - sv_pogostick = cvar("sv_pogostick"); g_ctf_reverse = cvar("g_ctf_reverse"); sv_autotaunt = cvar("sv_autotaunt"); sv_taunt = cvar("sv_taunt"); @@ -1304,9 +1198,6 @@ void readlevelcvars(void) if(!g_weapon_stay) g_weapon_stay = cvar("g_weapon_stay"); - if (!g_weapon_stay && (cvar("deathmatch") == 2)) - g_weapon_stay = 1; - g_ghost_items = cvar("g_ghost_items"); if(g_ghost_items >= 1) @@ -1326,7 +1217,6 @@ void readlevelcvars(void) // Sound functions string precache_sound (string s) = #19; -void(entity e, float chan, string samp, float vol, float atten) sound_builtin = #8; float precache_sound_index (string s) = #19; #define SND_VOLUME 1 @@ -1341,7 +1231,9 @@ float sound_allowed(float dest, entity e) { if (e.classname == "body") e = e.enemy; - if (e.owner && e.owner != e) + else if (e.realowner && e.realowner != e) + e = e.realowner; + else if (e.owner && e.owner != e) e = e.owner; else break; @@ -1358,12 +1250,24 @@ float sound_allowed(float dest, entity e) return TRUE; } +#ifdef COMPAT_XON010_CHANNELS +void(entity e, float chan, string samp, float vol, float atten) builtin_sound = #8; +void sound(entity e, float chan, string samp, float vol, float atten) +{ + if (!sound_allowed(MSG_BROADCAST, e)) + return; + builtin_sound(e, chan, samp, vol, atten); +} +#else +#undef sound void sound(entity e, float chan, string samp, float vol, float atten) { if (!sound_allowed(MSG_BROADCAST, e)) return; - sound_builtin(e, chan, samp, vol, atten); + sound7(e, chan, samp, vol, atten, 0, 0); } +#endif + void soundtoat(float dest, entity e, vector o, float chan, string samp, float vol, float atten) { float entno, idx; @@ -1384,7 +1288,7 @@ void soundtoat(float dest, entity e, vector o, float chan, string samp, float vo sflags |= SND_VOLUME; if (atten != 64) sflags |= SND_ATTENUATION; - if (entno >= 8192) + if (entno >= 8192 || chan < 0 || chan > 7) sflags |= SND_LARGEENTITY; if (idx >= 256) sflags |= SND_LARGESOUND; @@ -1425,7 +1329,7 @@ void soundto(float dest, entity e, float chan, string samp, float vol, float att } void soundat(entity e, vector o, float chan, string samp, float vol, float atten) { - soundtoat(MSG_BROADCAST, e, o, chan, samp, vol, atten); + soundtoat(((chan & 8) ? MSG_ALL : MSG_BROADCAST), e, o, chan, samp, vol, atten); } void stopsoundto(float dest, entity e, float chan) { @@ -1436,7 +1340,7 @@ void stopsoundto(float dest, entity e, float chan) entno = num_for_edict(e); - if (entno >= 8192) + if (entno >= 8192 || chan < 0 || chan > 7) { float idx, sflags; idx = precache_sound_index("misc/null.wav"); @@ -1474,7 +1378,7 @@ void play2(entity e, string filename) { //stuffcmd(e, strcat("play2 ", filename, "\n")); msg_entity = e; - soundtoat(MSG_ONE, world, '0 0 0', CHAN_AUTO, filename, VOL_BASE, ATTN_NONE); + soundtoat(MSG_ONE, world, '0 0 0', CH_INFO, filename, VOL_BASE, ATTN_NONE); } // use this one if you might be causing spam (e.g. from touch functions that might get called more than once per frame) @@ -1495,7 +1399,7 @@ float spamsound(entity e, float chan, string samp, float vol, float atten) void play2team(float t, string filename) { - local entity head; + entity head; if (autocvar_bot_sound_monopoly) return; @@ -1512,7 +1416,7 @@ void play2all(string samp) if (autocvar_bot_sound_monopoly) return; - sound(world, CHAN_AUTO, samp, VOL_BASE, ATTN_NONE); + sound(world, CH_INFO, samp, VOL_BASE, ATTN_NONE); } void PrecachePlayerSounds(string f); @@ -1526,15 +1430,12 @@ void precache_playermodel(string m) if(substring(m, -9,5) == "_lod2") return; precache_model(m); - if(sv_loddistance1) - { - f = strcat(substring(m, 0, -5), "_lod1", substring(m, -4, -1)); - if(fexists(f)) - precache_model(f); - f = strcat(substring(m, 0, -5), "_lod2", substring(m, -4, -1)); - if(fexists(f)) - precache_model(f); - } + f = strcat(substring(m, 0, -5), "_lod1", substring(m, -4, -1)); + if(fexists(f)) + precache_model(f); + f = strcat(substring(m, 0, -5), "_lod2", substring(m, -4, -1)); + if(fexists(f)) + precache_model(f); globhandle = search_begin(strcat(m, "_*.sounds"), TRUE, FALSE); if (globhandle < 0) @@ -1570,7 +1471,6 @@ void precache() { // gamemode related things precache_model ("models/misc/chatbubble.spr"); - precache_model ("models/misc/teambubble.spr"); if (g_runematch) { precache_model ("models/runematch/curse.mdl"); @@ -1630,8 +1530,6 @@ void precache() precache_sound ("misc/gib_splat02.wav"); precache_sound ("misc/gib_splat03.wav"); precache_sound ("misc/gib_splat04.wav"); - precache_sound ("misc/hit.wav"); - precache_sound ("misc/typehit.wav"); PrecacheGlobalSound((globalsound_fall = "misc/hitground 4")); PrecacheGlobalSound((globalsound_metalfall = "misc/metalhitground 4")); precache_sound ("misc/null.wav"); @@ -1658,6 +1556,7 @@ void precache() precache_model ("models/sprites/10.spr32"); // common weapon precaches + precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound here precache_sound ("weapons/weapon_switch.wav"); precache_sound ("weapons/weaponpickup.wav"); precache_sound ("weapons/unavailable.wav"); @@ -1671,7 +1570,7 @@ void precache() if(autocvar_sv_precacheweapons) { //precache weapon models/sounds - local float wep; + float wep; wep = WEP_FIRST; while (wep <= WEP_LAST) { @@ -1704,6 +1603,29 @@ void precache() #define WRITESPECTATABLE_MSG_ONE(statement) WRITESPECTATABLE_MSG_ONE_VARNAME(oldmsg_entity, statement) #define WRITESPECTATABLE(msg,statement) if(msg == MSG_ONE) { WRITESPECTATABLE_MSG_ONE(statement); } else statement float WRITESPECTATABLE_workaround = 0 + +void Send_CSQC_Centerprint_Generic(entity e, float id, string s, float duration, float countdown_num) +{ + if (clienttype(e) == CLIENTTYPE_REAL) + { + msg_entity = e; + WRITESPECTATABLE_MSG_ONE({ + WriteByte(MSG_ONE, SVC_TEMPENTITY); + WriteByte(MSG_ONE, TE_CSQC_CENTERPRINT_GENERIC); + WriteByte(MSG_ONE, id); + WriteString(MSG_ONE, s); + if (id != 0 && s != "") + { + WriteByte(MSG_ONE, duration); + WriteByte(MSG_ONE, countdown_num); + } + }); + } +} +void Send_CSQC_Centerprint_Generic_Expire(entity e, float id) +{ + Send_CSQC_Centerprint_Generic(e, id, "", 1, 0); +} // WARNING: this kills the trace globals #define EXACTTRIGGER_TOUCH if(WarpZoneLib_ExactTrigger_Touch()) return #define EXACTTRIGGER_INIT WarpZoneLib_ExactTrigger_Init() @@ -1756,7 +1678,7 @@ void make_safe_for_remove(entity e) void objerror(string s) { make_safe_for_remove(self); - objerror_builtin(s); + builtin_objerror(s); } .float remove_except_protected_forbidden; @@ -1764,18 +1686,20 @@ void remove_except_protected(entity e) { if(e.remove_except_protected_forbidden) error("not allowed to remove this at this point"); - remove_builtin(e); + builtin_remove(e); } void remove_unsafely(entity e) { - remove_builtin(e); + if(e.classname == "spike") + error("Removing spikes is forbidden (crylink bug), please report"); + builtin_remove(e); } void remove_safely(entity e) { make_safe_for_remove(e); - remove_builtin(e); + builtin_remove(e); } void InitializeEntity(entity e, void(void) func, float order) @@ -1836,7 +1760,7 @@ void InitializeEntitiesRun() { entity e_old; e_old = self.enemy; - remove_builtin(self); + builtin_remove(self); self = e_old; } //dprint("Delayed initialization: ", self.classname, "\n"); @@ -1933,7 +1857,7 @@ void adaptor_think2use_hittype_splash() // for timed projectile detonation // deferred dropping void DropToFloor_Handler() { - droptofloor_builtin(); + builtin_droptofloor(); self.dropped_origin = self.origin; } @@ -2001,7 +1925,8 @@ float SUB_NoImpactCheck() // these stop the projectile from moving, so... if(trace_dphitcontents == 0) { - dprint("A hit happened with zero hit contents... DEBUG THIS, this should never happen for projectiles! Projectile will self-destruct.\n"); + //dprint("A hit happened with zero hit contents... DEBUG THIS, this should never happen for projectiles! Projectile will self-destruct.\n"); + dprint(sprintf(_("A hit from a projectile happened with no hit contents! DEBUG THIS, this should never happen for projectiles! Profectile will self-destruct. (edict: %d, classname: %s, origin: %s)\n"), num_for_edict(self), self.classname, vtos(self.origin))); checkclient(); } if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT) @@ -2028,17 +1953,27 @@ float SUB_NoImpactCheck() #define SUB_OwnerCheck() (other && (other == self.owner)) +void RemoveGrapplingHook(entity pl); +void W_Crylink_Dequeue(entity e); float WarpZone_Projectile_Touch_ImpactFilter_Callback() { if(SUB_OwnerCheck()) return TRUE; if(SUB_NoImpactCheck()) { - remove(self); + if(self.classname == "grapplinghook") + RemoveGrapplingHook(self.realowner); + else if(self.classname == "spike") + { + W_Crylink_Dequeue(self); + remove(self); + } + else + remove(self); return TRUE; } if(trace_ent && trace_ent.solid > SOLID_TRIGGER) - UpdateCSQCProjectileNextFrame(self); + UpdateCSQCProjectile(self); return FALSE; } #define PROJECTILE_TOUCH if(WarpZone_Projectile_Touch()) return @@ -2048,7 +1983,6 @@ float MAX_IPBAN_URIS = 16; float URI_GET_DISCARD = 0; float URI_GET_IPBAN = 1; float URI_GET_IPBAN_END = 16; -float URI_GET_PLAYERSTATS_SENT = 17; void URI_Get_Callback(float id, float status, string data) { @@ -2056,7 +1990,11 @@ void URI_Get_Callback(float id, float status, string data) dprint(data); dprint("\nEnd of data.\n"); - if (id == URI_GET_DISCARD) + if(url_URI_Get_Callback(id, status, data)) + { + // handled + } + else if (id == URI_GET_DISCARD) { // discard } @@ -2065,27 +2003,27 @@ void URI_Get_Callback(float id, float status, string data) // online ban list OnlineBanList_URI_Get_Callback(id, status, data); } - else if (id == URI_GET_PLAYERSTATS_SENT) - { - PlayerStats_Sent_URI_Get_Callback(id, status, data); - } else { print("Received HTTP request data for an invalid id ", ftos(id), ".\n"); } } -void print_to(entity e, string s) -{ - if (e) - sprint(e, strcat(s, "\n")); - else - print(s, "\n"); -} - string uid2name(string myuid) { string s; - s = db_get(ServerProgsDB, strcat("uid2name", myuid)); + s = db_get(ServerProgsDB, strcat("/uid2name/", myuid)); + + // FIXME remove this later after 0.6 release + // convert old style broken records to correct style + if(s == "") + { + s = db_get(ServerProgsDB, strcat("uid2name", myuid)); + if(s != "") + { + db_put(ServerProgsDB, strcat("/uid2name/", myuid), s); + db_put(ServerProgsDB, strcat("uid2name", myuid), ""); + } + } if(s == "") s = "^1Unregistered Player"; @@ -2183,297 +2121,12 @@ string race_placeName(float pos) { else return strcat(ftos(pos), "th"); } -string getrecords(float page) // 50 records per page -{ - float rec; - string h; - float r; - float i; - string s; - - rec = 0; - - s = ""; - - if (g_ctf) - { - for (i = page * 200; i < MapInfo_count && i < page * 200 + 200; ++i) - { - if (MapInfo_Get_ByID(i)) - { - r = stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, "/captimerecord/time"))); - if (r == 0) - continue; - // TODO: uid2name - h = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, "/captimerecord/netname")); - s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-6, ftos_decimals(r, 2)), " ", h, "\n"); - ++rec; - } - } - } - - if (g_race) - { - for (i = page * 200; i < MapInfo_count && i < page * 200 + 200; ++i) - { - if (MapInfo_Get_ByID(i)) - { - r = race_readTime(MapInfo_Map_bspname, 1); - if (r == 0) - continue; - h = race_readName(MapInfo_Map_bspname, 1); - s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-8, TIME_ENCODED_TOSTRING(r)), " ", h, "\n"); - ++rec; - } - } - } - - if (g_cts) - { - for (i = page * 200; i < MapInfo_count && i < page * 200 + 200; ++i) - { - if (MapInfo_Get_ByID(i)) - { - r = race_readTime(MapInfo_Map_bspname, 1); - if (r == 0) - continue; - h = race_readName(MapInfo_Map_bspname, 1); - s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-8, TIME_ENCODED_TOSTRING(r)), " ", h, "\n"); - ++rec; - } - } - } - - MapInfo_ClearTemps(); - - if (s == "" && page == 0) - return "No records are available on this server.\n"; - else - return s; -} - -string getrankings() -{ - string n; - float t; - float i; - string s; - string p; - string map; - - s = ""; - - map = GetMapname(); - - for (i = 1; i <= RANKINGS_CNT; ++i) - { - t = race_readTime(map, i); - if (t == 0) - continue; - n = race_readName(map, i); - p = race_placeName(i); - s = strcat(s, strpad(8, p), " ", strpad(-8, TIME_ENCODED_TOSTRING(t)), " ", n, "\n"); - } - - MapInfo_ClearTemps(); - - if (s == "") - return strcat("No records are available for the map: ", map, "\n"); - else - return strcat("Records for ", map, ":\n", s); -} - -#define LADDER_FIRSTPOINT 100 -#define LADDER_CNT 10 - // position X still gives LADDER_FIRSTPOINT/X points -#define LADDER_SIZE 30 - // ladder shows the top X players -string top_uids[LADDER_SIZE]; -float top_scores[LADDER_SIZE]; -string getladder() -{ - float i, j, k, uidcnt; - string s, temp_s; - - s = ""; - temp_s = ""; - - string rr; - if(g_cts) - rr = CTS_RECORD; - else - rr = RACE_RECORD; - - string myuid; - - for (k = 0; k < MapInfo_count; ++k) - { - if (MapInfo_Get_ByID(k)) - { - for (i = 0; i <= LADDER_CNT; ++i) { // i = 0 because it is the speed award - if(i == 0) // speed award - { - if(stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, rr, "speed/speed"))) == 0) - continue; - - myuid = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, rr, "speed/crypto_idfp")); - } - else // normal record, if it exists (else break) - { - if(race_readTime(MapInfo_Map_bspname, i) == 0) - continue; - - myuid = race_readUID(MapInfo_Map_bspname, i); - } - - // string s contains: - // arg 0 = # of speed recs - // arg 1 = # of 1st place recs - // arg 2 = # of 2nd place recs - // ... etc - // LADDER_CNT+1 = total points - - temp_s = db_get(TemporaryDB, strcat("ladder", myuid)); - if (temp_s == "") - { - db_put(TemporaryDB, strcat("uid", ftos(uidcnt)), myuid); - ++uidcnt; - for (j = 0; j <= LADDER_CNT + 1; ++j) - { - if(j != LADDER_CNT + 1) - temp_s = strcat(temp_s, "0 "); - else - temp_s = strcat(temp_s, "0"); - } - } - - tokenize_console(temp_s); - s = ""; - - if(i == 0) // speed award - for (j = 0; j <= LADDER_CNT; ++j) // loop over each arg in the string - { - if(j == 0) // speed award - s = strcat(s, ftos(stof(argv(j)) +1)); // add 1 to speed rec count and write - else - s = strcat(s, " ", argv(j)); // just copy over everything else - } - else // record - for (j = 0; j <= LADDER_CNT; ++j) // loop over each arg in the string - { - if(j == 0) - s = strcat(s, argv(j)); // speed award, dont prefix with " " - else if(j == i) // wanted rec! - s = strcat(s, " ", ftos(stof(argv(j)) +1)); // update argv(j) - else - s = strcat(s, " ", argv(j)); // just copy over everything else - } - - // total points are (by default) calculated like this: - // speedrec = floor(100 / 10) = 10 points - // 1st place = floor(100 / 1) = 100 points - // 2nd place = floor(100 / 2) = 50 points - // 3rd place = floor(100 / 3) = 33 points - // 4th place = floor(100 / 4) = 25 points - // 5th place = floor(100 / 5) = 20 points - // ... etc - - if(i == 0) - s = strcat(s, " ", ftos(stof(argv(LADDER_CNT+1)) + LADDER_FIRSTPOINT / 10)); // speed award, add LADDER_FIRSTPOINT / 10 points - else - s = strcat(s, " ", ftos(stof(argv(LADDER_CNT+1)) + floor(LADDER_FIRSTPOINT / i))); // record, add LADDER_FIRSTPOINT / i points - - db_put(TemporaryDB, strcat("ladder", myuid), s); - } - } - } - - float thiscnt; - string thisuid; - for (i = 0; i <= uidcnt; ++i) // for each known uid - { - thisuid = db_get(TemporaryDB, strcat("uid", ftos(i))); - temp_s = db_get(TemporaryDB, strcat("ladder", thisuid)); - tokenize_console(temp_s); - thiscnt = stof(argv(LADDER_CNT+1)); - - if(thiscnt > top_scores[LADDER_SIZE-1]) - for (j = 0; j < LADDER_SIZE; ++j) // for each place in ladder - { - if(thiscnt > top_scores[j]) - { - for (k = LADDER_SIZE-1; k >= j; --k) - { - top_uids[k] = top_uids[k-1]; - top_scores[k] = top_scores[k-1]; - } - top_uids[j] = thisuid; - top_scores[j] = thiscnt; - break; - } - } - } - - s = "^3-----------------------\n\n"; - - s = strcat(s, "Pos ^3|"); - s = strcat(s, " ^7Total ^3|"); - for (i = 1; i <= LADDER_CNT; ++i) - { - s = strcat(s, " ^7", race_placeName(i), " ^3|"); - } - s = strcat(s, " ^7Speed awards ^3| ^7Name"); - - s = strcat(s, "\n^3----+--------"); - for (i = 1; i <= min(9, LADDER_CNT); ++i) - { - s = strcat(s, "+-----"); - } -#if LADDER_CNT > 9 - for (i = 1; i <= LADDER_CNT - 9; ++i) - { - s = strcat(s, "+------"); - } -#endif - - s = strcat(s, "+--------------+--------------------\n"); - - for (i = 0; i < LADDER_SIZE; ++i) - { - temp_s = db_get(TemporaryDB, strcat("ladder", top_uids[i])); - tokenize_console(temp_s); - if (argv(LADDER_CNT+1) == "") // total is 0, skip - continue; - s = strcat(s, strpad(4, race_placeName(i+1)), "^3| ^7"); // pos - s = strcat(s, strpad(7, argv(LADDER_CNT+1)), "^3| ^7"); // total - for (j = 1; j <= min(9, LADDER_CNT); ++j) - { - s = strcat(s, strpad(4, argv(j)), "^3| ^7"); // 1st, 2nd, 3rd etc cnt - } -#if LADDER_CNT > 9 - for (j = 10; j <= LADDER_CNT; ++j) - { - s = strcat(s, strpad(4, argv(j)), " ^3| ^7"); // 1st, 2nd, 3rd etc cnt - } -#endif - - s = strcat(s, strpad(13, argv(0)), "^3| ^7"); // speed award cnt - s = strcat(s, uid2name(top_uids[i]), "\n"); // name - } - - MapInfo_ClearTemps(); - - if (s == "") - return "No ladder on this server!\n"; - else - return strcat("Top ", ftos(LADDER_SIZE), " ladder rankings:\n", s); -} - float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance) { float m, i; vector start, org, delta, end, enddown, mstart; + entity sp; m = e.dphitcontentsmask; e.dphitcontentsmask = goodcontents | badcontents; @@ -2526,6 +2179,19 @@ float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, f if (trace_fraction >= 1) continue; + // rule 4: we must "see" some spawnpoint + for(sp = world; (sp = find(sp, classname, "info_player_deathmatch")); ) + if(checkpvs(mstart, sp)) + break; + if(!sp) + { + for(sp = world; (sp = findflags(sp, flags, FL_ITEM)); ) + if(checkpvs(mstart, sp)) + break; + if(!sp) + continue; + } + // find a random vector to "look at" end_x = org_x + random() * delta_x; end_y = org_y + random() * delta_y; @@ -2545,10 +2211,7 @@ float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, f // rule 6: we must not end up in trigger_hurt if (tracebox_hits_trigger_hurt(start, e.mins, e.maxs, enddown)) - { - dprint("trigger_hurt! ouch! and nothing else could find it!\n"); continue; - } break; } @@ -2640,15 +2303,15 @@ vector shotorg_adjustfromclient(vector vecs, float y_is_right, float allowcenter { switch(algn) { - case 1: // right + default: + case 3: // right break; - case 2: // left + case 4: // left vecs_y = -vecs_y; break; - default: - case 3: + case 1: if(allowcenter) // 2: allow center handedness { // center @@ -2661,7 +2324,7 @@ vector shotorg_adjustfromclient(vector vecs, float y_is_right, float allowcenter } break; - case 4: + case 2: if(allowcenter) // 2: allow center handedness { // center @@ -2687,7 +2350,8 @@ vector shotorg_adjust_values(vector vecs, float y_is_right, float visual, float { if (visual) { - vecs = shotorg_adjustfromclient(vecs, y_is_right, TRUE, algn); + vecs_y = 0; + vecs_z -= 2; } else { @@ -2697,15 +2361,8 @@ vector shotorg_adjust_values(vector vecs, float y_is_right, float visual, float } else if (autocvar_g_shootfromcenter) { - if (visual) - { - vecs = shotorg_adjustfromclient(vecs, y_is_right, TRUE, algn); - } - else - { - vecs_y = 0; - vecs_z -= 2; - } + vecs_y = 0; + vecs_z -= 2; } else if ((s = autocvar_g_shootfromfixedorigin) != "") { @@ -2853,71 +2510,6 @@ void SoundEntity_Detach(entity pl) SoundEntity_StopSound(pl, i); } - -float ParseCommandPlayerSlotTarget_firsttoken; -entity GetCommandPlayerSlotTargetFromTokenizedCommand(float tokens, float idx) // idx = start index -{ - string s; - entity e, head; - float n; - - s = string_null; - - ParseCommandPlayerSlotTarget_firsttoken = -1; - - if (tokens > idx) - { - if (substring(argv(idx), 0, 1) == "#") - { - s = substring(argv(idx), 1, -1); - ++idx; - if (s == "") - if (tokens > idx) - { - s = argv(idx); - ++idx; - } - ParseCommandPlayerSlotTarget_firsttoken = idx; - if (s == ftos(stof(s))) - { - e = edict_num(stof(s)); - if (e.flags & FL_CLIENT) - return e; - } - } - else - { - // it must be a nick name - s = argv(idx); - ++idx; - ParseCommandPlayerSlotTarget_firsttoken = idx; - - n = 0; - FOR_EACH_CLIENT(head) - if (head.netname == s) - { - e = head; - ++n; - } - if (n == 1) - return e; - - s = strdecolorize(s); - n = 0; - FOR_EACH_CLIENT(head) - if (strdecolorize(head.netname) == s) - { - e = head; - ++n; - } - if (n == 1) - return e; - } - } - - return world; -} - .float scale2; float modeleffect_SendEntity(entity to, float sf) @@ -3066,14 +2658,14 @@ float ExponentialFalloff(float mindist, float maxdist, float halflifedist, float #ifdef RELEASE -#define cvar_string_normal cvar_string_builtin -#define cvar_normal cvar_builtin +#define cvar_string_normal builtin_cvar_string +#define cvar_normal builtin_cvar #else string cvar_string_normal(string n) { if not(cvar_type(n) & 1) backtrace(strcat("Attempt to access undefined cvar: ", n)); - return cvar_string_builtin(n); + return builtin_cvar_string(n); } float cvar_normal(string n) @@ -3081,7 +2673,7 @@ float cvar_normal(string n) return stof(cvar_string_normal(n)); } #endif -#define cvar_set_normal cvar_set_builtin +#define cvar_set_normal builtin_cvar_set void defer_think() { @@ -3109,3 +2701,60 @@ void defer(float fdelay, void() func) e.think = defer_think; e.nextthink = time + fdelay; } + +.string aiment_classname; +.float aiment_deadflag; +void SetMovetypeFollow(entity ent, entity e) +{ + // FIXME this may not be warpzone aware + ent.movetype = MOVETYPE_FOLLOW; // make the hole follow + ent.solid = SOLID_NOT; // MOVETYPE_FOLLOW is always non-solid - this means this cannot be teleported by warpzones any more! Instead, we must notice when our owner gets teleported. + ent.aiment = e; // make the hole follow bmodel + ent.punchangle = e.angles; // the original angles of bmodel + ent.view_ofs = ent.origin - e.origin; // relative origin + ent.v_angle = ent.angles - e.angles; // relative angles + ent.aiment_classname = strzone(e.classname); + ent.aiment_deadflag = e.deadflag; +} +void UnsetMovetypeFollow(entity ent) +{ + ent.movetype = MOVETYPE_FLY; + PROJECTILE_MAKETRIGGER(ent); + ent.aiment = world; +} +float LostMovetypeFollow(entity ent) +{ +/* + if(ent.movetype != MOVETYPE_FOLLOW) + if(ent.aiment) + error("???"); +*/ + if(ent.aiment) + { + if(ent.aiment.classname != ent.aiment_classname) + return 1; + if(ent.aiment.deadflag != ent.aiment_deadflag) + return 1; + } + return 0; +} + +float isPushable(entity e) +{ + if(e.iscreature) + return TRUE; + switch(e.classname) + { + case "body": + case "droppedweapon": + case "keepawayball": + case "nexball_basketball": + case "nexball_football": + return TRUE; + case "bullet": // antilagged bullets can't hit this either + return FALSE; + } + if (e.projectiledeathtype) + return TRUE; + return FALSE; +} diff --git a/qcsrc/server/mode_onslaught.qc b/qcsrc/server/mode_onslaught.qc index ba1f8accc3..f6e3de4cdd 100644 --- a/qcsrc/server/mode_onslaught.qc +++ b/qcsrc/server/mode_onslaught.qc @@ -43,11 +43,11 @@ void ons_throwgib_think() if(d>2) if(random()<0.6) pointparticles(particleeffectnum("onslaught_generator_gib_flame"), self.origin, '0 0 0', 1); -}; +} void ons_throwgib(vector v_from, vector v_to, string smodel, float f_lifetime, float b_burn) { - local entity gib; + entity gib; gib = spawn(); @@ -70,12 +70,12 @@ void ons_throwgib(vector v_from, vector v_to, string smodel, float f_lifetime, f } else SUB_SetFade(gib, gib.giblifetime, 2); -}; +} void onslaught_updatelinks() { - local entity l, links; - local float stop, t1, t2, t3, t4; + entity l, links; + float stop, t1, t2, t3, t4; // first check if the game has ended dprint("--- updatelinks ---\n"); links = findchain(classname, "onslaught_link"); @@ -258,7 +258,7 @@ void onslaught_updatelinks() dprint("--- game over ---\n"); else dprint("--- done updating links ---\n"); -}; +} float onslaught_controlpoint_can_be_linked(entity cp, float t) { @@ -372,19 +372,25 @@ float onslaught_controlpoint_attackable(entity cp, float t) return 0; } +float overtime_msg_time; void onslaught_generator_think() { - local float d; - local entity e; + float d; + entity e; self.nextthink = ceil(time + 1); if (!gameover) { - if (autocvar_timelimit) - if (time > game_starttime + autocvar_timelimit * 60) + if (autocvar_timelimit && time > game_starttime + autocvar_timelimit * 60) { + if (!overtime_msg_time) + { + FOR_EACH_PLAYER(e) + centerprint(e, "^3Now playing ^1OVERTIME^3!\n^3Generators start now to self-damaging.\n^3The more control points your team holds,\n^3the more damage the enemy generator gets."); + overtime_msg_time = time; + } // self.max_health / 300 gives 5 minutes of overtime. // control points reduce the overtime duration. - sound(self, CHAN_TRIGGER, "onslaught/generator_decay.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER, "onslaught/generator_decay.wav", VOL_BASE, ATTN_NORM); d = 1; e = findchain(classname, "onslaught_controlpoint"); while (e) @@ -397,13 +403,15 @@ void onslaught_generator_think() d = d * self.max_health / 300; Damage(self, self, self, d, DEATH_HURTTRIGGER, self.origin, '0 0 0'); } + else if (overtime_msg_time) + overtime_msg_time = 0; } -}; +} void onslaught_generator_ring_spawn(vector org) { modeleffect_spawn("models/onslaught/shockwavetransring.md3", 0, 0, org, '0 0 0', '0 0 0', '0 0 0', 0, -16, 0.1, 1.25, 0.25); -}; +} void onslaught_generator_ray_think() { @@ -421,7 +429,7 @@ void onslaught_generator_ray_think() self.scale += 0.2; self.count +=1; -}; +} void onslaught_generator_ray_spawn(vector org) { @@ -434,12 +442,12 @@ void onslaught_generator_ray_spawn(vector org) e.scale = random() * 5 + 8; e.think = onslaught_generator_ray_think; e.nextthink = time + 0.05; -}; +} void onslaught_generator_shockwave_spawn(vector org) { shockwave_spawn("models/onslaught/shockwave.md3", org, -64, 0.75, 0.5); -}; +} void onslaught_generator_damage_think() { @@ -455,11 +463,11 @@ void onslaught_generator_damage_think() if(random() < 0.01) { pointparticles(particleeffectnum("electro_ballexplode"), self.origin + randompos('-50 -50 -20', '50 50 50'), '0 0 0', 1); - sound(self, CHAN_TRIGGER, "onslaught/electricity_explode.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER, "onslaught/electricity_explode.wav", VOL_BASE, ATTN_NORM); } else pointparticles(particleeffectnum("torch_small"), self.origin + randompos('-60 -60 -20', '60 60 60'), '0 0 0', 1); -}; +} void onslaught_generator_damage_spawn(entity gd_owner) { @@ -470,12 +478,12 @@ void onslaught_generator_damage_spawn(entity gd_owner) setorigin(e, gd_owner.origin); e.think = onslaught_generator_damage_think; e.nextthink = time+1; -}; +} void onslaught_generator_deaththink() { - local vector org; - local float i; + vector org; + float i; if not (self.count) self.count = 40; @@ -484,7 +492,7 @@ void onslaught_generator_deaththink() if(self.count==40||self.count==20) { onslaught_generator_ring_spawn(self.origin); - sound(self, CHAN_TRIGGER, "onslaught/shockwave.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER, "onslaught/shockwave.wav", VOL_BASE, ATTN_NORM); } // Throw some gibs @@ -510,7 +518,7 @@ void onslaught_generator_deaththink() if(random() < 0.25) { te_explosion(self.origin); - sound(self, CHAN_TRIGGER, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM); } // Particles @@ -530,17 +538,17 @@ void onslaught_generator_deaththink() te_explosion(org); onslaught_generator_shockwave_spawn(org); pointparticles(particleeffectnum("onslaught_generator_finalexplosion"), org, '0 0 0', 1); - sound(self, CHAN_TRIGGER, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); } else self.nextthink = time + 0.05; self.count = self.count - 1; -}; +} void onslaught_generator_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) { - local float i; + float i; if (damage <= 0) return; if(inWarmupStage) @@ -631,7 +639,7 @@ void onslaught_generator_damage(entity inflictor, entity attacker, float damage, // Throw some flaming gibs on damage, more damage = more chance for gib if(random() < damage/220) { - sound(self, CHAN_TRIGGER, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); i = random(); if(i < 0.3) ons_throwgib(hitloc + '0 0 20', force * -1, "models/onslaught/gen_gib1.md3", 5, TRUE); @@ -647,16 +655,16 @@ void onslaught_generator_damage(entity inflictor, entity attacker, float damage, //sound on every hit if (random() < 0.5) - sound(self, CHAN_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE, ATTN_NORM); else - sound(self, CHAN_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE, ATTN_NORM); } //throw some gibs on damage if(random() < damage/200+0.2) if(random() < 0.5) ons_throwgib(hitloc + '0 0 20', randomvec()*360, "models/onslaught/gen_gib1.md3", 5, FALSE); -}; +} // update links after a delay void onslaught_generator_delayed() @@ -665,7 +673,7 @@ void onslaught_generator_delayed() // now begin normal thinking self.think = onslaught_generator_think; self.nextthink = time; -}; +} string onslaught_generator_waypointsprite_for_team(entity e, float t) { @@ -819,6 +827,7 @@ void onslaught_generator_reset() self.think = onslaught_generator_delayed; self.nextthink = time + 0.2; setmodel(self, "models/onslaught/generator.md3"); + setsize(self, '-52 -52 -14', '52 52 75'); WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health); WaypointSprite_UpdateHealth(self.sprite, self.health); @@ -841,7 +850,7 @@ void spawnfunc_onslaught_generator() return; } - local entity e; + entity e; precache_model("models/onslaught/generator.md3"); precache_model("models/onslaught/generator_shield.md3"); precache_model("models/onslaught/generator_dmg1.md3"); @@ -900,7 +909,7 @@ void spawnfunc_onslaught_generator() self.nextthink = time + 0.2; InitializeEntity(self, onslaught_generator_delayed, INITPRIO_LAST); - WaypointSprite_SpawnFixed(string_null, e.origin + '0 0 1' * e.maxs_z, self, sprite); + WaypointSprite_SpawnFixed(string_null, e.origin + '0 0 1' * e.maxs_z, self, sprite, RADARICON_NONE, '0 0 0'); WaypointSprite_UpdateRule(self.sprite, COLOR_TEAM2, SPRITERULE_TEAMPLAY); WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health); WaypointSprite_UpdateHealth(self.sprite, self.health); @@ -910,7 +919,7 @@ void spawnfunc_onslaught_generator() onslaught_updatelinks(); self.reset = onslaught_generator_reset; -}; +} .float waslinked; .float cp_bob_spd; @@ -977,13 +986,13 @@ void onslaught_controlpoint_icon_damage(entity inflictor, entity attacker, float pointparticles(particleeffectnum("sparks"), hitloc, force*-1, 1); //sound on every hit if (random() < 0.5) - sound(self, CHAN_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE+0.3, ATTN_NORM); + sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE+0.3, ATTN_NORM); else - sound(self, CHAN_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE+0.3, ATTN_NORM); + sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE+0.3, ATTN_NORM); if (self.health < 0) { - sound(self, CHAN_TRIGGER, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM); pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1); { string t; @@ -1022,7 +1031,7 @@ void onslaught_controlpoint_icon_damage(entity inflictor, entity attacker, float remove(self); } -}; +} void onslaught_controlpoint_icon_think() { @@ -1067,33 +1076,55 @@ void onslaught_controlpoint_icon_think() self.owner.waslinked = self.owner.islinked; } - if (self.punchangle_x > 2) - self.punchangle_x = self.punchangle_x - 2; - else if (self.punchangle_x < -2) - self.punchangle_x = self.punchangle_x + 2; - else - self.punchangle_x = 0; - if (self.punchangle_y > 2) - self.punchangle_y = self.punchangle_y - 2; - else if (self.punchangle_y < -2) - self.punchangle_y = self.punchangle_y + 2; - else - self.punchangle_y = 0; - if (self.punchangle_z > 2) - self.punchangle_z = self.punchangle_z - 2; - else if (self.punchangle_z < -2) - self.punchangle_z = self.punchangle_z + 2; - else - self.punchangle_z = 0; + + if (self.punchangle_x > 0) + { + self.punchangle_x = self.punchangle_x - 60 * sys_frametime; + if (self.punchangle_x < 0) + self.punchangle_x = 0; + } + else if (self.punchangle_x < 0) + { + self.punchangle_x = self.punchangle_x + 60 * sys_frametime; + if (self.punchangle_x > 0) + self.punchangle_x = 0; + } + + if (self.punchangle_y > 0) + { + self.punchangle_y = self.punchangle_y - 60 * sys_frametime; + if (self.punchangle_y < 0) + self.punchangle_y = 0; + } + else if (self.punchangle_y < 0) + { + self.punchangle_y = self.punchangle_y + 60 * sys_frametime; + if (self.punchangle_y > 0) + self.punchangle_y = 0; + } + + if (self.punchangle_z > 0) + { + self.punchangle_z = self.punchangle_z - 60 * sys_frametime; + if (self.punchangle_z < 0) + self.punchangle_z = 0; + } + else if (self.punchangle_z < 0) + { + self.punchangle_z = self.punchangle_z + 60 * sys_frametime; + if (self.punchangle_z > 0) + self.punchangle_z = 0; + } + self.angles_x = self.punchangle_x; self.angles_y = self.punchangle_y + self.mangle_y; self.angles_z = self.punchangle_z; - self.mangle_y = self.mangle_y + 1.5; + self.mangle_y = self.mangle_y + 45 * sys_frametime; - self.cp_bob_origin_z = 4 * PI * (1 - cos(self.cp_bob_spd / 8)); - self.cp_bob_spd = self.cp_bob_spd + 0.5; + self.cp_bob_origin_z = 4 * PI * (1 - cos(self.cp_bob_spd)); + self.cp_bob_spd = self.cp_bob_spd + 1.875 * sys_frametime; if(self.cp_bob_dmg_z > 0) - self.cp_bob_dmg_z = self.cp_bob_dmg_z - 0.1; + self.cp_bob_dmg_z = self.cp_bob_dmg_z - 3 * sys_frametime; else self.cp_bob_dmg_z = 0; setorigin(self,self.cp_origin + self.cp_bob_origin + self.cp_bob_dmg); @@ -1104,15 +1135,15 @@ void onslaught_controlpoint_icon_think() pointparticles(particleeffectnum("electricity_sparks"), self.origin + randompos('-10 -10 -20', '10 10 20'), '0 0 0', 1); if(random() > 0.8) - sound(self, CHAN_PAIN, "onslaught/ons_spark1.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_PAIN, "onslaught/ons_spark1.wav", VOL_BASE, ATTN_NORM); else if (random() > 0.5) - sound(self, CHAN_PAIN, "onslaught/ons_spark2.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_PAIN, "onslaught/ons_spark2.wav", VOL_BASE, ATTN_NORM); } -}; +} void onslaught_controlpoint_icon_buildthink() { - local entity oself; + entity oself; float a; self.nextthink = time + sys_frametime; @@ -1129,7 +1160,7 @@ void onslaught_controlpoint_icon_buildthink() self.health = self.max_health; self.count = autocvar_g_onslaught_cp_regen * sys_frametime; // slow repair rate from now on self.think = onslaught_controlpoint_icon_think; - sound(self, CHAN_TRIGGER, "onslaught/controlpoint_built.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER, "onslaught/controlpoint_built.wav", VOL_BASE, ATTN_NORM); bprint(ColoredTeamName(self.team), " captured ", self.owner.message, " control point\n"); self.owner.iscaptured = TRUE; @@ -1157,14 +1188,14 @@ void onslaught_controlpoint_icon_buildthink() if(random() < 0.9 - self.health / self.max_health) pointparticles(particleeffectnum("rage"), self.origin + 10 * randomvec(), '0 0 -1', 1); -}; +} void onslaught_controlpoint_touch() { - local entity e; + entity e; float a; if (other.classname != "player") return; @@ -1192,12 +1223,12 @@ void onslaught_controlpoint_touch() e.think = onslaught_controlpoint_icon_buildthink; e.nextthink = time + sys_frametime; e.count = (e.max_health - e.health) * sys_frametime / autocvar_g_onslaught_cp_buildtime; // how long it takes to build - sound(e, CHAN_TRIGGER, "onslaught/controlpoint_build.wav", VOL_BASE, ATTN_NORM); + sound(e, CH_TRIGGER, "onslaught/controlpoint_build.wav", VOL_BASE, ATTN_NORM); self.team = e.team; self.colormap = e.colormap; WaypointSprite_UpdateBuildFinished(self.sprite, time + (e.max_health - e.health) / (e.count / sys_frametime)); onslaught_updatelinks(); -}; +} void onslaught_controlpoint_reset() { @@ -1236,7 +1267,7 @@ keys: */ void spawnfunc_onslaught_controlpoint() { - local entity e; + entity e; if (!g_onslaught) { remove(self); @@ -1283,13 +1314,13 @@ void spawnfunc_onslaught_controlpoint() waypoint_spawnforitem(self); - WaypointSprite_SpawnFixed(string_null, e.origin + '0 0 1' * e.maxs_z, self, sprite); + WaypointSprite_SpawnFixed(string_null, e.origin + '0 0 1' * e.maxs_z, self, sprite, RADARICON_NONE, '0 0 0'); WaypointSprite_UpdateRule(self.sprite, COLOR_TEAM2, SPRITERULE_TEAMPLAY); onslaught_updatelinks(); self.reset = onslaught_controlpoint_reset; -}; +} float onslaught_link_send(entity to, float sendflags) { @@ -1393,4 +1424,4 @@ void spawnfunc_onslaught_link() objerror("target and target2 must be set\n"); InitializeEntity(self, onslaught_link_delayed, INITPRIO_FINDTARGET); Net_LinkEntity(self, FALSE, 0, onslaught_link_send); -}; +} diff --git a/qcsrc/server/monsters/ai.qc b/qcsrc/server/monsters/ai.qc deleted file mode 100644 index 022fde2015..0000000000 --- a/qcsrc/server/monsters/ai.qc +++ /dev/null @@ -1,887 +0,0 @@ -void() movetarget_f; -void() t_movetarget; -void() FoundTarget; - -float MONSTER_WANDER = 64; // disable wandering around -float MONSTER_APPEAR = 128; // spawn invisible, and appear when triggered - -.float ismonster; -.float monsterawaitingteleport; // avoid awaking monsters in teleport rooms - -// when a monster becomes angry at a player, that monster will be used -// as the sight target the next frame so that monsters near that one -// will wake up even if they wouldn't have noticed the player -// -entity sight_entity; -float sight_entity_time; - -/* - -.enemy -Will be world if not currently angry at anyone. - -.movetarget -The next path spot to walk toward. If .enemy, ignore .movetarget. -When an enemy is killed, the monster will try to return to it's path. - -.huntt_ime -Set to time + something when the player is in sight, but movement straight for -him is blocked. This causes the monster to use wall following code for -movement direction instead of sighting on the player. - -.ideal_yaw -A yaw angle of the intended direction, which will be turned towards at up -to 45 deg / state. If the enemy is in view and hunt_time is not active, -this will be the exact line towards the enemy. - -.pausetime -A monster will leave it's stand state and head towards it's .movetarget when -time > .pausetime. - -walkmove(angle, speed) primitive is all or nothing -*/ - - -// -// globals -// -//float current_yaw; - -float(float v) anglemod = -{ - v = v - 360 * floor(v / 360); - return v; -}; - -/* -============================================================================== - -MOVETARGET CODE - -The angle of the movetarget effects standing and bowing direction, but has no effect on movement, which allways heads to the next target. - -targetname -must be present. The name of this movetarget. - -target -the next spot to move to. If not present, stop here for good. - -pausetime -The number of seconds to spend standing or bowing for path_stand or path_bow - -============================================================================== -*/ - - -void() movetarget_f = -{ - if (!self.targetname) - objerror ("monster_movetarget: no targetname"); - - self.solid = SOLID_TRIGGER; - self.touch = t_movetarget; - setsize (self, '-8 -8 -8', '8 8 8'); -}; - -/*QUAKED path_corner (0.5 0.3 0) (-8 -8 -8) (8 8 8) -Monsters will continue walking towards the next target corner. -*/ -void() path_corner = -{ - movetarget_f (); -}; - -/* -============= -t_movetarget - -Something has bumped into a movetarget. If it is a monster -moving towards it, change the next destination and continue. -============== -*/ -void() t_movetarget = -{ - local entity temp; - - if (other.health < 1) - return; - if (other.movetarget != self) - return; - - if (other.enemy) - return; // fighting, not following a path - - temp = self; - self = other; - other = temp; - - if (self.classname == "monster_ogre") - sound (self, CHAN_VOICE, "ogre/ogdrag.wav", 1, ATTN_IDLE);// play chainsaw drag sound - -//dprint ("t_movetarget\n"); - self.goalentity = self.movetarget = find (world, targetname, other.target); - self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin); - if (!self.movetarget) - { - self.pausetime = time + 999999; - self.th_stand (); - return; - } -}; - -void() monster_wanderpaththink = -{ - local vector v, v1; - local float b, c; - self.nextthink = time + random() * 10 + 1; - if (self.owner.health < 1) // dead, also handled in death code - { - self.owner.movetarget = world; - remove(self); - return; - } - b = -1; - c = 10; - while (c > 0) - { - c = c - 1; - v = randomvec(); - traceline(self.owner.origin, v * 1024 + self.owner.origin, FALSE, self); - v = trace_endpos - (normalize(v) * 16) - self.owner.origin; - if (vlen(v) > b) - { - b = vlen(v); - v1 = v; - } - } - setorigin(self, v1 + self.owner.origin); - self.owner.ideal_yaw = vectoyaw(self.origin - self.owner.origin); -}; - -void() monster_wanderpathtouch = -{ - if (other.health < 1) - return; - if (other.movetarget != self) - return; - - if (other.enemy) - return; // fighting, not following a path - - if (other.classname == "monster_ogre") - sound (other, CHAN_VOICE, "ogre/ogdrag.wav", 1, ATTN_IDLE);// play chainsaw drag sound - monster_wanderpaththink(); -}; - -void() monster_spawnwanderpath = -{ - newmis = spawn(); - newmis.classname = "monster_wanderpath"; - newmis.solid = SOLID_TRIGGER; - newmis.touch = monster_wanderpathtouch; - setsize (newmis, '-8 -8 -8', '8 8 8'); - newmis.think = monster_wanderpaththink; - newmis.nextthink = time + random() * 10 + 1; - newmis.owner = self; - self.goalentity = self.movetarget = newmis; -}; - -void() monster_checkbossflag = -{ -//#NO AUTOCVARS START -#if 0 - local float healthboost; - local float r; - - // monsterbosses cvar or spawnflag 64 causes a monster to be a miniboss - if ((self.spawnflags & 64) || (random() * 100 < cvar("monsterbosspercent"))) - { - self.radsuit_finished = time + 1000000000; - r = random() * 4; - if (r < 2) - { - self.super_damage_finished = time + 1000000000; - healthboost = 30 + self.health * 0.5; - self.effects = self.effects | (EF_FULLBRIGHT | EF_BLUE); - } - if (r >= 1) - { - healthboost = 30 + self.health * bound(0.5, skill * 0.5, 1.5); - self.effects = self.effects | (EF_FULLBRIGHT | EF_RED); - self.healthregen = max(self.healthregen, min(skill * 10, 30)); - } - self.health = self.health + healthboost; - self.max_health = self.health; - self.bodyhealth = self.bodyhealth * 2 + healthboost; - do - { - self.colormod_x = random(); - self.colormod_y = random(); - self.colormod_z = random(); - self.colormod = normalize(self.colormod); - } - while (self.colormod_x > 0.6 && self.colormod_y > 0.6 && self.colormod_z > 0.6); - } -#endif -//#NO AUTOCVARS END -}; - - -//============================================================================ - -/* -============= -range - -returns the range catagorization of an entity reletive to self -0 melee range, will become hostile even if back is turned -1 visibility and infront, or visibility and show hostile -2 infront and show hostile -3 only triggered by damage -============= -*/ -float(entity targ) range = -{ - local float r; - r = vlen ((self.origin + self.view_ofs) - (targ.origin + targ.view_ofs)); - if (r < 120) - return RANGE_MELEE; - if (r < 500) - return RANGE_NEAR; - if (r < 2000) // increased from 1000 for DP - return RANGE_MID; - return RANGE_FAR; -}; - -/* -============= -visible - -returns 1 if the entity is visible to self, even if not infront () -============= -*/ -float (entity targ) visible = -{ - if (vlen(targ.origin - self.origin) > 5000) // long traces are slow - return FALSE; - - traceline ((self.origin + self.view_ofs), (targ.origin + targ.view_ofs), TRUE, self); // see through other monsters - - if (trace_inopen && trace_inwater) - return FALSE; // sight line crossed contents - - if (trace_fraction == 1) - return TRUE; - return FALSE; -}; - - -/* -============= -infront - -returns 1 if the entity is in front (in sight) of self -============= -*/ -float(entity targ) infront = -{ - local float dot; - - makevectors (self.angles); - dot = normalize (targ.origin - self.origin) * v_forward; - - return (dot > 0.3); -}; -// returns 0 if not infront, or the dotproduct if infront -float(vector dir, entity targ) infront2 = -{ - local float dot; - - dir = normalize(dir); - dot = normalize (targ.origin - self.origin) * dir; - - if (dot >= 0.3) return dot; // infront - return 0; -}; - - -//============================================================================ - -/* -=========== -ChangeYaw - -Turns towards self.ideal_yaw at self.yaw_speed -Sets the global variable current_yaw -Called every 0.1 sec by monsters -============ -*/ -/* - -void() ChangeYaw = -{ - local float ideal, move; - -//current_yaw = self.ideal_yaw; -// mod down the current angle - current_yaw = anglemod( self.angles_y ); - ideal = self.ideal_yaw; - - if (current_yaw == ideal) - return; - - move = ideal - current_yaw; - if (ideal > current_yaw) - { - if (move > 180) - move = move - 360; - } - else - { - if (move < -180) - move = move + 360; - } - - if (move > 0) - { - if (move > self.yaw_speed) - move = self.yaw_speed; - } - else - { - if (move < 0-self.yaw_speed ) - move = 0-self.yaw_speed; - } - - current_yaw = anglemod (current_yaw + move); - - self.angles_y = current_yaw; -}; - -*/ - - -//============================================================================ - -void() HuntTarget = -{ - self.goalentity = self.enemy; - self.think = self.th_run; - self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin); - self.nextthink = time + 0.1; - SUB_AttackFinished (1); // wait a while before first attack -}; - -.void() th_sightsound; - -void() SightSound = -{ - if (self.health < 1) - return; - // skill 5 does not play sight sounds, instead you only hear the appear sound as they are about to attack - if (skill >= 5) - if (self.classname != "monster_hellfish") - return; - - if (self.th_sightsound) - self.th_sightsound(); -}; - -void() FoundTarget = -{ - if (self.health < 1 || !self.th_run) - return; - if (self.enemy.health < 1 || !self.enemy.takedamage) - return; - if (self.enemy.classname == "player") - { - // let other monsters see this monster for a while - sight_entity = self; - sight_entity_time = time + 0.1; - } - - self.show_hostile = time + 1; // wake up other monsters - - SightSound (); - HuntTarget (); -}; - -/* -//float checkplayertime; -entity lastcheckplayer; -entity havocbot_list; - - -entity() checkplayer = -{ - local entity check; - local float worldcount; - // we can just fallback on checkclient if there are no bots - if (!havocbot_list) - return checkclient(); -*/ - /* - if (time < checkplayertime) - { - traceline(self.origin + self.view_ofs, lastcheckplayer.origin + lastcheckplayer.view_ofs, TRUE, self); - if (trace_fraction == 1) - return lastcheckplayer; - if (trace_ent == lastcheckplayer) - return lastcheckplayer; - } - checkplayertime = time + 0.1; - */ -/* - check = lastcheckplayer; - worldcount = 0; - c = 0; - do - { - c = c + 1; - check = findfloat(check, havocattack, TRUE); - if (check.classname == "player" || check.classname == "turretbase") - { - traceline(self.origin + self.view_ofs, check.origin + check.view_ofs, TRUE, self); - if (trace_fraction == 1) - return lastcheckplayer = check; - if (trace_ent == check) - return lastcheckplayer = check; - } - else if (check == world) - { - worldcount = worldcount + 1; - if (worldcount >= 2) - return lastcheckplayer = check; - } - } - while(check != lastcheckplayer && c < 100); - return world; -}; -*/ - -/* -=========== -FindTarget - -Self is currently not attacking anything, so try to find a target - -Returns TRUE if an enemy was sighted - -When a player fires a missile, the point of impact becomes a fakeplayer so -that monsters that see the impact will respond as if they had seen the -player. - -To avoid spending too much time, only a single client (or fakeclient) is -checked each frame. This means multi player games will have slightly -slower noticing monsters. -============ -*/ -.float findtarget; -float() FindTarget = -{ - local entity client; - local float r; - - if (self.health < 1) - return FALSE; - - // if the first or second spawnflag bit is set, the monster will only - // wake up on really seeing the player, not another monster getting angry - - if (self.spawnflags & 3) - { - // don't wake up on seeing another monster getting angry - client = checkclient (); - if (!client) - return FALSE; // current check entity isn't in PVS - } - else - { - if (sight_entity_time >= time) - { - client = sight_entity; - if (client.enemy == self.enemy) - return TRUE; - } - else - { - client = checkclient (); - if (!client) - return FALSE; // current check entity isn't in PVS - } - } - - if (client == self.enemy) - return FALSE; - - if (client.flags & FL_NOTARGET) - return FALSE; - -#if 0 - if (client.items & IT_INVISIBILITY) - return FALSE; -#endif - - // on skill 5 the monsters usually ignore the player and remain ghostlike - if (skill >= 5) - if (self.classname != "monster_hellfish") - if (random() < 0.99) - return FALSE; - - r = range(client); - if (r == RANGE_FAR) - return FALSE; - - if (!visible (client)) - return FALSE; - - if (r == RANGE_NEAR) - { - if (client.show_hostile < time && !infront (client)) - return FALSE; - } - else if (r == RANGE_MID) - { - // LordHavoc: was if ( /* client.show_hostile < time || */ !infront (client)) - if (client.show_hostile < time && !infront (client)) - return FALSE; - } - - // - // got one - // - - if (client.model == "") - return FALSE; - self.enemy = client; - if (self.enemy.classname != "player" && self.enemy.classname != "turretbase") - { - self.enemy = self.enemy.enemy; - if (self.enemy.classname != "player" && self.enemy.classname != "turretbase") - { - self.enemy = world; - return FALSE; - } - } - - FoundTarget (); - - return TRUE; -}; - - -//============================================================================= - -void(float dist) ai_forward = -{ - walkmove (self.angles_y, dist); -}; - -void(float dist) ai_back = -{ - walkmove ( (self.angles_y+180), dist); -}; - - -void(float a) monster_setalpha; - -/* -============= -ai_pain - -stagger back a bit -============= -*/ -void(float dist) ai_pain = -{ - if (self.health < 1) - return; - ai_back (dist); -}; - -/* -============= -ai_painforward - -stagger back a bit -============= -*/ -void(float dist) ai_painforward = -{ - if (self.health < 1) - return; - walkmove (self.ideal_yaw, dist); -}; - -/* -============= -ai_walk - -The monster is walking it's beat -============= -*/ -void(float dist) ai_walk = -{ - if (self.health < 1) - return; - - movedist = dist; - - // check for noticing a player - if (self.oldenemy.takedamage) - if (self.oldenemy.health >= 1) - { - self.enemy = self.oldenemy; - self.oldenemy = world; - FoundTarget(); - monster_setalpha(0); - return; - } - if (self.enemy) - { - if (self.enemy.takedamage) - { - if (self.enemy.health >= 1) - { - FoundTarget(); - monster_setalpha(0); - return; - } - else - self.enemy = world; - } - else - self.enemy = world; - } - - self.findtarget = TRUE; - - movetogoal (dist); - monster_setalpha(0); -}; - - -/* -============= -ai_stand - -The monster is staying in one place for a while, with slight angle turns -============= -*/ -void() ai_stand = -{ - if (self.health < 1) - return; - if (self.enemy) - { - if (self.enemy.takedamage) - { - if (self.enemy.health >= 1) - { - FoundTarget(); - monster_setalpha(0); - return; - } - else - self.enemy = world; - } - else - self.enemy = world; - } - self.findtarget = TRUE; - - if (time > self.pausetime) - { - self.th_walk (); - monster_setalpha(0); - return; - } - -// change angle slightly - - monster_setalpha(0); -}; - -/* -============= -ai_turn - -don't move, but turn towards ideal_yaw -============= -*/ -void() ai_turn = -{ - if (self.enemy) - { - if (self.enemy.takedamage) - { - if (self.enemy.health >= 1) - { - FoundTarget(); - monster_setalpha(0); - return; - } - else - self.enemy = world; - } - else - self.enemy = world; - } - self.findtarget = TRUE; - - ChangeYaw (); - monster_setalpha(0); -}; - -//============================================================================= - -/* -============= -ChooseTurn -============= -*/ -void(vector pDestvec) ChooseTurn = -{ - local vector dir, newdir; - - dir = self.origin - pDestvec; - - newdir_x = trace_plane_normal_y; - newdir_y = 0 - trace_plane_normal_x; - newdir_z = 0; - - if (dir * newdir > 0) - { - dir_x = 0 - trace_plane_normal_y; - dir_y = trace_plane_normal_x; - } - else - { - dir_x = trace_plane_normal_y; - dir_y = 0 - trace_plane_normal_x; - } - - dir_z = 0; - self.ideal_yaw = vectoyaw(dir); -}; - -/* -============ -FacingIdeal - -============ -*/ -float() FacingIdeal = -{ - local float delta; - - delta = anglemod(self.angles_y - self.ideal_yaw); - if (delta > 45 && delta < 315) - return FALSE; - return TRUE; -}; - - -//============================================================================= - -.float() th_checkattack; - - - -/* -============= -ai_run - -The monster has an enemy it is trying to kill -============= -*/ -void(float dist) ai_run = -{ - local float ofs; - if (self.health < 1) - return; - movedist = dist; - // see if the enemy is dead - if (self.enemy.health < 1 || self.enemy.takedamage == DAMAGE_NO) - { - self.enemy = world; - // FIXME: look all around for other targets - if (self.oldenemy.health >= 1 && self.oldenemy.takedamage) - { - self.enemy = self.oldenemy; - self.oldenemy = world; - HuntTarget (); - } - else - { - if (self.movetarget) - self.th_walk (); - else - self.th_stand (); - return; - } - } - - // wake up other monsters - self.show_hostile = time + 1; - - // check knowledge of enemy - enemy_range = range(self.enemy); - - self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin); - ChangeYaw (); - - if (self.attack_state == AS_MELEE) - { - //dprint ("ai_run_melee\n"); - //Turn and close until within an angle to launch a melee attack - if (FacingIdeal()) - { - self.th_melee (); - self.attack_state = AS_STRAIGHT; - } - return; - } - else if (self.attack_state == AS_MISSILE) - { - //dprint ("ai_run_missile\n"); - //Turn in place until within an angle to launch a missile attack - if (FacingIdeal()) - if (self.th_missile ()) - self.attack_state = AS_STRAIGHT; - return; - } - - if (self.th_checkattack()) - return; // beginning an attack - - if (visible(self.enemy)) - self.search_time = time + 5; - else if (coop) - { - // look for other coop players - if (self.search_time < time) - self.findtarget = TRUE; - } - - if (self.attack_state == AS_SLIDING) - { - //dprint ("ai_run_slide\n"); - //Strafe sideways, but stay at aproximately the same range - if (self.lefty) - ofs = 90; - else - ofs = -90; - - if (walkmove (self.ideal_yaw + ofs, movedist)) - return; - - self.lefty = !self.lefty; - - walkmove (self.ideal_yaw - ofs, movedist); - } - - // head straight in - movetogoal (dist); // done in C code... -}; - diff --git a/qcsrc/server/monsters/defs.qc b/qcsrc/server/monsters/defs.qc deleted file mode 100644 index 19821429c3..0000000000 --- a/qcsrc/server/monsters/defs.qc +++ /dev/null @@ -1,55 +0,0 @@ -.entity movetarget; -.float pausetime; - -.void() th_stand; -.void() th_walk; -.void() th_run; -.float() th_missile; // LordHavoc: changed from void() to float(), returns true if attacking -.void() th_melee; -//.void(entity attacker, float damage, float damgtype, string dethtype) th_pain; // TODO Xonotic uses event_damage -//.void() th_die; // TODO never called directly by Xonotic -.entity oldenemy; // mad at this player before taking damage -entity newmis; // launch_spike sets this after spawning it - -// range values -float RANGE_MELEE = 0; -float RANGE_NEAR = 1; -float RANGE_MID = 2; -float RANGE_FAR = 3; - -float DMG_KNIGHT_MELEE_BASE = 0; -float DMG_KNIGHT_MELEE_RANDOM1 = 3; -float DMG_KNIGHT_MELEE_RANDOM2 = 3; -float DMG_KNIGHT_MELEE_RANDOM3 = 3; - -.float show_hostile; - // set to time+0.2 whenever a client fires a - // weapon or takes damage. Used to alert - // monsters that otherwise would let the player go - -float movedist; -.float lefty; -.float search_time; -.float attack_state; - -float AS_STRAIGHT = 1; -float AS_SLIDING = 2; -float AS_MELEE = 3; -float AS_MISSILE = 4; - -float SKILL4_MINALPHA = 0.4; - -float monsterwander; -//#NO AUTOCVARS START -/* - monsterwander = cvar("monsterwander"); - // monsterwander is always on in skill 5 - if (skill >= 5) - monsterwander = TRUE; -*/ -//#NO AUTOCVARS END - -.float candrown; - -.void(vector org, float bodydamage, float armordamage, vector vel, float damgtype) bleedfunc; -void(vector org, float bodydamage, float armordamage, vector vel, float damgtype) genericbleedfunc; diff --git a/qcsrc/server/monsters/fight.qc b/qcsrc/server/monsters/fight.qc deleted file mode 100644 index 10d00a16bb..0000000000 --- a/qcsrc/server/monsters/fight.qc +++ /dev/null @@ -1,252 +0,0 @@ - -/* - -A monster is in fight mode if it thinks it can effectively attack its -enemy. - -When it decides it can't attack, it goes into hunt mode. - -*/ - -void SUB_AttackFinished (float normal) -{ - self.cnt = 0; // refire count for nightmare - if (skill < 3) - ATTACK_FINISHED(self) = time + normal; -} - -float CanDamage(entity targ, entity inflictor) -{ - if (targ.movetype == MOVETYPE_PUSH) - { - traceline(inflictor.origin, 0.5 * (targ.absmin + targ.absmax), TRUE, self); - if (trace_fraction == 1) - return TRUE; - if (trace_ent == targ) - return TRUE; - return FALSE; - } - - traceline(inflictor.origin, targ.origin, TRUE, self); - if (trace_fraction == 1) - return TRUE; - traceline(inflictor.origin, targ.origin + '15 15 0', TRUE, self); - if (trace_fraction == 1) - return TRUE; - traceline(inflictor.origin, targ.origin + '-15 -15 0', TRUE, self); - if (trace_fraction == 1) - return TRUE; - traceline(inflictor.origin, targ.origin + '-15 15 0', TRUE, self); - if (trace_fraction == 1) - return TRUE; - traceline(inflictor.origin, targ.origin + '15 -15 0', TRUE, self); - if (trace_fraction == 1) - return TRUE; - - return FALSE; -} - -float(float v) anglemod; - -void(vector dest) ChooseTurn; - -void() ai_face; - - -float enemy_range; - - -//============================================================================= - -/* -=========== -GenericCheckAttack - -The player is in view, so decide to move or launch an attack -Returns FALSE if movement should continue -============ -*/ -float() GenericCheckAttack = -{ - local vector spot1, spot2; - local entity targ; - local float chance; - - if (self.health < 1) - return FALSE; - targ = self.enemy; - - if (vlen(targ.origin - self.origin) > 5000) // long traces are slow - return FALSE; - -// see if any entities are in the way of the shot - spot1 = self.origin + self.view_ofs; - spot2 = targ.origin + targ.view_ofs; - - traceline (spot1, spot2, FALSE, self); - - if (trace_ent != targ) - return FALSE; // don't have a clear shot - - if (trace_inopen && trace_inwater) - return FALSE; // sight line crossed contents - - if (enemy_range == RANGE_MELEE) - { // melee attack - if (self.th_melee) - { - self.th_melee (); - return TRUE; - } - } - -// missile attack - if (time < ATTACK_FINISHED(self)) - return FALSE; - - if (!self.th_missile) - return FALSE; - - if (enemy_range == RANGE_FAR) - return FALSE; - - if (enemy_range == RANGE_MELEE) - { - chance = 0.9; - ATTACK_FINISHED(self) = 0; - } - else if (enemy_range == RANGE_NEAR) - { - if (self.th_melee) - chance = 0.2; - else - chance = 0.4; - } - else if (enemy_range == RANGE_MID) - { - if (self.th_melee) - chance = 0.05; - else - chance = 0.1; - } - else - chance = 0; - - if (random () < chance) - if (self.th_missile ()) - { - SUB_AttackFinished (2*random()); - return TRUE; - } - - return FALSE; -}; - - -/* -============= -ai_face - -Stay facing the enemy -============= -*/ -void() ai_face = -{ - self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin); - ChangeYaw (); -}; - -/* -============= -ai_charge - -The monster is in a melee attack, so get as close as possible to .enemy -============= -*/ -float (entity targ) visible; -float(entity targ) infront; -float(entity targ) range; - -void(float d) ai_charge = -{ - if (self.health < 1) - return; - ai_face (); - movetogoal (d); // done in C code... -}; - -void() ai_charge_side = -{ - if (self.health < 1) - return; - local vector dtemp; - local float heading; - -// aim to the left of the enemy for a flyby - - self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin); - ChangeYaw (); - - makevectors (self.angles); - dtemp = self.enemy.origin - 30*v_right; - heading = vectoyaw(dtemp - self.origin); - - walkmove(heading, 20); -}; - - -/* -============= -ai_melee - -============= -*/ -void() ai_melee = -{ - local vector delta; - local float ldmg; - - if (self.health < 1) - return; - if (!self.enemy) - return; // removed before stroke - - delta = self.enemy.origin - self.origin; - - if (vlen(delta) > 60) - return; - - ldmg = DMG_KNIGHT_MELEE_BASE + DMG_KNIGHT_MELEE_RANDOM1 * random(); - ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM2 * random(); - ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM3 * random(); - traceline(self.origin, self.enemy.origin, FALSE, self); - - Damage (self.enemy, self, self, ldmg, self.projectiledeathtype, trace_endpos, '0 0 0'); // TODO add force to monster melee attacks? -}; - - -void() ai_melee_side = -{ - local vector delta; - local float ldmg; - - if (self.health < 1) - return; - if (!self.enemy) - return; // removed before stroke - - ai_charge_side(); - - delta = self.enemy.origin - self.origin; - - if (vlen(delta) > 60) - return; - if (!CanDamage (self.enemy, self)) - return; - ldmg = DMG_KNIGHT_MELEE_BASE + DMG_KNIGHT_MELEE_RANDOM1 * random(); - ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM2 * random(); - ldmg = ldmg + DMG_KNIGHT_MELEE_RANDOM3 * random(); - traceline(self.origin, self.enemy.origin, FALSE, self); - Damage (self.enemy, self, self, ldmg, self.projectiledeathtype, trace_endpos, '0 0 0'); -}; - diff --git a/qcsrc/server/monsters/m_monsters.qc b/qcsrc/server/monsters/m_monsters.qc deleted file mode 100644 index dd12e96bcb..0000000000 --- a/qcsrc/server/monsters/m_monsters.qc +++ /dev/null @@ -1,468 +0,0 @@ -/* ALL MONSTERS SHOULD BE 1 0 0 IN COLOR */ - -// name =[framenum, nexttime, nextthink] {code} -// expands to: -// name () -// { -// self.frame=framenum; -// self.nextthink = time + nexttime; -// self.think = nextthink -// <code> -// }; - -.float ismonster; - -.float modelindex2; - -/* -================ -monster_use - -Using a monster makes it angry at the current activator -LordHavoc: using a monster with the spawnflag 'Appear' makes it appear -================ -*/ -void() monster_use = -{ - if (self.enemy) - return; - if (self.health < 1) - return; - if (self.mdl) - if (self.spawnflags & MONSTER_APPEAR) - { - self.nextthink = time + 0.1; - self.spawnflags = self.spawnflags - MONSTER_APPEAR; - self.solid = SOLID_SLIDEBOX; - self.takedamage = DAMAGE_AIM; - //self.movetype = MOVETYPE_STEP; - self.model = self.mdl; - self.mdl = ""; - self.modelindex = self.modelindex2; - self.modelindex2 = 0; - //setorigin(self, self.origin + '0 0 1'); - spawn_tdeath(self.origin, self, self.origin); - return; - } - -#if 0 - if (activator.items & IT_INVISIBILITY) - return; -#endif - if (activator.flags & FL_NOTARGET) - return; - if (activator.classname != "player") - return; - - // delay reaction so if the monster is teleported, its sound is still heard - self.enemy = activator; - self.nextthink = time + 0.1; - self.think = FoundTarget; -}; - -void() monster_appearsetup = -{ - if ((self.spawnflags & MONSTER_APPEAR) == 0) - return; - self.mdl = self.model; - self.modelindex2 = self.modelindex; - self.modelindex = 0; - self.solid = SOLID_NOT; - self.takedamage = DAMAGE_NO; - //self.movetype = MOVETYPE_NONE; - self.nextthink = -1; - self.model = ""; -}; - -/* -================ -monster_setalpha - -Sets relative alpha of monster in skill 4 mode. -================ -*/ -void(float a) monster_setalpha = -{ - if (skill < 4 || self.classname == "monster_hellfish") - { - self.alpha = 1.0; - return; - } - - if (skill >= 5) - { - // randomly forget enemy, this makes monsters randomly return to their normal ghostlike state - if (a == 0) - if (self.enemy) - if (random() < 0.1) - self.enemy = world; - // randomly blink (playing the same alarming sound as if attacking) - if (self.enemy == world) - { - a = 0; - if (time >= 0.3) // don't blink during the init process because it might become permanent - if (random() < 0.005) - { - // blink for an instant, this causes the appear sound, alarming the player as if under attack - sound(self, CHAN_AUTO, "wizard/wsight.wav", 1, ATTN_NORM); - a = 1; - } - } - // if ghosted, become non-solid and immune to damage - if (a <= 0 || self.enemy == world) - { - self.solid = SOLID_NOT; - self.takedamage = DAMAGE_NO; - } - else - { - // if unghosting, make sure we have an enemy, otherwise stay ghosted (even if blinking) so we can't be shot while blinking - if (self.solid != SOLID_SLIDEBOX) - sound(self, CHAN_AUTO, "wizard/wsight.wav", 1, ATTN_NORM); - self.solid = SOLID_SLIDEBOX; - self.takedamage = DAMAGE_AIM; - } - } - self.alpha = SKILL4_MINALPHA + (1 - SKILL4_MINALPHA) * bound(0, a, 1); -}; - -/* -================ -monster_death_use - -When a mosnter dies, it fires all of its targets with the current -enemy as activator. -================ -*/ -void() monster_death_use = -{ -// fall to ground - if (self.flags & FL_FLY) - self.flags = self.flags - FL_FLY; - if (self.flags & FL_SWIM) - self.flags = self.flags - FL_SWIM; - - if (!self.target) - return; - - activator = self.enemy; - SUB_UseTargets (); -}; - - -void() monsterinwall = -{ - local entity e; - if (!autocvar_developer) - return; - // this is handy for level designers, - // puts a spikey ball where the error is... - e = spawn(); - setorigin(e, self.origin); - setmodel (e, "models/ebomb.mdl"); - e.movetype = MOVETYPE_NONE; - e.solid = SOLID_NOT; - e.think = SUB_Null; - e.nextthink = -1; - e.scale = 16; -}; - -//============================================================================ - -void() walkmonster_start_go = -{ - self.origin_z = self.origin_z + 1; // raise off floor a bit - - tracebox(self.origin, self.mins, self.maxs, self.origin, TRUE, self); - if (trace_startsolid) - { - dprint("walkmonster in wall at: "); - dprint(vtos(self.origin)); - dprint("\n"); - monsterinwall(); - droptofloor(); - } - else - { - droptofloor(); - if (!walkmove(0,0)) - { - dprint("walkmonster in wall at: "); - dprint(vtos(self.origin)); - dprint("\n"); - monsterinwall(); - } - } - - //self.cantrigger = TRUE; - - self.takedamage = DAMAGE_AIM; - - self.ideal_yaw = self.angles * '0 1 0'; - if (!self.yaw_speed) - self.yaw_speed = 20; - self.view_ofs = '0 0 25'; - self.use = monster_use; - - self.flags = self.flags | FL_MONSTER; - - if (monsterwander) - self.spawnflags = self.spawnflags | MONSTER_WANDER; - - if (self.target) - { - self.goalentity = self.movetarget = find(world, targetname, self.target); - self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin); - if (!self.movetarget) - { - dprint("Monster can't find target at "); - dprint(vtos(self.origin)); - dprint("\n"); - } - // this used to be an objerror - if (self.movetarget.classname == "path_corner") - self.th_walk (); - else - { - if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp")) - { - monster_spawnwanderpath(); - self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin); - self.th_walk (); - } - else - { - self.pausetime = 99999999; - self.th_stand (); - } - } - } - else - { - if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp")) - { - monster_spawnwanderpath(); - self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin); - self.th_walk (); - } - else - { - self.pausetime = 99999999; - self.th_stand (); - } - } - -// spread think times so they don't all happen at same time - self.nextthink = self.nextthink + random()*0.5 + 0.1; - self.iscreature = TRUE; - - force_retouch = 2; // mainly to detect teleports - - monster_appearsetup(); -}; - - -void() walkmonster_start = -{ - self.candrown = 1; // this is turned off by some monsters like zombies - // delay drop to floor to make sure all doors have been spawned - // spread think times so they don't all happen at same time - self.nextthink = time + random()*0.5 + 0.3; - self.think = walkmonster_start_go; - total_monsters = total_monsters + 1; - self.bot_attack = TRUE; - self.frags = 2; // actually just used to get havocbots to attack it... - self.bleedfunc = genericbleedfunc; - self.ismonster = TRUE; - - monster_setalpha (0); -}; - - - -void() flymonster_start_go = -{ - self.takedamage = DAMAGE_AIM; - - self.ideal_yaw = self.angles * '0 1 0'; - if (!self.yaw_speed) - self.yaw_speed = 10; - self.view_ofs = '0 0 25'; - self.use = monster_use; - - self.flags = self.flags | FL_FLY; - self.flags = self.flags | FL_MONSTER; - - if (!walkmove(0,0)) - { - dprint("flymonster in wall at: "); - dprint(vtos(self.origin)); - dprint("\n"); - monsterinwall(); - } - - //self.cantrigger = TRUE; - - if (monsterwander) - self.spawnflags = self.spawnflags | MONSTER_WANDER; - - if (self.target) - { - self.goalentity = self.movetarget = find(world, targetname, self.target); - if (!self.movetarget) - { - dprint("Monster can't find target at "); - dprint(vtos(self.origin)); - dprint("\n"); - } - // this used to be an objerror - if (self.movetarget.classname == "path_corner") - self.th_walk (); - else - { - if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp")) - { - monster_spawnwanderpath(); - self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin); - self.th_walk (); - } - else - { - self.pausetime = 99999999; - self.th_stand (); - } - } - } - else - { - if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp")) - { - monster_spawnwanderpath(); - self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin); - self.th_walk (); - } - else - { - self.pausetime = 99999999; - self.th_stand (); - } - } - self.iscreature = TRUE; - - force_retouch = 2; // mainly to detect teleports - - monster_appearsetup(); -}; - -void() flymonster_start = -{ - self.candrown = 1; - // spread think times so they don't all happen at same time - self.nextthink = time + random()*0.5 + 0.1; - self.think = flymonster_start_go; - total_monsters = total_monsters + 1; - self.bot_attack = TRUE; - self.frags = 2; // actually just used to get havocbots to attack it... - self.bleedfunc = genericbleedfunc; - self.ismonster = TRUE; - - monster_setalpha (0); -}; - - -void() swimmonster_start_go = -{ - if (deathmatch) - { - remove(self); - return; - } - - //self.cantrigger = TRUE; - - self.takedamage = DAMAGE_AIM; - - self.ideal_yaw = self.angles * '0 1 0'; - if (!self.yaw_speed) - self.yaw_speed = 10; - self.view_ofs = '0 0 10'; - self.use = monster_use; - - self.flags = self.flags | FL_SWIM; - self.flags = self.flags | FL_MONSTER; - - if (monsterwander) - self.spawnflags = self.spawnflags | MONSTER_WANDER; - - if (self.target) - { - self.goalentity = self.movetarget = find(world, targetname, self.target); - if (!self.movetarget) - { - dprint("Monster can't find target at "); - dprint(vtos(self.origin)); - dprint("\n"); - } - // this used to be an objerror - if (self.movetarget.classname == "path_corner") - self.th_walk (); - else - { - if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp")) - { - monster_spawnwanderpath(); - self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin); - self.th_walk (); - } - else - { - self.pausetime = 99999999; - self.th_stand (); - } - } - } - else - { - if ((self.spawnflags & MONSTER_WANDER) && (!self.monsterawaitingteleport) && (self.spawnflags & 3) == 0 && (world.model != "maps/e1m7.bsp")) - { - monster_spawnwanderpath(); - self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin); - self.th_walk (); - } - else - { - self.pausetime = 99999999; - self.th_stand (); - } - } - self.iscreature = TRUE; - - force_retouch = 2; // mainly to detect teleports - - monster_appearsetup(); -}; - -void() swimmonster_start = -{ - // spread think times so they don't all happen at same time - self.candrown = 0; - self.nextthink = time + random()*0.5 + 0.1; - self.think = swimmonster_start_go; - total_monsters = total_monsters + 1; - self.bot_attack = TRUE; - self.frags = 2; // actually just used to get havocbots to attack it... - self.bleedfunc = genericbleedfunc; - self.ismonster = TRUE; - - monster_setalpha(0); -}; - -void(vector org, float bodydamage, float armordamage, vector force, float damgtype) genericbleedfunc = -{ - local vector v; - v = '0 0 0' - force * 0.05; - if (armordamage > 0) - te_spark(org, v, armordamage * 3); - if (bodydamage > 0) - te_blood(org, v, bodydamage); -} diff --git a/qcsrc/server/monsters/monster_zombie.qc b/qcsrc/server/monsters/monster_zombie.qc deleted file mode 100644 index 2973dee97c..0000000000 --- a/qcsrc/server/monsters/monster_zombie.qc +++ /dev/null @@ -1,555 +0,0 @@ -//#define MONSTES_ENABLED -#ifdef MONSTES_ENABLED - -#define zombie_anim_attackleap 0 -#define zombie_anim_attackrun1 1 -#define zombie_anim_attackrun2 2 -#define zombie_anim_attackrun3 3 -#define zombie_anim_attackstanding1 4 -#define zombie_anim_attackstanding2 5 -#define zombie_anim_attackstanding3 6 -#define zombie_anim_blockend 7 -#define zombie_anim_blockstart 8 -#define zombie_anim_deathback1 9 -#define zombie_anim_deathback2 10 -#define zombie_anim_deathback3 11 -#define zombie_anim_deathfront1 12 -#define zombie_anim_deathfront2 13 -#define zombie_anim_deathfront3 14 -#define zombie_anim_deathleft1 15 -#define zombie_anim_deathleft2 16 -#define zombie_anim_deathright1 17 -#define zombie_anim_deathright2 18 -#define zombie_anim_idle 19 -#define zombie_anim_painback1 20 -#define zombie_anim_painback2 21 -#define zombie_anim_painfront1 22 -#define zombie_anim_painfront2 23 -#define zombie_anim_runbackwards 24 -#define zombie_anim_runbackwardsleft 25 -#define zombie_anim_runbackwardsright 26 -#define zombie_anim_runforward 27 -#define zombie_anim_runforwardleft 28 -#define zombie_anim_runforwardright 29 -#define zombie_anim_spawn 30 - -#define ZOMBIE_MIN '-18 -18 -25' -#define ZOMBIE_MAX '18 18 47' - -#define ZV_IDLE 10 - -#define ZV_PATH 100 -#define ZV_HUNT 200 - -#define ZV_ATTACK_FIND 10 -#define ZV_ATTACK_RUN 20 -#define ZV_ATTACK_STAND 30 - -#define ZV_PATH2 10000 - -//.entity verbs_idle; -//.entity verbs_attack; -//.entity verbs_move; - -//.float state_timeout; -//.void() monster_state; -#define MONSTERFLAG_NORESPAWN 2 - -void zombie_spawn(); - -float zombie_scoretarget(entity trg) -{ - float tmp; - vector ang1; - - if (trg.takedamage == DAMAGE_AIM) - if not (trg.flags & FL_NOTARGET) - if (trg.deadflag == DEAD_NO) - if (trg.team != self.team) - { - if((self.origin_z - trg.origin_z) < 128) - { - ang1 = normalize(self.origin - trg.origin); - tmp = vlen(ang1 - v_forward); - if(tmp > 1.5) - { - traceline(self.origin + '0 0 47',trg.origin + '0 0 32',MOVE_NORMAL,self); - if(trace_ent != trg) - return 0; - - return (autocvar_g_monster_zombie_targetrange - vlen(self.origin - trg.origin)) * tmp; - } - else if(self.enemy == trg) - return (autocvar_g_monster_zombie_targetrange - vlen(self.origin - trg.origin)) * tmp; - } - } - - return 0; -} - -void zombie_corpse_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) -{ - //dprint("zombie_corpse_damage\n"); - Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker); - - self.health -= damage; - - if(self.health < 0) - { - Violence_GibSplash(self, 1, 1, attacker); - remove(self); - } -} - -void zombie_die(vector dir) -{ - vector v; - float f; - - entity dummy; - - dummy = spawn(); - setmodel(dummy,"models/monsters/zombie.dpm"); - setorigin(dummy, self.origin); - dummy.velocity = self.velocity; - dummy.movetype = MOVETYPE_BOUNCE; - dummy.think = SUB_Remove; - dummy.nextthink = time + 3; - dummy.health = 50; - dummy.takedamage = DAMAGE_YES; - dummy.event_damage = zombie_corpse_damage; - dummy.solid = SOLID_CORPSE; - setsize(dummy,self.mins,self.maxs); - - SUB_SetFade(dummy,time + 5,2); - - - v = normalize(self.origin - dir); - f = vlen(v_forward - v) - 1; - if(f > 0.5) - dummy.frame = zombie_anim_deathfront1 + rint(random() * 2); - else if(f < 0.5) - dummy.frame = zombie_anim_deathback1 + rint(random() * 2); - else - { - f = vlen(v_right - v) - 1; - if(f > 0.5) - dummy.frame = zombie_anim_deathright1 + rint(random() * 2); - else if(f < 0.5) - dummy.frame = zombie_anim_deathleft1 + rint(random() * 2); - } - - - if(self.spawnflags & MONSTERFLAG_NORESPAWN) - { - self.think = SUB_Remove; - self.nextthink = time; - return; - } - - setmodel(self,""); - self.solid = SOLID_NOT; - self.takedamage = DAMAGE_NO; - self.event_damage = SUB_Null; - self.enemy = world; - self.think = zombie_spawn; - self.nextthink = time + autocvar_g_monster_zombie_respawntime; - self.pain_finished = self.nextthink; -} - -void zombie_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) -{ - - vector v; - float f; - - v = normalize(self.origin - hitloc); - f = vlen(v_forward - v) - 1; - - - self.health -= damage; - self.velocity = self.velocity + force; - if(self.health <= 0) - { - zombie_die(hitloc); - return; - } - - Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker); - - if (damage > 50) - Violence_GibSplash_At(hitloc, force * -0.1, 3, 1, self, attacker); - if (damage > 100) - Violence_GibSplash_At(hitloc, force * -0.2, 3, 1, self, attacker); - - if (time > self.pain_finished) - { - if(f < 0.5) - { - if(random() < 0.5) - self.frame = zombie_anim_painback1; - else - self.frame = zombie_anim_painback2; - } - else - { - if(random() < 0.5) - self.frame = zombie_anim_painfront1; - else - self.frame = zombie_anim_painfront2; - } - - self.pain_finished = time + 0.36; - } -} - -.vector bvec; -.float bvec_time; - -void zombie_move() -{ - vector real_angle; - float vz, tdiff, tspeed; - - tdiff = time - self.zoomstate; - tspeed = tdiff * autocvar_g_monster_zombie_turnspeed; - vz = self.velocity_z; - self.zoomstate = time; - - if(self.bvec_time < time) - { - self.bvec_time = time + 0.2; - self.bvec = steerlib_beamsteer(steerlib_attract2(self.moveto,0.5,500,0.95),512,32,34,64); - } - - if(self.enemy) - self.moveto = self.enemy.origin; - else - self.moveto = self.origin + v_forward; - - self.steerto = normalize(steerlib_attract2(self.moveto,0.5,500,0.95) + self.bvec); - - self.angles_y = safeangle(self.angles_y); - real_angle = vectoangles(self.steerto) - self.angles; - self.angles_y += bound(-10, real_angle_y, 10); - - if(vlen(self.origin - self.moveto) > 64) - { - movelib_move_simple(v_forward ,autocvar_g_monster_zombie_movespeed,0.6); - if(time > self.pain_finished) - if(self.attack_finished_single < time) - self.frame = zombie_anim_runforward; - } - else - { - movelib_beak_simple(autocvar_g_monster_zombie_stopspeed); - if(time > self.pain_finished) - if(self.attack_finished_single < time) - self.frame = zombie_anim_idle; - } - - self.velocity_z = vz; - self.steerto = self.origin; -} - -float zombie_verb_idle_roam(float eval) -{ - switch (eval) - { - case VCM_EVAL: - - if(self.enemy) - return VS_CALL_NO; - - return verb.verb_static_value; - - case VCM_DO: - - self.moveto = v_forward * 128; - self.steerto = v_forward; //steerlib_beamsteer(v_forward,512,32,34,64); - - return VS_CALL_YES_DOING; - } - - return VS_CALL_YES_DONE; -} - -float zombie_verb_idle_stand(float eval) -{ - switch (eval) - { - case VCM_EVAL: - - if(self.enemy) - return VS_CALL_NO; - - return verb.verb_static_value; - - case VCM_DO: - - self.moveto = self.origin; - self.frame = zombie_anim_idle; - self.velocity = '0 0 0'; - - return VS_CALL_YES_DOING; - } - - return VS_CALL_YES_DONE; -} - -float zombie_verb_idle(float eval) -{ - switch (eval) - { - case VCM_EVAL: - - if(self.enemy) - return VS_CALL_NO; - - return verb.verb_static_value; - - case VCM_DO: - float t; - - t = autocvar_g_monster_zombie_idle_timer_max - autocvar_g_monster_zombie_idle_timer_min; - t = autocvar_g_monster_zombie_idle_timer_min + (random() * t); - - if(random() < 0.5) - verbstack_push(self.verbs_idle, zombie_verb_idle_roam, ZV_IDLE + 1, t, self); - else - verbstack_push(self.verbs_idle, zombie_verb_idle_stand, ZV_IDLE + 1, 0.1, self); - - return VS_CALL_YES_DOING; - } - - return VS_CALL_YES_DONE; -} - -float zombie_verb_attack_findtarget(float eval) -{ - switch (eval) - { - case VCM_EVAL: - if(self.enemy) - return VS_CALL_NO; - - return verb.verb_static_value; - - case VCM_DO: - - entity trg, best_trg; - float trg_score, best_trg_score; - - trg = findradius(self.origin,autocvar_g_monster_zombie_targetrange); - while(trg) - { - trg_score = zombie_scoretarget(trg); - if(trg_score > best_trg_score) - { - best_trg = trg; - best_trg_score = trg_score; - } - - trg = trg.chain; - } - - if(best_trg) - { - self.enemy = best_trg; - dprint("Selected: ",best_trg.netname, " as target.\n"); - } - - return VS_CALL_YES_DOING; - } - - return VS_CALL_YES_DONE; -} - -void zombie_runattack_damage() -{ - entity oldself; - oldself = self; - self = self.owner; - - if(vlen(self.origin - self.enemy.origin) > autocvar_g_monster_zombie_attack_run_hitrange) - return; - - if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6) - return; - - Damage(self.enemy, self, self, autocvar_g_monster_zombie_attack_run_damage, DEATH_TURRET, self.enemy.origin, normalize(self.enemy.origin - self.origin) * autocvar_g_monster_zombie_attack_run_force); - - self = oldself; - self.think = SUB_Remove; - self.nextthink = time; -} - -float zombie_verb_attack_run(float eval) -{ - switch (eval) - { - case VCM_EVAL: - if not (self.enemy) - return VS_CALL_NO; - - if(self.attack_finished_single > time) - return VS_CALL_NO; - - if(vlen(self.origin - self.enemy.origin) > autocvar_g_monster_zombie_attack_run_range) - return VS_CALL_NO; - - if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6) - return VS_CALL_NO; - - return verb.verb_static_value; - - case VCM_DO: - entity pain; - pain = spawn(); - pain.owner = self; - pain.think = zombie_runattack_damage; - pain.nextthink = time + autocvar_g_monster_zombie_attack_run_delay; - - self.attack_finished_single = time + 0.7; - self.frame = zombie_anim_attackrun1 + rint(random() * 2); - - return VS_CALL_YES_DOING; - } - - return VS_CALL_YES_DONE; -} - -void zombie_standattack_damage() -{ - //entity oldself; - //oldself = self; - //self = self.owner; - - setorigin(self,self.owner.origin + v_forward * 32); - RadiusDamage(self, self.owner, autocvar_g_monster_zombie_attack_stand_damage,autocvar_g_monster_zombie_attack_stand_damage,16,self, autocvar_g_monster_zombie_attack_stand_force,DEATH_TURRET,world); - //float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity ignore, float forceintensity, float deathtype, entity directhitentity) - - - //self = oldself; - self.think = SUB_Remove; - self.nextthink = time; -} - -float zombie_verb_attack_stand(float eval) -{ - switch (eval) - { - case VCM_EVAL: - if not (self.enemy) - return VS_CALL_NO; - - if(self.attack_finished_single > time) - return VS_CALL_NO; - - if(vlen(self.origin - self.enemy.origin) > autocvar_g_monster_zombie_attack_stand_range) - return VS_CALL_NO; - - if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.8) - return VS_CALL_NO; - - return verb.verb_static_value; - - case VCM_DO: - entity pain; - pain = spawn(); - pain.owner = self; - pain.think = zombie_runattack_damage; - pain.nextthink = time + autocvar_g_monster_zombie_attack_stand_delay; - - self.attack_finished_single = time + 0.7; - self.frame = zombie_anim_attackstanding1 + rint(random() * 1); - dprint("frame:",ftos(self.frame),"\n"); - - return VS_CALL_YES_DOING; - } - - return VS_CALL_YES_DONE; -} - -void zombie_think() -{ - self.angles_x *= -1; - makevectors(self.angles); - self.angles_x *= -1; - - if (zombie_scoretarget(self.enemy) == 0) - self.enemy = world; - - verbstack_pop(self.verbs_attack); - //verbstack_pop(self.verbs_move); - - if not (self.enemy) - verbstack_pop(self.verbs_idle); - - zombie_move(); - - if(self.enemy) - self.nextthink = time; - else - self.nextthink = time + 0.2; -} - -void zombie_spawn() -{ - setmodel(self,"models/monsters/zombie.dpm"); - - self.solid = SOLID_BBOX; - self.takedamage = DAMAGE_AIM; - self.event_damage = zombie_damage; - self.enemy = world; - self.frame = zombie_anim_spawn; - self.think = zombie_think; - self.nextthink = time + 2.1; - self.pain_finished = self.nextthink; - self.movetype = MOVETYPE_WALK; - self.health = autocvar_g_monster_zombie_health; - self.velocity = '0 0 0'; - self.angles = self.pos2; - self.moveto = self.origin; - self.flags = FL_MONSTER; - - setorigin(self,self.pos1); - setsize(self,ZOMBIE_MIN,ZOMBIE_MAX); -} - - -void spawnfunc_monster_zombie() -{ - if not(autocvar_g_monsters) - { - remove(self); - return; - } - - precache_model("models/monsters/zombie.dpm"); - - - self.verbs_idle = spawn(); - self.verbs_attack = spawn(); - - self.verbs_idle.owner = self; - self.verbs_attack.owner = self; - - self.think = zombie_spawn; - self.nextthink = time + 2; - - traceline(self.origin + '0 0 10', self.origin - '0 0 32', MOVE_WORLDONLY, self); - - self.pos1 = trace_endpos; - self.pos2 = self.angles; - self.team = MAX_SHOT_DISTANCE -1; - - verbstack_push(self.verbs_idle, zombie_verb_idle, ZV_IDLE,0 , self); - - verbstack_push(self.verbs_attack, zombie_verb_attack_findtarget, ZV_ATTACK_FIND,0 , self); - verbstack_push(self.verbs_attack, zombie_verb_attack_run, ZV_ATTACK_RUN,0 , self); - verbstack_push(self.verbs_attack, zombie_verb_attack_stand, ZV_ATTACK_STAND,0 , self); - -} - -#endif // MONSTES_ENABLED diff --git a/qcsrc/server/movelib.qc b/qcsrc/server/movelib.qc index 89feff9a49..8a6235127c 100644 --- a/qcsrc/server/movelib.qc +++ b/qcsrc/server/movelib.qc @@ -1,3 +1,4 @@ +#ifdef SVQC .vector moveto; /** @@ -161,10 +162,14 @@ void movelib_update(vector dir,float force) } */ +/* void movelib_move_simple(vector newdir,float velo,float blendrate) { self.velocity = self.velocity * (1 - blendrate) + (newdir * blendrate) * velo; } +*/ +#define movelib_move_simple(newdir,velo,blendrate) \ + self.velocity = self.velocity * (1 - blendrate) + (newdir * blendrate) * velo void movelib_beak_simple(float force) { @@ -183,6 +188,8 @@ void movelib_beak_simple(float force) Pitches and rolls the entity to match the gound. Yed need to set v_up and v_forward (generally by calling makevectors) before calling this. **/ +#endif + void movelib_groundalign4point(float spring_length, float spring_up, float blendrate) { vector a, b, c, d, e, r, push_angle, ahead, side; diff --git a/qcsrc/server/mutators/base.qc b/qcsrc/server/mutators/base.qc index 0b1bea45ed..fdf24edb75 100644 --- a/qcsrc/server/mutators/base.qc +++ b/qcsrc/server/mutators/base.qc @@ -83,23 +83,55 @@ float CallbackChain_Call(entity cb) entity e; r = 0; for(e = cb; e.cbc_next; e = e.cbc_next) + { + CallbackChain_ReturnValue = r; r |= e.cbc_next.cbc_func(); + } return r; // callbacks return an error status, so 0 is default return value } -float Mutator_Add(float(float) func) +#define MAX_MUTATORS 8 +string loaded_mutators[MAX_MUTATORS]; +float Mutator_Add(mutatorfunc_t func, string name) { + float i, j; + j = -1; + for(i = 0; i < MAX_MUTATORS; ++i) + { + if(name == loaded_mutators[i]) + return 1; // already added + if(!loaded_mutators[i]) + j = i; + } + if(j < 0) + { + backtrace("WARNING: too many mutators, cannot add any more\n"); + return 0; + } + loaded_mutators[j] = name; + if(func(MUTATOR_ADDING) == 0) { // good return 1; } backtrace("WARNING: when adding mutator: adding failed\n"); - Mutator_Remove(func); + Mutator_Remove(func, name); return 0; } -void Mutator_Remove(float(float) func) +void Mutator_Remove(float(float) func, string name) { + float i; + for(i = 0; i < MAX_MUTATORS; ++i) + if(name == loaded_mutators[i]) + break; + if(i >= MAX_MUTATORS) + { + backtrace("WARNING: removing not-added mutator\n"); + return; + } + loaded_mutators[i] = string_null; + if(func(MUTATOR_REMOVING) != 0) { // baaaaad diff --git a/qcsrc/server/mutators/base.qh b/qcsrc/server/mutators/base.qh index b7c523dcbb..ecec3c87c5 100644 --- a/qcsrc/server/mutators/base.qh +++ b/qcsrc/server/mutators/base.qh @@ -3,6 +3,8 @@ #define CBC_ORDER_LAST 2 #define CBC_ORDER_ANY 4 +float CallbackChain_ReturnValue; // read-only field of the current return value + entity CallbackChain_New(string name); float CallbackChain_Add(entity cb, float() func, float order) float CallbackChain_Remove(entity cb, float() func); @@ -16,11 +18,12 @@ float CallbackChain_Call(entity cb); #define MUTATOR_REMOVING 0 #define MUTATOR_ADDING 1 -float Mutator_Add(float(float) func); -void Mutator_Remove(float(float) func); // calls error() on fail +typedef float(float) mutatorfunc_t; +float Mutator_Add(mutatorfunc_t func, string name); +void Mutator_Remove(mutatorfunc_t func, string name); // calls error() on fail -#define MUTATOR_ADD(name) Mutator_Add(MUTATOR_##name) -#define MUTATOR_REMOVE(name) Mutator_Remove(MUTATOR_##name) +#define MUTATOR_ADD(name) Mutator_Add(MUTATOR_##name, #name) +#define MUTATOR_REMOVE(name) Mutator_Remove(MUTATOR_##name, #name) #define MUTATOR_DEFINITION(name) float MUTATOR_##name(float mode) #define MUTATOR_DECLARATION(name) float MUTATOR_##name(float mode) #define MUTATOR_HOOKFUNCTION(name) float HOOKFUNCTION_##name() @@ -31,6 +34,7 @@ void Mutator_Remove(float(float) func); // calls error() on fail #define MUTATOR_HOOKABLE(cb) entity HOOK_##cb #define MUTATOR_CALLHOOK(cb) CallbackChain_Call(HOOK_##cb) +#define MUTATOR_RETURNVALUE CallbackChain_ReturnValue @@ -41,6 +45,7 @@ MUTATOR_HOOKABLE(MakePlayerObserver); // called when a player becomes observer, after shared setup MUTATOR_HOOKABLE(PlayerSpawn); + entity spawn_spot; // spot that was used, or world // called when a player spawns as player, after shared setup, before his weapon is chosen (so items may be changed in here) MUTATOR_HOOKABLE(ClientDisconnect); @@ -94,6 +99,10 @@ MUTATOR_HOOKABLE(FilterItem); // checks if the current item may be spawned (self.items and self.weapons may be read and written to, as well as the ammo_ fields) // return error to request removal +MUTATOR_HOOKABLE(TurretSpawn); + // return error to request removal + // INPUT: self - turret + MUTATOR_HOOKABLE(OnEntityPreSpawn); // return error to prevent entity spawn, or modify the entity @@ -146,3 +155,49 @@ MUTATOR_HOOKABLE(PlayerPowerups); // INPUT entity self; float olditems; // also technically output, but since it is at the end of the function it's useless for that :P + +MUTATOR_HOOKABLE(PlayerUseKey); + // called when the use key is pressed + // if MUTATOR_RETURNVALUE is 1, don't do anything + // return 1 if the use key actually did something + +MUTATOR_HOOKABLE(SV_ParseClientCommand); + // called when a client command is parsed + // NOTE: hooks MUST start with if(MUTATOR_RETURNVALUE) return 0; + // NOTE: return 1 if you handled the command, return 0 to continue handling + // NOTE: THESE HOOKS MUST NEVER EVER CALL tokenize() + // INPUT + string cmd_name; // command name + float cmd_argc; // also, argv() can be used + string cmd_string; // whole command, use only if you really have to + /* + // example: + MUTATOR_HOOKFUNCTION(foo_SV_ParseClientCommand) + { + if(MUTATOR_RETURNVALUE) // command was already handled? + return 0; + if(cmd_name == "echocvar" && cmd_argc >= 2) + { + print(cvar_string(argv(1)), "\n"); + return 1; + } + if(cmd_name == "echostring" && cmd_argc >= 2) + { + print(substring(cmd_string, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)), "\n"); + return 1; + } + return 0; + } + */ + +MUTATOR_HOOKABLE(Spawn_Score); + // called when a spawnpoint is being evaluated + // return 1 to make the spawnpoint unusable + // INPUT + entity self; // player wanting to spawn + entity spawn_spot; // spot to be evaluated + // IN+OUT + vector spawn_score; // _x is priority, _y is "distance" + +MUTATOR_HOOKABLE(SV_StartFrame); + // runs globally each server frame diff --git a/qcsrc/server/mutators/gamemode_freezetag.qc b/qcsrc/server/mutators/gamemode_freezetag.qc index a1cc9deb6c..d2c741f0b4 100644 --- a/qcsrc/server/mutators/gamemode_freezetag.qc +++ b/qcsrc/server/mutators/gamemode_freezetag.qc @@ -2,6 +2,7 @@ void freezetag_Initialize() { precache_model("models/ice/ice.md3"); warmup = time + autocvar_g_start_delay + autocvar_g_freezetag_warmup; + ScoreRules_freezetag(); } void freezetag_CheckWinner() @@ -22,6 +23,7 @@ void freezetag_CheckWinner() entity e, winner; string teamname; + winner = world; FOR_EACH_PLAYER(e) { @@ -34,7 +36,6 @@ void freezetag_CheckWinner() if(winner != world) // just in case a winner wasn't found { - TeamScore_AddToTeam(winner.team, ST_SCORE, +1); if(winner.team == COLOR_TEAM1) teamname = "^1Red Team"; else if(winner.team == COLOR_TEAM2) @@ -47,20 +48,28 @@ void freezetag_CheckWinner() centerprint(e, strcat(teamname, "^5 wins the round, all other teams were frozen.\n")); } bprint(teamname, "^5 wins the round since all the other teams were frozen.\n"); + TeamScore_AddToTeam(winner.team, ST_SCORE, +1); } next_round = time + 5; } +// this is needed to allow the player to turn his view around (fixangle can't +// be used to freeze his view, as that also changes the angles), while not +// turning that ice object with the player void freezetag_Ice_Think() { setorigin(self, self.owner.origin - '0 0 16'); self.nextthink = time; } -void freezetag_Freeze() +void freezetag_Freeze(entity attacker) { + if(self.freezetag_frozen) + return; self.freezetag_frozen = 1; + self.freezetag_revive_progress = 0; + self.health = 1; entity ice; ice = spawn(); @@ -71,19 +80,41 @@ void freezetag_Freeze() ice.frame = floor(random() * 21); // ice model has 20 different looking frames setmodel(ice, "models/ice/ice.md3"); - self.movement = '0 0 0'; + entity oldself; + oldself = self; + self = ice; + freezetag_Ice_Think(); + self = oldself; + + RemoveGrapplingHook(self); // add waypoint - WaypointSprite_Spawn("freezetag_frozen", 0, 0, self, '0 0 64', world, self.team, self, waypointsprite_attached, TRUE); - if(self.waypointsprite_attached) + WaypointSprite_Spawn("freezetag_frozen", 0, 0, self, '0 0 64', world, self.team, self, waypointsprite_attached, TRUE, RADARICON_WAYPOINT, '0.25 0.90 1'); + + if(attacker == self) { - WaypointSprite_UpdateTeamRadar(self.waypointsprite_attached, RADARICON_WAYPOINT, '0.25 0.90 1'); + // you froze your own dumb self + // counted as "suicide" already + PlayerScore_Add(self, SP_SCORE, -1); + } + else if(attacker.classname == "player") + { + // got frozen by an enemy + // counted as "kill" and "death" already + PlayerScore_Add(self, SP_SCORE, -1); + PlayerScore_Add(attacker, SP_SCORE, +1); + } + else + { + // nothing - got frozen by the game type rules themselves } } -void freezetag_Unfreeze() +void freezetag_Unfreeze(entity attacker) { self.freezetag_frozen = 0; + self.freezetag_revive_progress = 0; + self.health = autocvar_g_balance_health_start; // remove the ice block entity ice; @@ -113,10 +144,10 @@ MUTATOR_HOOKFUNCTION(freezetag_RemovePlayer) --totalalive; } - if(totalspawned > 2) // only check for winners if we had more than two players (one of them left, don't let the other player win just because of that) + if(total_players > 2) // only check for winners if we had more than two players (one of them left, don't let the other player win just because of that) freezetag_CheckWinner(); - freezetag_Unfreeze(); + freezetag_Unfreeze(world); return 1; } @@ -135,7 +166,7 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerDies) --pinkalive; --totalalive; - freezetag_Freeze(); + freezetag_Freeze(frag_attacker); } if(frag_attacker.classname == STR_PLAYER) @@ -154,7 +185,7 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerDies) bprint("^7", frag_target.netname, "^1 was frozen by ^7", frag_attacker.netname, ".\n"); } - frag_target.health = autocvar_g_balance_health_start; // "respawn" the player :P + frag_target.health = 1; // "respawn" the player :P freezetag_CheckWinner(); @@ -163,9 +194,9 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerDies) MUTATOR_HOOKFUNCTION(freezetag_PlayerSpawn) { - freezetag_Unfreeze(); // start by making sure that all ice blocks are removed + freezetag_Unfreeze(world); // start by making sure that all ice blocks are removed - if(totalspawned == 1 && time > game_starttime) // only one player active on server, start a new match immediately + if(total_players == 1 && time > game_starttime) // only one player active on server, start a new match immediately if(!next_round && warmup && (time < warmup - autocvar_g_freezetag_warmup || time > warmup)) // not awaiting next round { next_round = time; @@ -174,7 +205,7 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerSpawn) if(warmup && time > warmup) // spawn too late, freeze player { centerprint(self, "^1You spawned after the round started, you'll spawn as frozen.\n"); - freezetag_Freeze(); + freezetag_Freeze(world); } return 1; @@ -188,64 +219,88 @@ MUTATOR_HOOKFUNCTION(freezetag_GiveFragsForKill) MUTATOR_HOOKFUNCTION(freezetag_PlayerPreThink) { - vector revive_extra_size; - revive_extra_size = '1 1 1' * autocvar_g_freezetag_revive_extra_size; + float n; + vector revive_extra_size; - float teammate_nearby; - FOR_EACH_PLAYER(other) if(self != other) - { - if(other.freezetag_frozen == 0) - { - if(other.team == self.team) - { - teammate_nearby = boxesoverlap(self.absmin - revive_extra_size, self.absmax + revive_extra_size, other.absmin, other.absmax); - if(teammate_nearby) - break; - } - } - } + revive_extra_size = '1 1 1' * autocvar_g_freezetag_revive_extra_size; - if(teammate_nearby && self.freezetag_frozen == 1) // OK, there is at least one teammate reviving us - { - if(self.freezetag_beginrevive_time == -9999) // initialize values if this is the first frame of revival - { - self.freezetag_beginrevive_time = time; - self.freezetag_revive_progress = 0; - } - else - { - self.freezetag_revive_progress = (time - self.freezetag_beginrevive_time) / autocvar_g_freezetag_revive_time; - if(time - self.freezetag_beginrevive_time >= autocvar_g_freezetag_revive_time) - { - freezetag_Unfreeze(); - - centerprint(self, strcat("^5You were revived by ^7", other.netname, ".\n")); - centerprint(other, strcat("^5You revived ^7", self.netname, ".\n")); - bprint("^7", other.netname, "^5 revived ^7", self.netname, ".\n"); - - self.freezetag_beginrevive_time = -9999; - self.freezetag_revive_progress = 0; - } - } - // now find EVERY teammate within reviving radius, set their revive_progress values correct - FOR_EACH_PLAYER(other) if(self != other) - { - if(other.freezetag_frozen == 0) - { - if(other.team == self.team) - { - teammate_nearby = boxesoverlap(self.absmin - revive_extra_size, self.absmax + revive_extra_size, other.absmin, other.absmax); - if(teammate_nearby) - other.freezetag_revive_progress = self.freezetag_revive_progress; - } - } - } - } - else if(!teammate_nearby) // only if no teammate is nearby will we reset - { - self.freezetag_beginrevive_time = -9999; - self.freezetag_revive_progress = 0; - } + entity o; + o = world; + n = 0; + FOR_EACH_PLAYER(other) if(self != other) + { + if(other.freezetag_frozen == 0) + { + if(other.team == self.team) + { + if(boxesoverlap(self.absmin - revive_extra_size, self.absmax + revive_extra_size, other.absmin, other.absmax)) + { + if(!o) + o = other; + ++n; + } + } + } + } + + if(n && self.freezetag_frozen) // OK, there is at least one teammate reviving us + { + self.freezetag_revive_progress = bound(0, self.freezetag_revive_progress + frametime * autocvar_g_freezetag_revive_speed, 1); + self.health = max(1, self.freezetag_revive_progress * autocvar_g_balance_health_start); + + if(self.freezetag_revive_progress >= 1) + { + freezetag_Unfreeze(self); + + // EVERY team mate nearby gets a point (even if multiple!) + FOR_EACH_PLAYER(other) if(self != other) + { + if(other.freezetag_frozen == 0) + { + if(other.team == self.team) + { + if(boxesoverlap(self.absmin - revive_extra_size, self.absmax + revive_extra_size, other.absmin, other.absmax)) + { + PlayerScore_Add(other, SP_FREEZETAG_REVIVALS, +1); + PlayerScore_Add(other, SP_SCORE, +1); + } + } + } + } + + if(n > 1) + centerprint(self, strcat("^5You were revived by ^7", o.netname, "^5 et al.\n")); + else + centerprint(self, strcat("^5You were revived by ^7", o.netname, "^5.\n")); + centerprint(o, strcat("^5You revived ^7", self.netname, "^5.\n")); + if(n > 1) + bprint("^7", o.netname, "^5 et al revived ^7", self.netname, "^5.\n"); + else + bprint("^7", o.netname, "^5 revived ^7", self.netname, "^5.\n"); + } + + // now find EVERY teammate within reviving radius, set their revive_progress values correct + FOR_EACH_PLAYER(other) if(self != other) + { + if(other.freezetag_frozen == 0) + { + if(other.team == self.team) + { + if(boxesoverlap(self.absmin - revive_extra_size, self.absmax + revive_extra_size, other.absmin, other.absmax)) + other.freezetag_revive_progress = self.freezetag_revive_progress; + } + } + } + } + else if(!n && self.freezetag_frozen) // only if no teammate is nearby will we reset + { + self.freezetag_revive_progress = bound(0, self.freezetag_revive_progress - frametime * autocvar_g_freezetag_revive_clearspeed, 1); + self.health = max(1, self.freezetag_revive_progress * autocvar_g_balance_health_start); + } + else if(!n) + { + self.freezetag_revive_progress = 0; // thawing nobody + } return 1; } @@ -253,7 +308,10 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerPreThink) MUTATOR_HOOKFUNCTION(freezetag_PlayerPhysics) { if(self.freezetag_frozen) + { self.movement = '0 0 0'; + self.disableclientprediction = 1; + } return 1; } @@ -270,6 +328,13 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerDamage_Calculate) return 1; } +MUTATOR_HOOKFUNCTION(freezetag_ForbidThrowCurrentWeapon) +{ + if (self.freezetag_frozen) + return 1; + return 0; +} + MUTATOR_DEFINITION(gamemode_freezetag) { MUTATOR_HOOK(MakePlayerObserver, freezetag_RemovePlayer, CBC_ORDER_ANY); @@ -280,6 +345,7 @@ MUTATOR_DEFINITION(gamemode_freezetag) MUTATOR_HOOK(PlayerPreThink, freezetag_PlayerPreThink, CBC_ORDER_FIRST); MUTATOR_HOOK(PlayerPhysics, freezetag_PlayerPhysics, CBC_ORDER_FIRST); MUTATOR_HOOK(PlayerDamage_Calculate, freezetag_PlayerDamage_Calculate, CBC_ORDER_ANY); + MUTATOR_HOOK(ForbidThrowCurrentWeapon, freezetag_ForbidThrowCurrentWeapon, CBC_ORDER_FIRST); //first, last or any? dunno. MUTATOR_ONADD { diff --git a/qcsrc/server/mutators/gamemode_keepaway.qc b/qcsrc/server/mutators/gamemode_keepaway.qc index 9fb47afbb3..9134353e01 100644 --- a/qcsrc/server/mutators/gamemode_keepaway.qc +++ b/qcsrc/server/mutators/gamemode_keepaway.qc @@ -2,6 +2,10 @@ void ka_SpawnBall(void); void ka_TouchEvent(void); void ka_RespawnBall(void); void ka_DropEvent(entity); +void ka_TimeScoring(void); +void ka_EventLog(string, entity); + +entity ka_ball; float ka_ballcarrier_waypointsprite_visible_for_player(entity); @@ -28,53 +32,54 @@ void ka_Reset() // used to clear the ballcarrier whenever the match switches fro ka_RespawnBall(); } -void ka_SpawnBall() // loads various values for the ball +void ka_SpawnBall() // loads various values for the ball, runs only once at start of match { if(!g_keepaway) { return; } entity e; e = spawn(); e.model = "models/orbs/orbblue.md3"; - e.scale = 1; precache_model(e.model); setmodel(e, e.model); setsize(e, '-16 -16 -20', '16 16 20'); // 20 20 20 was too big, player is only 16 16 24... gotta cheat with the Z (20) axis so that the particle isn't cut off e.classname = "keepawayball"; e.damageforcescale = autocvar_g_keepawayball_damageforcescale; e.takedamage = DAMAGE_YES; + e.solid = SOLID_TRIGGER; + e.movetype = MOVETYPE_BOUNCE; e.glow_color = autocvar_g_keepawayball_trail_color; e.glow_trail = TRUE; - e.movetype = MOVETYPE_BOUNCE; - e.touch = ka_TouchEvent; e.flags = FL_ITEM; e.reset = ka_Reset; + e.touch = ka_TouchEvent; e.owner = world; + ka_ball = e; InitializeEntity(e, ka_RespawnBall, INITPRIO_SETLOCATION); // is this the right priority? Neh, I have no idea.. Well-- it works! So. } void ka_RespawnBall() // runs whenever the ball needs to be relocated { + if(gameover) { return; } vector oldballorigin = self.origin; - + if(MoveToRandomMapLocation(self, DPCONTENTS_SOLID | DPCONTENTS_CORPSE | DPCONTENTS_PLAYERCLIP, DPCONTENTS_SLIME | DPCONTENTS_LAVA | DPCONTENTS_SKY | DPCONTENTS_BODY | DPCONTENTS_DONOTENTER, Q3SURFACEFLAG_SKY, 10, 1024, 256)) { makevectors(self.angles); self.movetype = MOVETYPE_BOUNCE; self.velocity = '0 0 200'; self.angles = '0 0 0'; - self.solid = SOLID_TRIGGER; + self.effects = autocvar_g_keepawayball_effects; self.think = ka_RespawnBall; self.nextthink = time + autocvar_g_keepawayball_respawntime; pointparticles(particleeffectnum("electro_combo"), oldballorigin, '0 0 0', 1); pointparticles(particleeffectnum("electro_combo"), self.origin, '0 0 0', 1); - WaypointSprite_Spawn("ka-ball", 0, 0, self, '0 0 64', world, self.team, self, waypointsprite_attachedforcarrier, FALSE); - WaypointSprite_UpdateTeamRadar(self.waypointsprite_attachedforcarrier, RADARICON_FLAGCARRIER, '0 1 1'); + WaypointSprite_Spawn("ka-ball", 0, 0, self, '0 0 64', world, self.team, self, waypointsprite_attachedforcarrier, FALSE, RADARICON_FLAGCARRIER, '0 1 1'); WaypointSprite_Ping(self.waypointsprite_attachedforcarrier); - sound(self, CHAN_AUTO, "keepaway/respawn.wav", VOL_BASE, ATTN_NONE); // ATTN_NONE (it's a sound intended to be heard anywhere) + sound(self, CH_TRIGGER, "keepaway/respawn.wav", VOL_BASE, ATTN_NONE); // ATTN_NONE (it's a sound intended to be heard anywhere) } else { @@ -84,6 +89,7 @@ void ka_RespawnBall() // runs whenever the ball needs to be relocated void ka_TouchEvent() // runs any time that the ball comes in contact with something { + if(gameover) { return; } if(!self) { return; } if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT) { // The ball fell off the map, respawn it since players can't get to it @@ -94,7 +100,7 @@ void ka_TouchEvent() // runs any time that the ball comes in contact with someth if(other.classname != "player") { // The ball just touched an object, most likely the world pointparticles(particleeffectnum("kaball_sparks"), self.origin, '0 0 0', 1); - sound(self, CHAN_AUTO, "keepaway/touch.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER, "keepaway/touch.wav", VOL_BASE, ATTN_NORM); return; } else if(self.wait > time) { return; } @@ -103,38 +109,36 @@ void ka_TouchEvent() // runs any time that the ball comes in contact with someth self.owner = other; other.ballcarried = self; setattachment(self, other, ""); - setorigin(self, '3 0 20'); + setorigin(self, '0 0 0'); - // make the ball invisible/unable to do anything + // make the ball invisible/unable to do anything/set up time scoring self.velocity = '0 0 0'; self.movetype = MOVETYPE_NONE; - self.touch = SUB_Null; self.effects |= EF_NODRAW; - self.think = SUB_Null; - self.nextthink = 0; + self.touch = SUB_Null; + self.think = ka_TimeScoring; + self.nextthink = time + autocvar_g_keepaway_score_timeinterval; self.takedamage = DAMAGE_NO; // apply effects to player other.glow_color = autocvar_g_keepawayball_trail_color; other.glow_trail = TRUE; - other.effects |= EF_DIMLIGHT; - other.alpha = autocvar_g_keepaway_ballcarrier_alpha; - other.exteriorweaponentity.alpha = autocvar_g_keepaway_ballcarrier_alpha; - + other.effects |= autocvar_g_keepaway_ballcarrier_effects; + // messages and sounds + ka_EventLog("pickup", other); Send_KillNotification(other.netname, "", "", KA_PICKUPBALL, MSG_KA); WriteByte(MSG_BROADCAST, SVC_CENTERPRINT); - WriteString(MSG_BROADCAST, strcat("\n\n", other.netname, "^7 has picked up the ball!\n")); - sound(self.owner, CHAN_AUTO, "keepaway/pickedup.wav", VOL_BASE, ATTN_NONE); // ATTN_NONE (it's a sound intended to be heard anywhere) + WriteString(MSG_BROADCAST, strcat(other.netname, "^7 has picked up the ball!")); + sound(self.owner, CH_TRIGGER, "keepaway/pickedup.wav", VOL_BASE, ATTN_NONE); // ATTN_NONE (it's a sound intended to be heard anywhere) // scoring PlayerScore_Add(other, SP_KEEPAWAY_PICKUPS, 1); // waypoints - WaypointSprite_AttachCarrier("ka-ballcarrier", other); + WaypointSprite_AttachCarrier("ka-ballcarrier", other, RADARICON_FLAGCARRIER, '1 0 0'); other.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = ka_ballcarrier_waypointsprite_visible_for_player; WaypointSprite_UpdateRule(other.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT); - WaypointSprite_UpdateTeamRadar(other.waypointsprite_attachedforcarrier, RADARICON_FLAGCARRIER, '1 0 0'); WaypointSprite_Ping(other.waypointsprite_attachedforcarrier); WaypointSprite_Kill(self.waypointsprite_attachedforcarrier); } @@ -149,11 +153,10 @@ void ka_DropEvent(entity plyr) // runs any time that a player is supposed to los // reset the ball setattachment(ball, world, ""); ball.movetype = MOVETYPE_BOUNCE; - ball.solid = SOLID_TRIGGER; // is this needed? ball.wait = time + 1; + ball.touch = ka_TouchEvent; ball.think = ka_RespawnBall; ball.nextthink = time + autocvar_g_keepawayball_respawntime; - ball.touch = ka_TouchEvent; ball.takedamage = DAMAGE_YES; ball.effects &~= EF_NODRAW; setorigin(ball, plyr.origin + '0 0 10'); @@ -162,24 +165,22 @@ void ka_DropEvent(entity plyr) // runs any time that a player is supposed to los ball.owner = world; // reset the player effects - plyr.effects &~= EF_DIMLIGHT; - plyr.alpha = default_player_alpha; - plyr.exteriorweaponentity.alpha = default_weapon_alpha; plyr.glow_trail = FALSE; - + plyr.effects &~= autocvar_g_keepaway_ballcarrier_effects; + // messages and sounds + ka_EventLog("dropped", plyr); Send_KillNotification(plyr.netname, "", "", KA_DROPBALL, MSG_KA); WriteByte(MSG_BROADCAST, SVC_CENTERPRINT); - WriteString(MSG_BROADCAST, strcat("\n\n", plyr.netname, "^7 has dropped the ball!\n")); - sound(other, CHAN_AUTO, "keepaway/dropped.wav", VOL_BASE, ATTN_NONE); // ATTN_NONE (it's a sound intended to be heard anywhere) + WriteString(MSG_BROADCAST, strcat(plyr.netname, "^7 has dropped the ball!")); + sound(other, CH_TRIGGER, "keepaway/dropped.wav", VOL_BASE, ATTN_NONE); // ATTN_NONE (it's a sound intended to be heard anywhere) // scoring - PlayerScore_Add(plyr, SP_KEEPAWAY_DROPS, 1); + // PlayerScore_Add(plyr, SP_KEEPAWAY_DROPS, 1); Not anymore, this is 100% the same as pickups and is useless. // waypoints - WaypointSprite_Spawn("ka-ball", 0, 0, ball, '0 0 64', world, ball.team, ball, waypointsprite_attachedforcarrier, FALSE); + WaypointSprite_Spawn("ka-ball", 0, 0, ball, '0 0 64', world, ball.team, ball, waypointsprite_attachedforcarrier, FALSE, RADARICON_FLAGCARRIER, '0 1 1'); WaypointSprite_UpdateRule(ball.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT); - WaypointSprite_UpdateTeamRadar(ball.waypointsprite_attachedforcarrier, RADARICON_FLAGCARRIER, '0 1 1'); WaypointSprite_Ping(ball.waypointsprite_attachedforcarrier); WaypointSprite_Kill(plyr.waypointsprite_attachedforcarrier); } @@ -187,20 +188,30 @@ void ka_DropEvent(entity plyr) // runs any time that a player is supposed to los float ka_ballcarrier_waypointsprite_visible_for_player(entity e) // runs on waypoints which are attached to ballcarriers, updates once per frame { if(e.ballcarried) - { if(other.classname == "spectator") return FALSE; // we don't want spectators of the ballcarrier to see the attached waypoint on the top of their screen - else if(g_minstagib && (e.items & IT_STRENGTH)) - return FALSE; // if the ballcarrier has invisibility, don't draw the waypoint as this is the function of invisibility in keepaway - } + + // TODO: Make the ballcarrier lack a waypointsprite whenever they have the invisibility powerup return TRUE; } -MUTATOR_HOOKFUNCTION(ka_RemovePlayer) +void ka_TimeScoring() { - if(self.ballcarried) { ka_DropEvent(self); } // a player with the ball has left the match, drop it - return 0; + if(self.owner.ballcarried) + { // add points for holding the ball after a certain amount of time + if(autocvar_g_keepaway_score_timepoints) + PlayerScore_Add(self.owner, SP_SCORE, autocvar_g_keepaway_score_timepoints); + + PlayerScore_Add(self.owner, SP_KEEPAWAY_BCTIME, (autocvar_g_keepaway_score_timeinterval / 1)); // interval is divided by 1 so that time always shows "seconds" + self.nextthink = time + autocvar_g_keepaway_score_timeinterval; + } +} + +void ka_EventLog(string mode, entity actor) // use an alias for easy changing and quick editing later +{ + if(autocvar_sv_eventlog) + GameLogEcho(strcat(":ka:", mode, ((actor != world) ? (strcat(":", ftos(actor.playerid))) : ""))); } MUTATOR_HOOKFUNCTION(ka_Scoring) @@ -209,15 +220,15 @@ MUTATOR_HOOKFUNCTION(ka_Scoring) { if(frag_target.ballcarried) { // add to amount of times killing carrier PlayerScore_Add(frag_attacker, SP_KEEPAWAY_CARRIERKILLS, 1); - if(autocvar_g_keepaway_bckillscore) // add bckills to the score - PlayerScore_Add(frag_attacker, SP_KEEPAWAY_SCORE, 1); + if(autocvar_g_keepaway_score_bckill) // add bckills to the score + PlayerScore_Add(frag_attacker, SP_SCORE, autocvar_g_keepaway_score_bckill); } else if(!frag_attacker.ballcarried) if(autocvar_g_keepaway_noncarrier_warn) - centerprint_atprio(frag_attacker, (CENTERPRIO_SPAM + 5), "Killing people while you don't have the ball gives no points!"); + centerprint(frag_attacker, "Killing people while you don't have the ball gives no points!"); if(frag_attacker.ballcarried) // add to amount of kills while ballcarrier - PlayerScore_Add(frag_attacker, SP_KEEPAWAY_SCORE, 1); + PlayerScore_Add(frag_attacker, SP_SCORE, autocvar_g_keepaway_score_killac); } if(self.ballcarried) { ka_DropEvent(self); } // a player with the ball has died, drop it @@ -227,7 +238,7 @@ MUTATOR_HOOKFUNCTION(ka_Scoring) MUTATOR_HOOKFUNCTION(ka_GiveFragsForKill) { frag_score = 0; // no frags counted in keepaway - return 0; + return 1; // you deceptive little bugger ;3 This needs to be true in order for this function to even count. } MUTATOR_HOOKFUNCTION(ka_PlayerPreThink) @@ -239,10 +250,17 @@ MUTATOR_HOOKFUNCTION(ka_PlayerPreThink) if(self.ballcarried) self.items |= IT_KEY1; - // drop the ball if the player presses the use button - if(self.BUTTON_USE) - if(self.ballcarried) { ka_DropEvent(self); } + return 0; +} +MUTATOR_HOOKFUNCTION(ka_PlayerUseKey) +{ + if(MUTATOR_RETURNVALUE == 0) + if(self.ballcarried) + { + ka_DropEvent(self); + return 1; + } return 0; } @@ -277,64 +295,35 @@ MUTATOR_HOOKFUNCTION(ka_PlayerDamage) // for changing damage and force values th return 0; } +MUTATOR_HOOKFUNCTION(ka_RemovePlayer) +{ + if(self.ballcarried) { ka_DropEvent(self); } // a player with the ball has left the match, drop it + return 0; +} + MUTATOR_HOOKFUNCTION(ka_PlayerPowerups) { - if(self.ballcarried) - { - // if the player has the ball, force ballcarrier alpha upon them - self.alpha = autocvar_g_keepaway_ballcarrier_alpha; - self.exteriorweaponentity.alpha = autocvar_g_keepaway_ballcarrier_alpha; + // In the future this hook is supposed to allow me to do some extra stuff with waypointsprites and invisibility powerup + // So bare with me until I can fix a certain bug with ka_ballcarrier_waypointsprite_visible_for_player() - // if we're in minstagib and a ballcarrier has just picked up invisibility, - // notify all the other players that the ballcarrier no longer has a waypoint - if(g_minstagib) - { - if(olditems & IT_STRENGTH) - { - if(time > self.strength_finished) - { // this only runs ONCE right after the player loses invisibility - bprint(self.netname, "^7 isn't invisible from radar anymore.\n"); - } - } - else - { - if(time < self.strength_finished) - { // this only runs ONCE right after the player gains invisibility - bprint(self.netname, "^7 has picked up invisibility and can no longer be seen on radar!\n"); - } - } - } - } - else if(g_minstagib) - { - // if we're in minstagib and a noncarrier has invisibility, assure that we apply the invisibility effects normally - if(olditems & IT_STRENGTH) - { - self.alpha = g_minstagib_invis_alpha; - self.exteriorweaponentity.alpha = g_minstagib_invis_alpha; - } - } - else - { - // if we're a normal player with no powerups that edit alpha make sure the alpha is default. - // (normal powerups just use EF_ADDITIVE) - self.alpha = default_player_alpha; - self.exteriorweaponentity.alpha = default_weapon_alpha; - } + self.effects &~= autocvar_g_keepaway_ballcarrier_effects; + + if(self.ballcarried) + self.effects |= autocvar_g_keepaway_ballcarrier_effects; return 0; } MUTATOR_DEFINITION(gamemode_keepaway) { - // I don't quite understand these orders, perhaps someone could enlighten me? MUTATOR_HOOK(MakePlayerObserver, ka_RemovePlayer, CBC_ORDER_ANY); MUTATOR_HOOK(ClientDisconnect, ka_RemovePlayer, CBC_ORDER_ANY); MUTATOR_HOOK(PlayerDies, ka_Scoring, CBC_ORDER_ANY); MUTATOR_HOOK(GiveFragsForKill, ka_GiveFragsForKill, CBC_ORDER_ANY); - MUTATOR_HOOK(PlayerPreThink, ka_PlayerPreThink, CBC_ORDER_FIRST); + MUTATOR_HOOK(PlayerPreThink, ka_PlayerPreThink, CBC_ORDER_ANY); MUTATOR_HOOK(PlayerDamage_Calculate, ka_PlayerDamage, CBC_ORDER_ANY); MUTATOR_HOOK(PlayerPowerups, ka_PlayerPowerups, CBC_ORDER_ANY); + MUTATOR_HOOK(PlayerUseKey, ka_PlayerUseKey, CBC_ORDER_ANY); MUTATOR_ONADD { diff --git a/qcsrc/server/mutators/gamemode_keyhunt.qc b/qcsrc/server/mutators/gamemode_keyhunt.qc index e1cb1a85bc..d3f4fdc87e 100644 --- a/qcsrc/server/mutators/gamemode_keyhunt.qc +++ b/qcsrc/server/mutators/gamemode_keyhunt.qc @@ -58,6 +58,7 @@ float kh_interferemsg_time, kh_interferemsg_team; .float kh_dropperteam; .entity kh_previous_owner; .float kh_previous_owner_playerid; +.float kh_cp_duration; string kh_sound_capture = "kh/capture.wav"; string kh_sound_destroy = "kh/destroy.wav"; @@ -121,7 +122,7 @@ void kh_update_state() var kh_Think_t kh_Controller_Thinkfunc; -void kh_Controller_SetThink(float t, string msg, kh_Think_t func) // runs occasionaly +void kh_Controller_SetThink(float t, string msg, float centerprint_duration, kh_Think_t func) // runs occasionaly { kh_Controller_Thinkfunc = func; kh_controller.cnt = ceil(t); @@ -130,10 +131,17 @@ void kh_Controller_SetThink(float t, string msg, kh_Think_t func) // runs occas if(msg == "") kh_Controller_Waitmsg = ""; else + { + kh_controller.kh_cp_duration = centerprint_duration; kh_Controller_Waitmsg = strzone(msg); + } if(t == 0) kh_controller.nextthink = time; // force } +void kh_Controller_SetThink_NoMsg(float t, kh_Think_t func) // runs occasionaly +{ + kh_Controller_SetThink(t, "", 0, func); +} void kh_Controller_Think() // called a lot { @@ -154,7 +162,7 @@ void kh_Controller_Think() // called a lot FOR_EACH_PLAYER(e) if(clienttype(e) == CLIENTTYPE_REAL) - centerprint_atprio(e, CENTERPRIO_SPAM, s); + Send_CSQC_Centerprint_Generic(e, CPID_KH_MSG, s, self.kh_cp_duration, 0); } self.cnt -= 1; } @@ -350,7 +358,7 @@ void kh_Key_AssignTo(entity key, entity player) // runs every time a key is pic if(key.kh_next == world) { // player is now a key carrier - WaypointSprite_AttachCarrier("", player); + WaypointSprite_AttachCarrier("", player, RADARICON_FLAGCARRIER, colormapPaletteColor(player.team - 1, 0)); player.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = kh_KeyCarrier_waypointsprite_visible_for_player; WaypointSprite_UpdateRule(player.waypointsprite_attachedforcarrier, player.team, SPRITERULE_TEAMPLAY); if(player.team == COLOR_TEAM1) @@ -361,7 +369,6 @@ void kh_Key_AssignTo(entity key, entity player) // runs every time a key is pic WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-yellow", "keycarrier-friend", "keycarrier-yellow"); else if(player.team == COLOR_TEAM4) WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-pink", "keycarrier-friend", "keycarrier-pink"); - WaypointSprite_UpdateTeamRadar(player.waypointsprite_attachedforcarrier, RADARICON_FLAGCARRIER, colormapPaletteColor(player.team - 1, 0)); if(!kh_no_radar_circles) WaypointSprite_Ping(player.waypointsprite_attachedforcarrier); } @@ -414,7 +421,7 @@ void kh_Key_Damage(entity inflictor, entity attacker, float damage, float deatht void kh_Key_Collect(entity key, entity player) //a player picks up a dropped key { - sound(player, CHAN_AUTO, kh_sound_collect, VOL_BASE, ATTN_NORM); + sound(player, CH_TRIGGER, kh_sound_collect, VOL_BASE, ATTN_NORM); if(key.kh_dropperteam != player.team) { @@ -487,7 +494,7 @@ void kh_FinishRound() // runs when a team captures the keys kh_Key_Remove(key); kh_no_radar_circles = FALSE; - kh_Controller_SetThink(autocvar_g_balance_keyhunt_delay_round, "Round starts in ", kh_StartRound); + kh_Controller_SetThink(autocvar_g_balance_keyhunt_delay_round, "Round starts in ", 1, kh_StartRound); } void kh_WinnerTeam(float teem) // runs when a team wins @@ -653,23 +660,6 @@ void kh_Key_Think() // runs all the time makevectors('0 1 0' * (self.cnt + mod(time, 360) * KH_KEY_XYSPEED)); setorigin(self, v_forward * KH_KEY_XYDIST + '0 0 1' * self.origin_z); #endif - - if(self.owner.BUTTON_USE) - if(time >= self.owner.kh_droptime + autocvar_g_balance_keyhunt_delay_drop) - { - self.owner.kh_droptime = time; - self.kh_droptime = time; // prevent collecting this one for some time - self.enemy = self.owner; - self.pusher = world; - kh_Scores_Event(self.owner, self, "dropkey", 0, 0); - bprint(self.owner.netname, "^7 dropped the ", self.netname, "\n"); - sound(self.owner, CHAN_AUTO, kh_sound_drop, VOL_BASE, ATTN_NORM); - makevectors(self.owner.v_angle); - self.velocity = W_CalculateProjectileVelocity(self.owner.velocity, autocvar_g_balance_keyhunt_throwvelocity * v_forward, FALSE); - kh_Key_AssignTo(self, world); - self.pushltime = time + autocvar_g_balance_keyhunt_protecttime; - self.kh_dropperteam = self.team; - } } // if in nodrop or time over, end the round @@ -682,7 +672,7 @@ void kh_Key_Think() // runs all the time { if(self.siren_time < time) { - sound(self.owner, CHAN_AUTO, kh_sound_alarm, VOL_BASE, ATTN_NORM); // play a simple alarm + sound(self.owner, CH_TRIGGER, kh_sound_alarm, VOL_BASE, ATTN_NORM); // play a simple alarm self.siren_time = time + 2.5; // repeat every 2.5 seconds } @@ -703,11 +693,11 @@ void kh_Key_Think() // runs all the time { if(head.team == kh_interferemsg_team) if(head.kh_next) - centerprint(head, "All keys are in your team's hands!\n\nMeet the other key carriers ^1NOW^7!"); + Send_CSQC_Centerprint_Generic(head, CPID_KH_MSG, "All keys are in your team's hands!\n\nMeet the other key carriers ^1NOW^7!", 0, 0); else - centerprint(head, "All keys are in your team's hands!\n\nHelp the key carriers to meet!"); + Send_CSQC_Centerprint_Generic(head, CPID_KH_MSG, "All keys are in your team's hands!\n\nHelp the key carriers to meet!", 0, 0); else - centerprint(head, strcat("All keys are in the ", ColoredTeamName(kh_interferemsg_team), "^7's hands!\n\nInterfere ^1NOW^7!")); + Send_CSQC_Centerprint_Generic(head, CPID_KH_MSG, strcat("All keys are in the ", ColoredTeamName(kh_interferemsg_team), "^7's hands!\n\nInterfere ^1NOW^7!"), 0, 0); } } @@ -768,9 +758,8 @@ void kh_Key_Spawn(entity initial_owner, float angle, float i) // runs every tim centerprint(initial_owner, strcat("You are starting with the ", key.netname, "\n")); // message to player at start of round - WaypointSprite_Spawn("key-dropped", 0, 0, key, '0 0 1' * KH_KEY_WP_ZSHIFT, world, key.team, key, waypointsprite_attachedforcarrier, FALSE); + WaypointSprite_Spawn("key-dropped", 0, 0, key, '0 0 1' * KH_KEY_WP_ZSHIFT, world, key.team, key, waypointsprite_attachedforcarrier, FALSE, RADARICON_FLAG, '0 1 1'); key.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = kh_Key_waypointsprite_visible_for_player; - WaypointSprite_UpdateTeamRadar(key.waypointsprite_attachedforcarrier, RADARICON_FLAG, '0 1 1'); kh_Key_AssignTo(key, initial_owner); } @@ -799,6 +788,28 @@ float kh_Key_AllOwnedByWhichTeam() // constantly called. check to see if all th return teem; } +void kh_Key_DropOne(entity key) +{ + // prevent collecting this one for some time + entity player; + player = key.owner; + + key.kh_droptime = time; + key.enemy = player; + + kh_Scores_Event(player, key, "dropkey", 0, 0); + PlayerScore_Add(player, SP_KH_LOSSES, 1); + bprint(player.netname, "^7 dropped the ", key.netname, "\n"); + kh_Key_AssignTo(key, world); + makevectors(player.v_angle); + key.velocity = W_CalculateProjectileVelocity(player.velocity, autocvar_g_balance_keyhunt_throwvelocity * v_forward, FALSE); + key.pusher = world; + key.pushltime = time + autocvar_g_balance_keyhunt_protecttime; + key.kh_dropperteam = key.team; + + sound(player, CH_TRIGGER, kh_sound_drop, VOL_BASE, ATTN_NORM); +} + void kh_Key_DropAll(entity player, float suicide) // runs whenever a player dies { entity key; @@ -822,7 +833,7 @@ void kh_Key_DropAll(entity player, float suicide) // runs whenever a player dies if(suicide) key.kh_dropperteam = player.team; } - sound(player, CHAN_AUTO, kh_sound_drop, VOL_BASE, ATTN_NORM); + sound(player, CH_TRIGGER, kh_sound_drop, VOL_BASE, ATTN_NORM); } } @@ -859,15 +870,15 @@ void kh_WaitForPlayers() // delay start of the round until enough players are p if(time < game_starttime) { - kh_Controller_SetThink(game_starttime - time + 0.1, "", kh_WaitForPlayers); + kh_Controller_SetThink_NoMsg(game_starttime - time + 0.1, kh_WaitForPlayers); return; } teams_missing = kh_CheckEnoughPlayers(); if(teams_missing == "") - kh_Controller_SetThink(autocvar_g_balance_keyhunt_delay_round, "Round starts in ", kh_StartRound); + kh_Controller_SetThink(autocvar_g_balance_keyhunt_delay_round, "Round starts in ", 1, kh_StartRound); else - kh_Controller_SetThink(1, strcat("Waiting for players to join...\n\nNeed active players for: ", teams_missing), kh_WaitForPlayers); + kh_Controller_SetThink(1, strcat("Waiting for players to join...\n\nNeed active players for: ", teams_missing), -1, kh_WaitForPlayers); } void kh_EnableTrackingDevice() // runs after each round @@ -876,7 +887,7 @@ void kh_EnableTrackingDevice() // runs after each round FOR_EACH_PLAYER(player) if(clienttype(player) == CLIENTTYPE_REAL) - centerprint_expire(player, CENTERPRIO_SPAM); + Send_CSQC_Centerprint_Generic_Expire(player, CPID_KH_MSG); kh_tracking_enabled = TRUE; } @@ -889,20 +900,20 @@ void kh_StartRound() // runs at the start of each round if(time < game_starttime) { - kh_Controller_SetThink(game_starttime - time + 0.1, "", kh_WaitForPlayers); + kh_Controller_SetThink_NoMsg(game_starttime - time + 0.1, kh_WaitForPlayers); return; } teams_missing = kh_CheckEnoughPlayers(); if(teams_missing != "") { - kh_Controller_SetThink(1, strcat("Waiting for players to join...\n\nNeed active players for: ", teams_missing), kh_WaitForPlayers); + kh_Controller_SetThink(1, strcat("Waiting for players to join...\n\nNeed active players for: ", teams_missing), -1, kh_WaitForPlayers); return; } FOR_EACH_PLAYER(player) if(clienttype(player) == CLIENTTYPE_REAL) - centerprint_expire(player, CENTERPRIO_SPAM); + Send_CSQC_Centerprint_Generic_Expire(player, CPID_KH_MSG); for(i = 0; i < kh_teams; ++i) { @@ -922,7 +933,7 @@ void kh_StartRound() // runs at the start of each round } kh_tracking_enabled = FALSE; - kh_Controller_SetThink(autocvar_g_balance_keyhunt_delay_tracking, "Scanning frequency range...", kh_EnableTrackingDevice); + kh_Controller_SetThink(autocvar_g_balance_keyhunt_delay_tracking, "Scanning frequency range...", -1, kh_EnableTrackingDevice); } float kh_HandleFrags(entity attacker, entity targ, float f) // adds to the player score @@ -974,7 +985,7 @@ void kh_Initialize() // sets up th KH environment // make a KH entity for controlling the game kh_controller = spawn(); kh_controller.think = kh_Controller_Think; - kh_Controller_SetThink(0, "", kh_WaitForPlayers); + kh_Controller_SetThink_NoMsg(0, kh_WaitForPlayers); setmodel(kh_controller, "models/keyhunt/key.md3"); kh_key_dropped = kh_controller.modelindex; @@ -1018,7 +1029,7 @@ MUTATOR_HOOKFUNCTION(kh_PlayerDies) { if(self == other) kh_Key_DropAll(self, TRUE); - else if(other.classname == "player" || other.classname == "gib") + else if(other.classname == "player") kh_Key_DropAll(self, FALSE); else kh_Key_DropAll(self, TRUE); @@ -1049,6 +1060,21 @@ MUTATOR_HOOKFUNCTION(kh_SpectateCopy) return 0; } +MUTATOR_HOOKFUNCTION(kh_PlayerUseKey) +{ + if(MUTATOR_RETURNVALUE == 0) + { + entity k; + k = self.kh_next; + if(k) + { + kh_Key_DropOne(k); + return 1; + } + } + return 0; +} + MUTATOR_DEFINITION(gamemode_keyhunt) { MUTATOR_HOOK(MakePlayerObserver, kh_Key_DropAll, CBC_ORDER_ANY); @@ -1058,6 +1084,7 @@ MUTATOR_DEFINITION(gamemode_keyhunt) MUTATOR_HOOK(MatchEnd, kh_finalize, CBC_ORDER_ANY); MUTATOR_HOOK(GetTeamCount, kh_GetTeamCount, CBC_ORDER_EXCLUSIVE); MUTATOR_HOOK(SpectateCopy, kh_SpectateCopy, CBC_ORDER_ANY); + MUTATOR_HOOK(PlayerUseKey, kh_PlayerUseKey, CBC_ORDER_ANY); MUTATOR_ONADD { diff --git a/qcsrc/server/mutators/gamemode_keyhunt.qh b/qcsrc/server/mutators/gamemode_keyhunt.qh index 71f25c3a88..8ee8434293 100644 --- a/qcsrc/server/mutators/gamemode_keyhunt.qh +++ b/qcsrc/server/mutators/gamemode_keyhunt.qh @@ -9,4 +9,4 @@ float kh_Key_AllOwnedByWhichTeam(); // used by arena.qc ready-restart: typedef void(void) kh_Think_t; void kh_StartRound(); -void kh_Controller_SetThink(float t, string msg, kh_Think_t func); +void kh_Controller_SetThink_NoMsg(float t, kh_Think_t func); diff --git a/qcsrc/server/mutators/mutator_dodging.qc b/qcsrc/server/mutators/mutator_dodging.qc index 1c05a4a091..3b193c163c 100644 --- a/qcsrc/server/mutators/mutator_dodging.qc +++ b/qcsrc/server/mutators/mutator_dodging.qc @@ -112,7 +112,7 @@ MUTATOR_HOOKFUNCTION(dodging_PlayerPhysics) { + (autocvar_sv_dodging_up_speed * v_up); if (autocvar_sv_dodging_sound == 1) - PlayerSound(playersound_jump, CHAN_PLAYER, VOICETYPE_PLAYERSOUND); + PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND); setanim(self, self.anim_jump, TRUE, FALSE, TRUE); diff --git a/qcsrc/server/mutators/mutator_invincibleproj.qc b/qcsrc/server/mutators/mutator_invincibleproj.qc new file mode 100644 index 0000000000..d1ab520001 --- /dev/null +++ b/qcsrc/server/mutators/mutator_invincibleproj.qc @@ -0,0 +1,30 @@ +MUTATOR_HOOKFUNCTION(invincibleprojectiles_EditProjectile) +{ + if(other.health) + { + // disable health which in effect disables damage calculations + other.health = 0; + } + return 0; +} + +MUTATOR_HOOKFUNCTION(invincibleprojectiles_BuildMutatorsString) +{ + ret_string = strcat(ret_string, ":InvincibleProjectiles"); + return 0; +} + +MUTATOR_HOOKFUNCTION(invincibleprojectiles_BuildMutatorsPrettyString) +{ + ret_string = strcat(ret_string, ", Invincible Projectiles"); + return 0; +} + +MUTATOR_DEFINITION(mutator_invincibleprojectiles) +{ + MUTATOR_HOOK(EditProjectile, invincibleprojectiles_EditProjectile, CBC_ORDER_ANY); + MUTATOR_HOOK(BuildMutatorsString, invincibleprojectiles_BuildMutatorsString, CBC_ORDER_ANY); + MUTATOR_HOOK(BuildMutatorsPrettyString, invincibleprojectiles_BuildMutatorsPrettyString, CBC_ORDER_ANY); + + return 0; +} diff --git a/qcsrc/server/mutators/mutator_nix.qc b/qcsrc/server/mutators/mutator_nix.qc index 1cc5c9c65b..519d51daa2 100644 --- a/qcsrc/server/mutators/mutator_nix.qc +++ b/qcsrc/server/mutators/mutator_nix.qc @@ -61,10 +61,13 @@ void NIX_GiveCurrentWeapon() nix_weapon = nix_nextweapon; nix_weapon_ammo = nix_nextweapon_ammo; nix_nextweapon = 0; - nix_nextchange = time + autocvar_g_balance_nix_roundtime; + if (!nix_nextchange) // no round played yet? + nix_nextchange = time; // start the first round now! + else + nix_nextchange = time + autocvar_g_balance_nix_roundtime; //weapon_action(nix_weapon, WR_PRECACHE); // forget it, too slow } - + if(nix_nextchange != self.nix_lastchange_id) // this shall only be called once per round! { self.nix_lastchange_id = nix_nextchange; @@ -98,13 +101,29 @@ void NIX_GiveCurrentWeapon() if(dt >= 1 && dt <= 5) self.nix_lastinfotime = -42; else - centerprint(self, strcat("\n\n^2Active weapon: ^3", W_Name(nix_weapon))); + Send_CSQC_Centerprint_Generic(self, CPID_NIX_WPNCHANGE, strcat("^2Active weapon: ^3", W_Name(nix_weapon)), 0, 0); + + weapon_action(nix_weapon, WR_RESETPLAYER); + + // all weapons must be fully loaded when we spawn + entity e; + e = get_weaponinfo(nix_weapon); + if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars + self.(weapon_load[nix_weapon]) = cvar(strcat("g_balance_", e.netname, "_reload_ammo")); + + // nex too + if(autocvar_g_balance_nex_charge) + { + if(autocvar_g_balance_nex_secondary_chargepool) + self.nex_chargepool_ammo = 1; + self.nex_charge = autocvar_g_balance_nex_charge_start; + } } if(self.nix_lastinfotime != dt) { self.nix_lastinfotime = dt; // initial value 0 should count as "not seen" if(dt >= 1 && dt <= 5) - centerprint(self, strcat("^3", ftos(dt), "^2 seconds until weapon change...\n\nNext weapon: ^3", W_Name(nix_nextweapon), "\n")); + Send_CSQC_Centerprint_Generic(self, CPID_NIX_WPNCHANGE, strcat("^3%d^2 seconds until weapon change...\n\nNext weapon: ^3", W_Name(nix_nextweapon)), 1, dt); } if(!(self.items & IT_UNLIMITED_WEAPON_AMMO) && time > self.nix_nextincr) @@ -191,7 +210,7 @@ MUTATOR_HOOKFUNCTION(nix_FilterItem) MUTATOR_HOOKFUNCTION(nix_OnEntityPreSpawn) { - if(self.classname == "target_items") // items triggers cannot work in nixnex (as they change weapons/ammo) + if(self.classname == "target_items") // items triggers cannot work in nix (as they change weapons/ammo) return 1; return 0; } @@ -229,7 +248,7 @@ MUTATOR_DEFINITION(mutator_nix) { g_nix_with_laser = autocvar_g_nix_with_laser; - nix_nextchange = time; + nix_nextchange = 0; nix_nextweapon = 0; NIX_precache(); diff --git a/qcsrc/server/mutators/mutator_spawn_near_teammate.qc b/qcsrc/server/mutators/mutator_spawn_near_teammate.qc new file mode 100644 index 0000000000..4d0746dec2 --- /dev/null +++ b/qcsrc/server/mutators/mutator_spawn_near_teammate.qc @@ -0,0 +1,59 @@ +float autocvar_g_spawn_near_teammate_distance; +.entity msnt_lookat; + +MUTATOR_HOOKFUNCTION(msnt_Spawn_Score) +{ + entity p; + + spawn_spot.msnt_lookat = world; + + if(!teamplay) + return 0; + + RandomSelection_Init(); + FOR_EACH_PLAYER(p) if(p != self) if(p.team == self.team) if(!p.deadflag) + { + float l = vlen(spawn_spot.origin - p.origin); + if(l > autocvar_g_spawn_near_teammate_distance) + continue; + if(l < 48) + continue; + if(!checkpvs(spawn_spot.origin, p)) + continue; + RandomSelection_Add(p, 0, string_null, 1, 1); + } + + if(RandomSelection_chosen_ent) + { + spawn_spot.msnt_lookat = RandomSelection_chosen_ent; + spawn_score_x += SPAWN_PRIO_NEAR_TEAMMATE_FOUND; + } + else if(self.team == spawn_spot.team) + spawn_score_x += SPAWN_PRIO_NEAR_TEAMMATE_SAMETEAM; // prefer same team, if we can't find a spawn near teammate + + return 0; +} + +MUTATOR_HOOKFUNCTION(msnt_PlayerSpawn) +{ + if(spawn_spot.msnt_lookat) + { + self.angles = vectoangles(spawn_spot.msnt_lookat.origin - self.origin); + self.angles_x = -self.angles_x; + /* + sprint(self, "You should be looking at ", spawn_spot.msnt_lookat.netname, "^7.\n"); + sprint(self, "distance: ", vtos(spawn_spot.msnt_lookat.origin - self.origin), "\n"); + sprint(self, "angles: ", vtos(self.angles), "\n"); + */ + } + + return 0; +} + +MUTATOR_DEFINITION(mutator_spawn_near_teammate) +{ + MUTATOR_HOOK(Spawn_Score, msnt_Spawn_Score, CBC_ORDER_ANY); + MUTATOR_HOOK(PlayerSpawn, msnt_PlayerSpawn, CBC_ORDER_ANY); + + return 0; +} diff --git a/qcsrc/server/mutators/mutators.qh b/qcsrc/server/mutators/mutators.qh index d9fff44904..825062e1cd 100644 --- a/qcsrc/server/mutators/mutators.qh +++ b/qcsrc/server/mutators/mutators.qh @@ -2,7 +2,12 @@ MUTATOR_DECLARATION(gamemode_keyhunt); MUTATOR_DECLARATION(gamemode_freezetag); MUTATOR_DECLARATION(gamemode_keepaway); +MUTATOR_DECLARATION(mutator_invincibleprojectiles); MUTATOR_DECLARATION(mutator_nix); MUTATOR_DECLARATION(mutator_dodging); MUTATOR_DECLARATION(mutator_rocketflying); MUTATOR_DECLARATION(mutator_vampire); +MUTATOR_DECLARATION(mutator_spawn_near_teammate); +MUTATOR_DECLARATION(mutator_spawn_near_teammate); + +MUTATOR_DECLARATION(sandbox); diff --git a/qcsrc/server/mutators/sandbox.qc b/qcsrc/server/mutators/sandbox.qc new file mode 100644 index 0000000000..66377d1d84 --- /dev/null +++ b/qcsrc/server/mutators/sandbox.qc @@ -0,0 +1,811 @@ +const float MAX_STORAGE_ATTACHMENTS = 16; +float object_count; +.float object_flood; +.entity object_attach; +.string material; + +.float touch_timer; +void sandbox_ObjectFunction_Touch() +{ + // apply material impact effects + + if(!self.material) + return; + if(self.touch_timer > time) + return; // don't execute each frame + self.touch_timer = time + 0.1; + + // make particle count and sound volume depend on impact speed + float intensity; + intensity = vlen(self.velocity) + vlen(other.velocity); + if(intensity) // avoid divisions by 0 + intensity /= 2; // average the two velocities + if not(intensity >= autocvar_g_sandbox_object_material_velocity_min) + return; // impact not strong enough to do anything + // now offset intensity and apply it to the effects + intensity -= autocvar_g_sandbox_object_material_velocity_min; // start from minimum velocity, not actual velocity + intensity = bound(0, intensity * autocvar_g_sandbox_object_material_velocity_factor, 1); + + sound(self, CH_TRIGGER, strcat("object/impact_", self.material, "_", ftos(ceil(random() * 5)) , ".ogg"), VOL_BASE * intensity, ATTN_NORM); + pointparticles(particleeffectnum(strcat("impact_", self.material)), self.origin, '0 0 0', ceil(intensity * 10)); // allow a count from 1 to 10 +} + +void sandbox_ObjectFunction_Think() +{ + entity e; + + // decide if and how this object can be grabbed + if(autocvar_g_sandbox_readonly) + self.grab = 0; // no grabbing + else if(autocvar_g_sandbox_editor_free < 2 && self.crypto_idfp) + self.grab = 1; // owner only + else + self.grab = 3; // anyone + + // Object owner is stored via player UID, but we also need the owner as an entity (if the player is available on the server). + // Therefore, scan for all players, and update the owner as long as the player is present. We must always do this, + // since if the owning player disconnects, the object's owner should also be reset. + FOR_EACH_REALPLAYER(e) // bots can't have objects + { + if(self.crypto_idfp == e.crypto_idfp) + { + self.realowner = e; + break; + } + self.realowner = world; + } + + self.nextthink = time; +} + +.float old_solid, old_movetype; +entity sandbox_ObjectEdit_Get(float permissions) +{ + // Returns the traced entity if the player can edit it, and world if not. + // If permissions if FALSE, the object is returned regardless of editing rights. + // Attached objects are SOLID_NOT and do not get traced. + + crosshair_trace_plusvisibletriggers(self); + if(vlen(self.origin - trace_ent.origin) > autocvar_g_sandbox_editor_distance_edit) + return world; // out of trace range + if(trace_ent.classname != "object") + return world; // entity is not an object + if(!permissions) + return trace_ent; // don't check permissions, anyone can edit this object + if(!trace_ent.crypto_idfp) + return trace_ent; // the player who spawned this object did not have an UID, so anyone can edit it + if not(trace_ent.realowner != self && autocvar_g_sandbox_editor_free < 2) + return trace_ent; // object does not belong to the player, and players can only edit their own objects on this server + return world; +} + +void sandbox_ObjectEdit_Scale(entity e, float f) +{ + e.scale = f; + if(e.scale) + { + e.scale = bound(autocvar_g_sandbox_object_scale_min, e.scale, autocvar_g_sandbox_object_scale_max); + setmodel(e, e.model); // reset mins and maxs based on mesh + setsize(e, e.mins * e.scale, e.maxs * e.scale); // adapt bounding box size to model size + } +} + +void sandbox_ObjectAttach_Remove(entity e); +void sandbox_ObjectAttach_Set(entity e, entity parent, string s) +{ + // attaches e to parent on string s + + // we can't attach to an attachment, for obvious reasons + sandbox_ObjectAttach_Remove(e); + + e.old_solid = e.solid; // persist solidity + e.old_movetype = e.movetype; // persist physics + e.movetype = MOVETYPE_FOLLOW; + e.solid = SOLID_NOT; + e.takedamage = DAMAGE_NO; + + setattachment(e, parent, s); + e.owner = parent; +} + +void sandbox_ObjectAttach_Remove(entity e) +{ + // detaches any object attached to e + + entity head; + for(head = world; (head = find(head, classname, "object")); ) + { + if(head.owner == e) + { + vector org; + org = gettaginfo(head, 0); + setattachment(head, world, ""); + head.owner = world; + + // objects change origin and angles when detached, so apply previous position + setorigin(head, org); + head.angles = e.angles; // don't allow detached objects to spin or roll + + head.solid = head.old_solid; // restore persisted solidity + head.movetype = head.old_movetype; // restore persisted physics + head.takedamage = DAMAGE_AIM; + } + } +} + +entity sandbox_ObjectSpawn(float database) +{ + // spawn a new object with default properties + + entity e; + e = spawn(); + e.classname = "object"; + e.takedamage = DAMAGE_AIM; + e.damageforcescale = 1; + e.solid = SOLID_BBOX; // SOLID_BSP would be best, but can lag the server badly + e.movetype = MOVETYPE_TOSS; + e.frame = 0; + e.skin = 0; + e.material = string_null; + e.touch = sandbox_ObjectFunction_Touch; + e.think = sandbox_ObjectFunction_Think; + e.nextthink = time; + //e.effects |= EF_SELECTABLE; // don't do this all the time, maybe just when editing objects? + + if(!database) + { + // set the object's owner via player UID + // if the player does not have an UID, the owner cannot be stored and his objects may be edited by anyone + if(self.crypto_idfp != "") + e.crypto_idfp = strzone(self.crypto_idfp); + else + print_to(self, "^1SANDBOX - WARNING: ^7You spawned an object, but lack a player UID. ^1Your objects are not secured and can be edited by any player!"); + + // set public object information + e.netname = strzone(self.netname); // name of the owner + e.message = strzone(strftime(TRUE, "%d-%m-%Y %H:%M:%S")); // creation time + e.message2 = strzone(strftime(TRUE, "%d-%m-%Y %H:%M:%S")); // last editing time + + // set origin and direction based on player position and view angle + makevectors(self.v_angle); + WarpZone_TraceLine(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * autocvar_g_sandbox_editor_distance_spawn, MOVE_NORMAL, self); + setorigin(e, trace_endpos); + e.angles_y = self.v_angle_y; + } + + object_count += 1; + return e; +} + +void sandbox_ObjectRemove(entity e) +{ + sandbox_ObjectAttach_Remove(e); // detach child objects + + // if the object being removed has been selected for attachment by a player, unset it + entity head; + FOR_EACH_REALPLAYER(head) // bots can't have objects + { + if(head.object_attach == e) + head.object_attach = world; + } + + if(e.material) { strunzone(e.material); e.material = string_null; } + if(e.crypto_idfp) { strunzone(e.crypto_idfp); e.crypto_idfp = string_null; } + if(e.netname) { strunzone(e.netname); e.netname = string_null; } + if(e.message) { strunzone(e.message); e.message = string_null; } + if(e.message2) { strunzone(e.message2); e.message2 = string_null; } + remove(e); + e = world; + + object_count -= 1; +} + +string port_string[MAX_STORAGE_ATTACHMENTS]; // fteqcc crashes if this isn't defined as a global + +string sandbox_ObjectPort_Save(entity e, float database) +{ + // save object properties, and return them as a string + float i; + string s; + entity head; + + for(head = world; (head = find(head, classname, "object")); ) + { + // the main object needs to be first in the array [0] with attached objects following + float slot, physics, solidity; + if(head == e) // this is the main object, place it first + { + slot = 0; + solidity = head.solid; // applied solidity is normal solidity for children + physics = head.movetype; // applied physics are normal physics for parents + } + else if(head.owner == e) // child object, list them in order + { + i += 1; // children start from 1 + slot = i; + solidity = head.old_solid; // persisted solidity is normal solidity for children + physics = head.old_movetype; // persisted physics are normal physics for children + gettaginfo(head.owner, head.tag_index); // get the name of the tag our object is attached to, used further below + } + else + continue; + + // ---------------- OBJECT PROPERTY STORAGE: SAVE ---------------- + if(slot) + { + // properties stored only for child objects + if(gettaginfo_name) port_string[slot] = strcat(port_string[slot], "\"", gettaginfo_name, "\" "); else port_string[slot] = strcat(port_string[slot], "\"\" "); // none + } + else + { + // properties stored only for parent objects + if(database) + { + port_string[slot] = strcat(port_string[slot], sprintf("\"%.9v\"", head.origin), " "); + port_string[slot] = strcat(port_string[slot], sprintf("\"%.9v\"", head.angles), " "); + } + } + // properties stored for all objects + port_string[slot] = strcat(port_string[slot], "\"", head.model, "\" "); + port_string[slot] = strcat(port_string[slot], ftos(head.skin), " "); + port_string[slot] = strcat(port_string[slot], ftos(head.alpha), " "); + port_string[slot] = strcat(port_string[slot], sprintf("\"%.9v\"", head.colormod), " "); + port_string[slot] = strcat(port_string[slot], sprintf("\"%.9v\"", head.glowmod), " "); + port_string[slot] = strcat(port_string[slot], ftos(head.frame), " "); + port_string[slot] = strcat(port_string[slot], ftos(head.scale), " "); + port_string[slot] = strcat(port_string[slot], ftos(solidity), " "); + port_string[slot] = strcat(port_string[slot], ftos(physics), " "); + port_string[slot] = strcat(port_string[slot], ftos(head.damageforcescale), " "); + if(head.material) port_string[slot] = strcat(port_string[slot], "\"", head.material, "\" "); else port_string[slot] = strcat(port_string[slot], "\"\" "); // none + if(database) + { + // properties stored only for the database + if(head.crypto_idfp) port_string[slot] = strcat(port_string[slot], "\"", head.crypto_idfp, "\" "); else port_string[slot] = strcat(port_string[slot], "\"\" "); // none + port_string[slot] = strcat(port_string[slot], "\"", e.netname, "\" "); + port_string[slot] = strcat(port_string[slot], "\"", e.message, "\" "); + port_string[slot] = strcat(port_string[slot], "\"", e.message2, "\" "); + } + } + + // now apply the array to a simple string, with the ; symbol separating objects + for(i = 0; i <= MAX_STORAGE_ATTACHMENTS; ++i) + { + if(port_string[i]) + s = strcat(s, port_string[i], "; "); + port_string[i] = string_null; // fully clear the string + } + + return s; +} + +entity sandbox_ObjectPort_Load(string s, float database) +{ + // load object properties, and spawn a new object with them + float n, i; + entity e, parent; + + // separate objects between the ; symbols + n = tokenizebyseparator(s, "; "); + for(i = 0; i < n; ++i) + port_string[i] = argv(i); + + // now separate and apply the properties of each object + for(i = 0; i < n; ++i) + { + float argv_num; + string tagname; + argv_num = 0; + tokenize_console(port_string[i]); + e = sandbox_ObjectSpawn(database); + + // ---------------- OBJECT PROPERTY STORAGE: LOAD ---------------- + if(i) + { + // properties stored only for child objects + if(argv(argv_num) != "") tagname = argv(argv_num); else tagname = string_null; ++argv_num; + } + else + { + // properties stored only for parent objects + if(database) + { + setorigin(e, stov(argv(argv_num))); ++argv_num; + e.angles = stov(argv(argv_num)); ++argv_num; + } + parent = e; // mark parent objects as such + } + // properties stored for all objects + setmodel(e, argv(argv_num)); ++argv_num; + e.skin = stof(argv(argv_num)); ++argv_num; + e.alpha = stof(argv(argv_num)); ++argv_num; + e.colormod = stov(argv(argv_num)); ++argv_num; + e.glowmod = stov(argv(argv_num)); ++argv_num; + e.frame = stof(argv(argv_num)); ++argv_num; + sandbox_ObjectEdit_Scale(e, stof(argv(argv_num))); ++argv_num; + e.solid = e.old_solid = stof(argv(argv_num)); ++argv_num; + e.movetype = e.old_movetype = stof(argv(argv_num)); ++argv_num; + e.damageforcescale = stof(argv(argv_num)); ++argv_num; + if(e.material) strunzone(e.material); if(argv(argv_num) != "") e.material = strzone(argv(argv_num)); else e.material = string_null; ++argv_num; + if(database) + { + // properties stored only for the database + if(e.crypto_idfp) strunzone(e.crypto_idfp); if(argv(argv_num) != "") e.crypto_idfp = strzone(argv(argv_num)); else e.crypto_idfp = string_null; ++argv_num; + if(e.netname) strunzone(e.netname); e.netname = strzone(argv(argv_num)); ++argv_num; + if(e.message) strunzone(e.message); e.message = strzone(argv(argv_num)); ++argv_num; + if(e.message2) strunzone(e.message2); e.message2 = strzone(argv(argv_num)); ++argv_num; + } + + // attach last + if(i) + sandbox_ObjectAttach_Set(e, parent, tagname); + } + + for(i = 0; i <= MAX_STORAGE_ATTACHMENTS; ++i) + port_string[i] = string_null; // fully clear the string + + return e; +} + +void sandbox_Database_Save() +{ + // saves all objects to the database file + entity head; + string file_name; + float file_get; + + file_name = strcat("sandbox/storage_", autocvar_g_sandbox_storage_name, "_", GetMapname(), ".txt"); + file_get = fopen(file_name, FILE_WRITE); + fputs(file_get, strcat("// sandbox storage \"", autocvar_g_sandbox_storage_name, "\" for map \"", GetMapname(), "\" last updated ", strftime(TRUE, "%d-%m-%Y %H:%M:%S"))); + fputs(file_get, strcat(" containing ", ftos(object_count), " objects\n")); + + for(head = world; (head = find(head, classname, "object")); ) + { + // attached objects are persisted separately, ignore them here + if(head.owner != world) + continue; + + // use a line of text for each object, listing all properties + fputs(file_get, strcat(sandbox_ObjectPort_Save(head, TRUE), "\n")); + } + fclose(file_get); +} + +void sandbox_Database_Load() +{ + // loads all objects from the database file + string file_read, file_name; + float file_get, i; + + file_name = strcat("sandbox/storage_", autocvar_g_sandbox_storage_name, "_", GetMapname(), ".txt"); + file_get = fopen(file_name, FILE_READ); + if(file_get < 0) + { + if(autocvar_g_sandbox_info > 0) + print(strcat("^3SANDBOX - SERVER: ^7could not find storage file ^3", file_name, "^7, no objects were loaded\n")); + } + else + { + for(;;) + { + file_read = fgets(file_get); + if(!file_read) + break; + if(substring(file_read, 0, 2) == "//") + continue; + if(substring(file_read, 0, 1) == "#") + continue; + + entity e; + e = sandbox_ObjectPort_Load(file_read, TRUE); + + if(e.material) + { + // since objects are being loaded for the first time, precache material sounds for each + for (i = 1; i <= 5; i++) // 5 sounds in total + precache_sound(strcat("object/impact_", e.material, "_", ftos(i), ".ogg")); + } + } + if(autocvar_g_sandbox_info > 0) + print(strcat("^3SANDBOX - SERVER: ^7successfully loaded storage file ^3", file_name, "\n")); + } + fclose(file_get); +} + +MUTATOR_HOOKFUNCTION(sandbox_PlayerCommand) +{ + if(MUTATOR_RETURNVALUE) // command was already handled? + return FALSE; + if(cmd_name == "g_sandbox") + { + if(autocvar_g_sandbox_readonly) + { + print_to(self, "^2SANDBOX - INFO: ^7Sandbox mode is active, but in read-only mode. Sandbox commands cannot be used"); + return TRUE; + } + if(cmd_argc < 2) + { + print_to(self, "^2SANDBOX - INFO: ^7Sandbox mode is active. For usage information, type 'sandbox help'"); + return TRUE; + } + + switch(argv(1)) + { + entity e; + float i; + string s; + + // ---------------- COMMAND: HELP ---------------- + case "help": + print_to(self, "You can use the following sandbox commands:"); + print_to(self, "^7\"^2object_spawn ^3models/foo/bar.md3^7\" spawns a new object in front of the player, and gives it the specified model"); + print_to(self, "^7\"^2object_remove^7\" removes the object the player is looking at. Players can only remove their own objects"); + print_to(self, "^7\"^2object_duplicate ^3value^7\" duplicates the object, if the player has copying rights over the original"); + print_to(self, "^3copy value ^7- copies the properties of the object to the specified client cvar"); + print_to(self, "^3paste value ^7- spawns an object with the given properties. Properties or cvars must be specified as follows; eg1: \"0 1 2 ...\", eg2: \"$cl_cvar\""); + print_to(self, "^7\"^2object_attach ^3property value^7\" attaches one object to another. Players can only attach their own objects"); + print_to(self, "^3get ^7- selects the object you are facing as the object to be attached"); + print_to(self, "^3set value ^7- attaches the previously selected object to the object you are facing, on the specified bone"); + print_to(self, "^3remove ^7- detaches all objects from the object you are facing"); + print_to(self, "^7\"^2object_edit ^3property value^7\" edits the given property of the object. Players can only edit their own objects"); + print_to(self, "^3skin value ^7- changes the skin of the object"); + print_to(self, "^3alpha value ^7- sets object transparency"); + print_to(self, "^3colormod \"value_x value_y value_z\" ^7- main object color"); + print_to(self, "^3glowmod \"value_x value_y value_z\" ^7- glow object color"); + print_to(self, "^3frame value ^7- object animation frame, for self-animated models"); + print_to(self, "^3scale value ^7- changes object scale. 0.5 is half size and 2 is double size"); + print_to(self, "^3solidity value ^7- object collisions, 0 = non-solid, 1 = solid"); + print_to(self, "^3physics value ^7- object physics, 0 = static, 1 = movable, 2 = physical"); + print_to(self, "^3force value ^7- amount of force applied to objects that are shot"); + print_to(self, "^3material value ^7- sets the material of the object. Default materials are: metal, stone, wood, flesh"); + print_to(self, "^7\"^2object_claim^7\" sets the player as the owner of the object, if he has the right to edit it"); + print_to(self, "^7\"^2object_info ^3value^7\" shows public information about the object"); + print_to(self, "^3object ^7- prints general information about the object, such as owner and creation / editing date"); + print_to(self, "^3mesh ^7- prints information about the object's mesh, including skeletal bones"); + print_to(self, "^3attachments ^7- prints information about the object's attachments"); + print_to(self, "^7The ^1drag object ^7key can be used to grab and carry objects. Players can only grab their own objects"); + return TRUE; + + // ---------------- COMMAND: OBJECT, SPAWN ---------------- + case "object_spawn": + if(time < self.object_flood) + { + print_to(self, strcat("^1SANDBOX - WARNING: ^7Flood protection active. Please wait ^3", ftos(self.object_flood - time), " ^7seconds beofore spawning another object")); + return TRUE; + } + self.object_flood = time + autocvar_g_sandbox_editor_flood; + if(object_count >= autocvar_g_sandbox_editor_maxobjects) + { + print_to(self, strcat("^1SANDBOX - WARNING: ^7Cannot spawn any more objects. Up to ^3", ftos(autocvar_g_sandbox_editor_maxobjects), " ^7objects may exist at a time")); + return TRUE; + } + if(cmd_argc < 3) + { + print_to(self, "^1SANDBOX - WARNING: ^7Attempted to spawn an object without specifying a model. Please specify the path to your model file after the 'object_spawn' command"); + return TRUE; + } + if not(fexists(argv(2))) + { + print_to(self, "^1SANDBOX - WARNING: ^7Attempted to spawn an object with a non-existent model. Make sure the path to your model file is correct"); + return TRUE; + } + + e = sandbox_ObjectSpawn(FALSE); + setmodel(e, argv(2)); + + if(autocvar_g_sandbox_info > 0) + print(strcat("^3SANDBOX - SERVER: ^7", self.netname, " spawned an object at origin ^3", vtos(e.origin), "\n")); + return TRUE; + + // ---------------- COMMAND: OBJECT, REMOVE ---------------- + case "object_remove": + e = sandbox_ObjectEdit_Get(TRUE); + if(e != world) + { + if(autocvar_g_sandbox_info > 0) + print(strcat("^3SANDBOX - SERVER: ^7", self.netname, " removed an object at origin ^3", vtos(e.origin), "\n")); + sandbox_ObjectRemove(e); + return TRUE; + } + + print_to(self, "^1SANDBOX - WARNING: ^7Object could not be removed. Make sure you are facing an object that you have edit rights over"); + return TRUE; + + // ---------------- COMMAND: OBJECT, DUPLICATE ---------------- + case "object_duplicate": + switch(argv(2)) + { + case "copy": + // copies customizable properties of the selected object to the clipboard cvar + e = sandbox_ObjectEdit_Get(autocvar_g_sandbox_editor_free); // can we copy objects we can't edit? + if(e != world) + { + s = sandbox_ObjectPort_Save(e, FALSE); + s = strreplace("\"", "\\\"", s); + stuffcmd(self, strcat("set ", argv(3), " \"", s, "\"")); + + print_to(self, "^2SANDBOX - INFO: ^7Object copied to clipboard"); + return TRUE; + } + print_to(self, "^1SANDBOX - WARNING: ^7Object could not be copied. Make sure you are facing an object that you have copy rights over"); + return TRUE; + + case "paste": + // spawns a new object using the properties in the player's clipboard cvar + if(time < self.object_flood) + { + print_to(self, strcat("^1SANDBOX - WARNING: ^7Flood protection active. Please wait ^3", ftos(self.object_flood - time), " ^7seconds beofore spawning another object")); + return TRUE; + } + self.object_flood = time + autocvar_g_sandbox_editor_flood; + if(!argv(3)) // no object in clipboard + { + print_to(self, "^1SANDBOX - WARNING: ^7No object in clipboard. You must copy an object before you can paste it"); + return TRUE; + } + if(object_count >= autocvar_g_sandbox_editor_maxobjects) + { + print_to(self, strcat("^1SANDBOX - WARNING: ^7Cannot spawn any more objects. Up to ^3", ftos(autocvar_g_sandbox_editor_maxobjects), " ^7objects may exist at a time")); + return TRUE; + } + e = sandbox_ObjectPort_Load(argv(3), FALSE); + + print_to(self, "^2SANDBOX - INFO: ^7Object pasted successfully"); + if(autocvar_g_sandbox_info > 0) + print(strcat("^3SANDBOX - SERVER: ^7", self.netname, " pasted an object at origin ^3", vtos(e.origin), "\n")); + return TRUE; + } + return TRUE; + + // ---------------- COMMAND: OBJECT, ATTACH ---------------- + case "object_attach": + switch(argv(2)) + { + case "get": + // select e as the object as meant to be attached + e = sandbox_ObjectEdit_Get(TRUE); + if(e != world) + { + self.object_attach = e; + print_to(self, "^2SANDBOX - INFO: ^7Object selected for attachment"); + return TRUE; + } + print_to(self, "^1SANDBOX - WARNING: ^7Object could not be selected for attachment. Make sure you are facing an object that you have edit rights over"); + return TRUE; + case "set": + if(self.object_attach == world) + { + print_to(self, "^1SANDBOX - WARNING: ^7No object selected for attachment. Please select an object to be attached first."); + return TRUE; + } + + // attaches the previously selected object to e + e = sandbox_ObjectEdit_Get(TRUE); + if(e != world) + { + sandbox_ObjectAttach_Set(self.object_attach, e, argv(3)); + self.object_attach = world; // object was attached, no longer keep it scheduled for attachment + print_to(self, "^2SANDBOX - INFO: ^7Object attached successfully"); + if(autocvar_g_sandbox_info > 1) + print(strcat("^3SANDBOX - SERVER: ^7", self.netname, " attached objects at origin ^3", vtos(e.origin), "\n")); + return TRUE; + } + print_to(self, "^1SANDBOX - WARNING: ^7Object could not be attached to the parent. Make sure you are facing an object that you have edit rights over"); + return TRUE; + case "remove": + // removes e if it was attached + e = sandbox_ObjectEdit_Get(TRUE); + if(e != world) + { + sandbox_ObjectAttach_Remove(e); + print_to(self, "^2SANDBOX - INFO: ^7Child objects detached successfully"); + if(autocvar_g_sandbox_info > 1) + print(strcat("^3SANDBOX - SERVER: ^7", self.netname, " detached objects at origin ^3", vtos(e.origin), "\n")); + return TRUE; + } + print_to(self, "^1SANDBOX - WARNING: ^7Child objects could not be detached. Make sure you are facing an object that you have edit rights over"); + return TRUE; + } + return TRUE; + + // ---------------- COMMAND: OBJECT, EDIT ---------------- + case "object_edit": + if(!argv(2)) + { + print_to(self, "^1SANDBOX - WARNING: ^7Too few parameters. You must specify a property to edit"); + return TRUE; + } + + e = sandbox_ObjectEdit_Get(TRUE); + if(e != world) + { + switch(argv(2)) + { + case "skin": + e.skin = stof(argv(3)); + break; + case "alpha": + e.alpha = stof(argv(3)); + break; + case "color_main": + e.colormod = stov(argv(3)); + break; + case "color_glow": + e.glowmod = stov(argv(3)); + break; + case "frame": + e.frame = stof(argv(3)); + break; + case "scale": + sandbox_ObjectEdit_Scale(e, stof(argv(3))); + break; + case "solidity": + switch(argv(3)) + { + case "0": // non-solid + e.solid = SOLID_TRIGGER; + break; + case "1": // solid + e.solid = SOLID_BBOX; + break; + default: + break; + } + case "physics": + switch(argv(3)) + { + case "0": // static + e.movetype = MOVETYPE_NONE; + break; + case "1": // movable + e.movetype = MOVETYPE_TOSS; + break; + case "2": // physical + e.movetype = MOVETYPE_PHYSICS; + break; + default: + break; + } + break; + case "force": + e.damageforcescale = stof(argv(3)); + break; + case "material": + if(e.material) strunzone(e.material); + if(argv(3)) + { + for (i = 1; i <= 5; i++) // precache material sounds, 5 in total + precache_sound(strcat("object/impact_", argv(3), "_", ftos(i), ".ogg")); + e.material = strzone(argv(3)); + } + else + e.material = string_null; // no material + break; + default: + print_to(self, "^1SANDBOX - WARNING: ^7Invalid object property. For usage information, type 'sandbox help'"); + return TRUE; + } + + // update last editing time + if(e.message2) strunzone(e.message2); + e.message2 = strzone(strftime(TRUE, "%d-%m-%Y %H:%M:%S")); + + if(autocvar_g_sandbox_info > 1) + print(strcat("^3SANDBOX - SERVER: ^7", self.netname, " edited property ^3", argv(2), " ^7of an object at origin ^3", vtos(e.origin), "\n")); + return TRUE; + } + + print_to(self, "^1SANDBOX - WARNING: ^7Object could not be edited. Make sure you are facing an object that you have edit rights over"); + return TRUE; + + // ---------------- COMMAND: OBJECT, CLAIM ---------------- + case "object_claim": + // if the player can edit an object but is not its owner, this can be used to claim that object + if(self.crypto_idfp == "") + { + print_to(self, "^1SANDBOX - WARNING: ^7You do not have a player UID, and cannot claim objects"); + return TRUE; + } + e = sandbox_ObjectEdit_Get(TRUE); + if(e != world) + { + // update the owner's name + // Do this before checking if you're already the owner and skipping if such, so we + // also update the player's nickname if he changed it (but has the same player UID) + if(e.netname != self.netname) + { + if(e.netname) strunzone(e.netname); + e.netname = strzone(self.netname); + print_to(self, "^2SANDBOX - INFO: ^7Object owner name updated"); + } + + if(e.crypto_idfp == self.crypto_idfp) + { + print_to(self, "^2SANDBOX - INFO: ^7Object is already yours, nothing to claim"); + return TRUE; + } + + if(e.crypto_idfp) strunzone(e.crypto_idfp); + e.crypto_idfp = strzone(self.crypto_idfp); + + print_to(self, "^2SANDBOX - INFO: ^7Object claimed successfully"); + } + print_to(self, "^1SANDBOX - WARNING: ^7Object could not be claimed. Make sure you are facing an object that you have edit rights over"); + return TRUE; + + // ---------------- COMMAND: OBJECT, INFO ---------------- + case "object_info": + // prints public information about the object to the player + e = sandbox_ObjectEdit_Get(FALSE); + if(e != world) + { + switch(argv(2)) + { + case "object": + print_to(self, strcat("^2SANDBOX - INFO: ^7Object is owned by \"^7", e.netname, "^7\", created \"^3", e.message, "^7\", last edited \"^3", e.message2, "^7\"")); + return TRUE; + case "mesh": + for(i = 1; gettaginfo(e, i); i++) + s = strcat(s, "^7\"^5", gettaginfo_name, "^7\", "); + print_to(self, strcat("^2SANDBOX - INFO: ^7Object mesh is \"^3", e.model, "^7\" at animation frame ^3", ftos(e.frame), " ^7containing the following tags: ", s)); + return TRUE; + case "attachments": + // this should show the same info as 'mesh' but for attachments + entity head; + for(head = world; (head = find(head, classname, "object")); ) + { + if(head.owner == e) + { + ++i; // start from 1 + gettaginfo(e, head.tag_index); + s = strcat(s, "^1attachment ", ftos(i), "^7 has mesh \"^3", head.model, "^7\" at animation frame ^3", ftos(head.frame)); + s = strcat(s, "^7 and is attached to bone \"^5", gettaginfo_name, "^7\", "); + } + } + if(i) // object contains attachments + print_to(self, strcat("^2SANDBOX - INFO: ^7Object contains the following ^1", ftos(i), "^7 attachment(s): ", s)); + else + print_to(self, "^2SANDBOX - INFO: ^7Object contains no attachments"); + return TRUE; + } + } + print_to(self, "^1SANDBOX - WARNING: ^7No information could be found. Make sure you are facing an object"); + return TRUE; + + // ---------------- COMMAND: DEFAULT ---------------- + default: + print_to(self, "Invalid command. For usage information, type 'sandbox help'"); + return TRUE; + } + } + return FALSE; +} + +float autosave_time; +MUTATOR_HOOKFUNCTION(sandbox_StartFrame) +{ + if(!autocvar_g_sandbox_storage_autosave) + return FALSE; + if(time < autosave_time) + return FALSE; + autosave_time = time + autocvar_g_sandbox_storage_autosave; + + sandbox_Database_Save(); + + return TRUE; +} + +MUTATOR_DEFINITION(sandbox) +{ + MUTATOR_HOOK(SV_ParseClientCommand, sandbox_PlayerCommand, CBC_ORDER_ANY); + MUTATOR_HOOK(SV_StartFrame, sandbox_StartFrame, CBC_ORDER_ANY); + + MUTATOR_ONADD + { + autosave_time = time + autocvar_g_sandbox_storage_autosave; // don't save the first server frame + if(autocvar_g_sandbox_storage_autoload) + sandbox_Database_Load(); + } + + return FALSE; +} + diff --git a/qcsrc/server/nexball.qc b/qcsrc/server/nexball.qc index b1f59497ab..a068a33a54 100644 --- a/qcsrc/server/nexball.qc +++ b/qcsrc/server/nexball.qc @@ -79,7 +79,7 @@ void ball_restart (void) void nexball_setstatus (void) { - local entity oldself; + entity oldself; self.items &~= IT_KEY1; if (self.ballcarried) { @@ -118,7 +118,7 @@ void football_touch(); void DropOwner (void) { - local entity ownr; + entity ownr; ownr = self.owner; DropBall(self, ownr.origin, ownr.velocity); makevectors(ownr.v_angle_y * '0 1 0'); @@ -128,7 +128,7 @@ void DropOwner (void) void GiveBall (entity plyr, entity ball) { - local entity ownr; + entity ownr; if ((ownr = ball.owner)) { @@ -166,9 +166,8 @@ void GiveBall (entity plyr, entity ball) ball.effects |= EF_NOSHADOW; ball.scale = 1; // scale down. - WaypointSprite_AttachCarrier("nb-ball", plyr); + WaypointSprite_AttachCarrier("nb-ball", plyr, RADARICON_FLAGCARRIER, BALL_SPRITECOLOR); WaypointSprite_UpdateRule(plyr.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT); - WaypointSprite_UpdateTeamRadar(plyr.waypointsprite_attachedforcarrier, RADARICON_FLAGCARRIER, BALL_SPRITECOLOR); if (g_nexball_basketball_delay_hold) { @@ -201,10 +200,8 @@ void DropBall (entity ball, vector org, vector vel) } WaypointSprite_Kill(ball.owner.waypointsprite_attachedforcarrier); - //WaypointSprite_AttachCarrier("nb-ball", ball); - WaypointSprite_Spawn("nb-ball", 0, 0, ball, '0 0 64', world, ball.team, ball, waypointsprite_attachedforcarrier, FALSE); // no health bar please + WaypointSprite_Spawn("nb-ball", 0, 0, ball, '0 0 64', world, ball.team, ball, waypointsprite_attachedforcarrier, FALSE, RADARICON_FLAGCARRIER, BALL_SPRITECOLOR); // no health bar please WaypointSprite_UpdateRule(ball.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT); - WaypointSprite_UpdateTeamRadar(ball.waypointsprite_attachedforcarrier, RADARICON_FLAGCARRIER, BALL_SPRITECOLOR); ball.owner.ballcarried = world; ball.owner = world; @@ -225,7 +222,7 @@ void InitBall (void) self.teamtime = 0; self.pusher = world; self.team = FALSE; - sound (self, CHAN_PROJECTILE, self.noise1, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER, self.noise1, VOL_BASE, ATTN_NORM); WaypointSprite_Ping(self.waypointsprite_attachedforcarrier); LogNB("init", world); } @@ -265,7 +262,7 @@ void football_touch (void) if (other.solid == SOLID_BSP) { if (time > self.lastground + 0.1) { - sound (self, CHAN_PROJECTILE, self.noise, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTN_NORM); self.lastground = time; } if (vlen(self.velocity) && !self.cnt) @@ -311,7 +308,7 @@ void basketball_touch (void) LogNB("caught", other); GiveBall(other, self); } else if (other.solid == SOLID_BSP) { - sound (self, CHAN_PROJECTILE, self.noise, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTN_NORM); if (vlen(self.velocity) && !self.cnt) self.nextthink = min(time + g_nexball_delay_idle, self.teamtime); } @@ -369,7 +366,7 @@ void GoalTouch (void) pscore = 1; } - sound (ball, CHAN_AUTO, self.noise, VOL_BASE, ATTN_NONE); + sound (ball, CH_TRIGGER, self.noise, VOL_BASE, ATTN_NONE); if(ball.team && pscore) { @@ -410,14 +407,14 @@ void spawnfunc_nexball_team (void) void nb_spawnteam (string teamname, float teamcolor) { dprint("^2spawned team ", teamname, "\n"); - local entity e; + entity e; e = spawn(); e.classname = "nexball_team"; e.netname = teamname; e.cnt = teamcolor; e.team = e.cnt + 1; nb_teams += 1; -}; +} void nb_spawnteams (void) { @@ -491,8 +488,7 @@ void SpawnBall (void) precache_sound (self.noise1); precache_sound (self.noise2); - WaypointSprite_AttachCarrier("nb-ball", self); // the ball's team is not set yet, no rule update needed - WaypointSprite_UpdateTeamRadar(self.waypointsprite_attachedforcarrier, RADARICON_FLAGCARRIER, BALL_SPRITECOLOR); + WaypointSprite_AttachCarrier("nb-ball", self, RADARICON_FLAGCARRIER, BALL_SPRITECOLOR); // the ball's team is not set yet, no rule update needed self.reset = ball_restart; self.think = InitBall; @@ -596,19 +592,19 @@ void spawnfunc_ball_bound (void) { spawnfunc_nexball_out(); } void W_Nexball_Touch (void) { - local entity ball, attacker; + entity ball, attacker; attacker = self.owner; PROJECTILE_TOUCH; if(attacker.team != other.team || g_nexball_basketball_teamsteal) - if((ball = other.ballcarried) && (attacker.classname == "player" || attacker.classname == "gib")) + if((ball = other.ballcarried) && (attacker.classname == "player")) { other.velocity = other.velocity + normalize(self.velocity) * other.damageforcescale * autocvar_g_balance_nexball_secondary_force; other.flags &~= FL_ONGROUND; if(!attacker.ballcarried) { LogNB("stole", attacker); - sound (other, CHAN_AUTO, ball.noise2, VOL_BASE, ATTN_NORM); + sound (other, CH_TRIGGER, ball.noise2, VOL_BASE, ATTN_NORM); if(attacker.team == other.team && time > attacker.teamkill_complain) { @@ -625,12 +621,12 @@ void W_Nexball_Touch (void) void W_Nexball_Attack (float t) { - local entity ball; - local float mul, mi, ma; + entity ball; + float mul, mi, ma; if (!(ball = self.ballcarried)) return; - W_SetupShot (self, FALSE, 4, "nexball/shoot1.wav", CHAN_WEAPON, 0); + W_SetupShot (self, FALSE, 4, "nexball/shoot1.wav", CH_WEAPON_A, 0); tracebox(w_shotorg, BALL_MINS, BALL_MAXS, w_shotorg, MOVE_WORLDONLY, world); if(trace_startsolid) { @@ -658,10 +654,10 @@ void W_Nexball_Attack (float t) void W_Nexball_Attack2 (void) { - local entity missile; + entity missile; if (!(balls & BALL_BASKET)) return; - W_SetupShot (self, FALSE, 2, "nexball/shoot2.wav", CHAN_WEAPON, 0); + W_SetupShot (self, FALSE, 2, "nexball/shoot2.wav", CH_WEAPON_A, 0); // pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); missile = spawn (); @@ -721,10 +717,11 @@ float w_nexball_weapon(float req) { precache_model ("models/weapons/g_porto.md3"); precache_model ("models/weapons/v_porto.md3"); - precache_model ("models/weapons/h_porto.dpm"); + precache_model ("models/weapons/h_porto.iqm"); precache_model ("models/elaser.mdl"); precache_sound ("nexball/shoot1.wav"); precache_sound ("nexball/shoot2.wav"); + precache_sound ("misc/typehit.wav"); } else if (req == WR_SETUP) weapon_setup(WEP_PORTO); diff --git a/qcsrc/server/pathlib/pathlib.qh b/qcsrc/server/pathlib/pathlib.qh index 2616a77369..71d13caa4e 100644 --- a/qcsrc/server/pathlib/pathlib.qh +++ b/qcsrc/server/pathlib/pathlib.qh @@ -18,7 +18,6 @@ void pathlib_showpath2(entity path); entity openlist; entity closedlist; -entity edgelist; entity goal_node; entity start_node; @@ -106,7 +105,6 @@ var float pathlib_makenode(entity parent,vector start, vector to, vector goal,f var float buildpath_nodefilter(vector n,vector c,vector p); var float pathlib_wpp_waypointcallback(entity wp, entity wp_prev); -var const float pathlib_wpp_wpcb_null(); #ifdef DEBUGPATHING #include "debug.qc" diff --git a/qcsrc/server/playerstats.qc b/qcsrc/server/playerstats.qc index 7904e30ef1..672b031c11 100644 --- a/qcsrc/server/playerstats.qc +++ b/qcsrc/server/playerstats.qc @@ -1,8 +1,9 @@ float playerstats_db; +string teamstats_last; string playerstats_last; string events_last; .float playerstats_addedglobalinfo; -float playerstats_requested; +.string playerstats_id; void PlayerStats_Init() { @@ -15,18 +16,71 @@ void PlayerStats_Init() playerstats_db = db_create(); if(playerstats_db >= 0) playerstats_waitforme = FALSE; // must wait for it at match end - + + serverflags |= SERVERFLAG_PLAYERSTATS; + PlayerStats_AddEvent(PLAYERSTATS_ALIVETIME); - PlayerStats_AddEvent(PLAYERSTATS_KILLS); + PlayerStats_AddEvent(PLAYERSTATS_WINS); + PlayerStats_AddEvent(PLAYERSTATS_MATCHES); + PlayerStats_AddEvent(PLAYERSTATS_JOINS); + PlayerStats_AddEvent(PLAYERSTATS_SCOREBOARD_VALID); + PlayerStats_AddEvent(PLAYERSTATS_RANK); + + // accuracy stats + entity w; + float i; + for(i = WEP_FIRST; i <= WEP_LAST; ++i) + { + w = get_weaponinfo(i); + + PlayerStats_AddEvent(strcat("acc-", w.netname, "-hit")); + PlayerStats_AddEvent(strcat("acc-", w.netname, "-fired")); + + PlayerStats_AddEvent(strcat("acc-", w.netname, "-cnt-hit")); + PlayerStats_AddEvent(strcat("acc-", w.netname, "-cnt-fired")); + + PlayerStats_AddEvent(strcat("acc-", w.netname, "-frags")); + } + + PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_3); + PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_5); + PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_10); + PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_15); + PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_20); + PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_25); + PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_30); + PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_BOTLIKE); + PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD); + PlayerStats_AddEvent(PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM); } void PlayerStats_AddPlayer(entity e) { - if(!e.crypto_idfp || playerstats_db < 0) + string s; + + if(playerstats_db < 0) return; - + if(e.playerstats_id) + return; + + s = string_null; + if(e.crypto_idfp != "" && e.cvar_cl_allow_uidtracking == 1) + s = e.crypto_idfp; + else if(clienttype(e) == CLIENTTYPE_BOT) + s = sprintf("bot#%g#%s", skill, e.cleanname); + + if(!s || find(world, playerstats_id, s)) // already have one of the ID - next one can't be tracked then! + { + if(clienttype(e) == CLIENTTYPE_BOT) + s = sprintf("bot#%d", e.playerid); + else + s = sprintf("player#%d", e.playerid); + } + + e.playerstats_id = strzone(s); + string key; - key = sprintf("%s:*", e.crypto_idfp); + key = sprintf("%s:*", e.playerstats_id); string p; p = db_get(playerstats_db, key); @@ -39,7 +93,30 @@ void PlayerStats_AddPlayer(entity e) } else db_put(playerstats_db, key, "#"); - playerstats_last = strzone(e.crypto_idfp); + playerstats_last = strzone(e.playerstats_id); + } +} + +void PlayerStats_AddTeam(float t) // TODO: doesn't this remain unused? +{ + if(playerstats_db < 0) + return; + + string key; + key = sprintf("%d", t); + + string p; + p = db_get(playerstats_db, key); + if(p == "") + { + if(teamstats_last) + { + db_put(playerstats_db, key, teamstats_last); + strunzone(teamstats_last); + } + else + db_put(playerstats_db, key, "#"); + teamstats_last = strzone(key); } } @@ -68,31 +145,144 @@ void PlayerStats_AddEvent(string event_id) void PlayerStats_Event(entity e, string event_id, float value) { - if(!e.crypto_idfp || playerstats_db < 0) + if(!e.playerstats_id || playerstats_db < 0) return; string key; float val; - key = sprintf("%s:%s", e.crypto_idfp, event_id); + key = sprintf("%s:%s", e.playerstats_id, event_id); val = stof(db_get(playerstats_db, key)); val += value; db_put(playerstats_db, key, ftos(val)); } -void PlayerStats_Sent_URI_Get_Callback(float id, float status, string data) +void PlayerStats_TeamScore(float t, string event_id, float value) // TODO: doesn't this remain unused? { - if(playerstats_requested) - playerstats_waitforme = TRUE; + string key; + float val; + key = sprintf("team#%d:%s", t, event_id); + val = stof(db_get(playerstats_db, key)); + val += value; + db_put(playerstats_db, key, ftos(val)); } -//#NO AUTOCVARS START -void PlayerStats_Shutdown() +/* + format spec: + + A collection of lines of the format <key> SPACE <value> NEWLINE, where + <key> is always a single character. + + The following keys are defined: + + V: format version (always 1) - this MUST be the first line! + #: comment (MUST be ignored by any parser) + R: release information on the server + T: time at which the game ended + G: game type + M: map name + I: match ID (see "matchid" in g_world.qc + S: "hostname" of the server + C: number of "unpure" cvar changes + U: UDP port number of the server + P: player ID of an existing player; this also sets the owner for all following "n", "e" and "t" lines (lower case!) + n: nickname of the player (optional) + t: team ID + e: followed by an event name, a space, and the event count/score + event names can be: + alivetime: total playing time of the player + wins: number of games won (can only be set if matches is set) + matches: number of matches played to the end (not aborted by map switch) + joins: number of matches joined (always 1 unless player never played during the match) + scoreboardvalid: set to 1 if the player was there at the end of the match + total-<scoreboardname>: total score of that scoreboard item + scoreboard-<scoreboardname>: end-of-game score of that scoreboard item (can differ in non-team games) + achievement-<achievementname>: achievement counters + rank <number>: rank of player + acc-<weapon netname>-hit: total damage dealt + acc-<weapon netname>-fired: total damage that all fired projectiles *could* have dealt + acc-<weapon netname>-cnt-hit: amount of shots that actually hit + acc-<weapon netname>-cnt-fired: amount of fired shots + acc-<weapon netname>-frags: amount of frags dealt by weapon +*/ + +void PlayerStats_ready(entity fh, entity pass, float status) { string p, pn; string e, en; - string nn; - float b; - float i; + string nn, tt; + string s; + + switch(status) + { + case URL_READY_CANWRITE: + url_fputs(fh, "V 1\n"); +#ifdef WATERMARK + url_fputs(fh, sprintf("R %s\n", WATERMARK())); +#endif + url_fputs(fh, sprintf("T %s.%06d\n", strftime(FALSE, "%s"), floor(random() * 1000000))); + url_fputs(fh, sprintf("G %s\n", GetGametype())); + url_fputs(fh, sprintf("M %s\n", GetMapname())); + url_fputs(fh, sprintf("I %s\n", matchid)); + url_fputs(fh, sprintf("S %s\n", cvar_string("hostname"))); + url_fputs(fh, sprintf("C %d\n", cvar_purechanges_count)); + url_fputs(fh, sprintf("U %d\n", cvar("port"))); + for(p = playerstats_last; (pn = db_get(playerstats_db, sprintf("%s:*", p))) != ""; p = pn) + { + url_fputs(fh, sprintf("P %s\n", p)); + nn = db_get(playerstats_db, sprintf("%s:_playerid", p)); + if(nn != "") + url_fputs(fh, sprintf("i %s\n", nn)); + nn = db_get(playerstats_db, sprintf("%s:_netname", p)); + if(nn != "") + url_fputs(fh, sprintf("n %s\n", nn)); + if(teamplay) + { + tt = db_get(playerstats_db, sprintf("%s:_team", p)); + url_fputs(fh, sprintf("t %s\n", tt)); + } + for(e = events_last; (en = db_get(playerstats_db, sprintf("*:%s", e))) != ""; e = en) + { + float v; + v = stof(db_get(playerstats_db, sprintf("%s:%s", p, e))); + if(v != 0) + url_fputs(fh, sprintf("e %s %g\n", e, v)); + } + } + url_fputs(fh, "\n"); + url_fclose(fh); + break; + case URL_READY_CANREAD: + // url_fclose is processing, we got a response for writing the data + // this must come from HTTP + print("Got response from player stats server:\n"); + while((s = url_fgets(fh))) + print(" ", s, "\n"); + print("End of response.\n"); + url_fclose(fh); + break; + case URL_READY_CLOSED: + // url_fclose has finished + print("Player stats written\n"); + playerstats_waitforme = TRUE; + db_close(playerstats_db); + playerstats_db = -1; + break; + case URL_READY_ERROR: + default: + print("Player stats writing failed: ", ftos(status), "\n"); + playerstats_waitforme = TRUE; + if(playerstats_db >= 0) + { + db_close(playerstats_db); + playerstats_db = -1; + } + break; + } +} + +//#NO AUTOCVARS START +void PlayerStats_Shutdown() +{ string uri; if(playerstats_db < 0) @@ -101,59 +291,94 @@ void PlayerStats_Shutdown() uri = autocvar_g_playerstats_uri; if(uri != "") { - b = buf_create(); - i = 0; - - db_dump(playerstats_db, "foo.db"); - - bufstr_set(b, i++, "V 1"); - bufstr_set(b, i++, sprintf("T %s.%06d", strftime(FALSE, "%s"), floor(random() * 1000000))); - bufstr_set(b, i++, sprintf("G %s", GetGametype())); - bufstr_set(b, i++, sprintf("M %s", GetMapname())); - bufstr_set(b, i++, sprintf("S %s", cvar_string("hostname"))); - bufstr_set(b, i++, sprintf("C %d", cvar_purechanges_count)); - for(p = playerstats_last; (pn = db_get(playerstats_db, sprintf("%s:*", p))) != ""; p = pn) - { - bufstr_set(b, i++, sprintf("P %s", p)); - nn = db_get(playerstats_db, sprintf("%s:_netname", p)); - if(nn != "") - bufstr_set(b, i++, sprintf("n %s", nn)); - for(e = events_last; (en = db_get(playerstats_db, sprintf("*:%s", e))) != ""; e = en) - { - float v; - v = stof(db_get(playerstats_db, sprintf("%s:%s", p, e))); - bufstr_set(b, i++, sprintf("e %s %f", e, v)); - } - } - bufstr_set(b, i++, ""); - - if(crypto_uri_postbuf(uri, URI_GET_PLAYERSTATS_SENT, "text/plain", "\n", b, 0)) - playerstats_requested = TRUE; - else - playerstats_waitforme = TRUE; // if posting fails, we must continue anyway - - buf_del(b); + playerstats_waitforme = FALSE; + url_multi_fopen(uri, FILE_APPEND, PlayerStats_ready, world); } else + { playerstats_waitforme = TRUE; - - db_close(playerstats_db); - playerstats_db = -1; + db_close(playerstats_db); + playerstats_db = -1; + } } //#NO AUTOCVARS END +void PlayerStats_Accuracy(entity p) +{ + entity a, w; + a = p.accuracy; + float i; + + for(i = WEP_FIRST; i <= WEP_LAST; ++i) + { + w = get_weaponinfo(i); + + PlayerStats_Event(p, strcat("acc-", w.netname, "-hit"), a.(accuracy_hit[i-1])); + PlayerStats_Event(p, strcat("acc-", w.netname, "-fired"), a.(accuracy_fired[i-1])); + + PlayerStats_Event(p, strcat("acc-", w.netname, "-cnt-hit"), a.(accuracy_cnt_hit[i-1])); + PlayerStats_Event(p, strcat("acc-", w.netname, "-cnt-fired"), a.(accuracy_cnt_fired[i-1])); + + PlayerStats_Event(p, strcat("acc-", w.netname, "-frags"), a.(accuracy_frags[i-1])); + } +} + void PlayerStats_AddGlobalInfo(entity p) { if(playerstats_db < 0) return; - if(!p.crypto_idfp || playerstats_db < 0) + if(!p.playerstats_id || playerstats_db < 0) return; p.playerstats_addedglobalinfo = TRUE; // add global info! if(p.alivetime) + { PlayerStats_Event(p, PLAYERSTATS_ALIVETIME, time - p.alivetime); + p.alivetime = 0; + } + + db_put(playerstats_db, sprintf("%s:_playerid", p.playerstats_id), ftos(p.playerid)); - if(p.cvar_cl_allow_uid2name == 1) - db_put(playerstats_db, sprintf("%s:_netname", p.crypto_idfp), p.netname); + if(p.cvar_cl_allow_uid2name == 1 || clienttype(p) == CLIENTTYPE_BOT) + db_put(playerstats_db, sprintf("%s:_netname", p.playerstats_id), p.netname); + + if(teamplay) + db_put(playerstats_db, sprintf("%s:_team", p.playerstats_id), ftos(p.team)); + + if(stof(db_get(playerstats_db, sprintf("%d:%s", p.playerstats_id, PLAYERSTATS_ALIVETIME))) > 0) + PlayerStats_Event(p, PLAYERSTATS_JOINS, 1); + + PlayerStats_Accuracy(p); + + strunzone(p.playerstats_id); + p.playerstats_id = string_null; +} + +void PlayerStats_EndMatch(float finished) +{ + entity p, winner; + winner = PlayerScore_Sort(score_dummyfield); + FOR_EACH_CLIENT(p) // spectators intentionally not included + { + PlayerStats_Accuracy(p); + if(g_arena || g_lms || g_ca) + { + if(p.alivetime <= 0) + continue; + } + else + { + if(p.classname != "player") + continue; + } + PlayerScore_PlayerStats(p); + PlayerStats_Event(p, PLAYERSTATS_SCOREBOARD_VALID, 1); + if(finished) + { + PlayerStats_Event(p, PLAYERSTATS_WINS, p.winning); + PlayerStats_Event(p, PLAYERSTATS_MATCHES, 1); + PlayerStats_Event(p, PLAYERSTATS_RANK, p.score_dummyfield); + } + } } diff --git a/qcsrc/server/playerstats.qh b/qcsrc/server/playerstats.qh index fea546a123..b99366434b 100644 --- a/qcsrc/server/playerstats.qh +++ b/qcsrc/server/playerstats.qh @@ -1,6 +1,24 @@ // time the player was alive and kicking -string PLAYERSTATS_ALIVETIME = "alivetime"; -string PLAYERSTATS_KILLS = "kills"; +string PLAYERSTATS_ALIVETIME = "alivetime"; +string PLAYERSTATS_WINS = "wins"; +string PLAYERSTATS_MATCHES = "matches"; +string PLAYERSTATS_JOINS = "joins"; +string PLAYERSTATS_SCOREBOARD_VALID = "scoreboardvalid"; +string PLAYERSTATS_RANK = "rank"; + +string PLAYERSTATS_TOTAL = "total-"; +string PLAYERSTATS_SCOREBOARD = "scoreboard-"; + +string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_3 = "achievement-kill-spree-3"; +string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_5 = "achievement-kill-spree-5"; +string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_10 = "achievement-kill-spree-10"; +string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_15 = "achievement-kill-spree-15"; +string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_20 = "achievement-kill-spree-20"; +string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_25 = "achievement-kill-spree-25"; +string PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_30 = "achievement-kill-spree-30"; +string PLAYERSTATS_ACHIEVEMENT_BOTLIKE = "achievement-botlike"; +string PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD = "achievement-firstblood"; +string PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM = "achievement-firstvictim"; // delay map switch until this is set float playerstats_waitforme; @@ -11,17 +29,23 @@ void PlayerStats_Init(); // add a new player void PlayerStats_AddPlayer(entity e); +// add a new team +void PlayerStats_AddTeam(float t); + // add a new event void PlayerStats_AddEvent(string event_id); // call on each event to track, or at player disconnect OR match end for "global stuff" void PlayerStats_Event(entity e, string event_id, float value); +// add a team score +void PlayerStats_TeamScore(float t, string event_id, float value); + // call at game over void PlayerStats_Shutdown(); // send stats to the server -// URI GET callback -void PlayerStats_Sent_URI_Get_Callback(float id, float status, string data); - // call this whenever a player leaves void PlayerStats_AddGlobalInfo(entity p); + +// call this at the end of the match +void PlayerStats_EndMatch(float finished); diff --git a/qcsrc/server/portals.qc b/qcsrc/server/portals.qc index 0ce3d515a1..bf50c9d3ca 100644 --- a/qcsrc/server/portals.qc +++ b/qcsrc/server/portals.qc @@ -7,6 +7,7 @@ .vector portal_safe_origin; .float portal_wants_to_vanish; .float portal_activatetime; +.float savemodelindex; float PlayerEdgeDistance(entity p, vector v) { @@ -355,7 +356,7 @@ void Portal_Disconnect(entity teleporter, entity destination) void Portal_Connect(entity teleporter, entity destination) { - teleporter.portal_transform = AnglesTransform_Divide(AnglesTransform_TurnDirectionFR(destination.mangle), teleporter.mangle); + teleporter.portal_transform = AnglesTransform_RightDivide(AnglesTransform_TurnDirectionFR(destination.mangle), teleporter.mangle); teleporter.enemy = destination; destination.enemy = teleporter; @@ -394,14 +395,14 @@ void Portal_Remove(entity portal, float killed) if(killed) { fixedmakevectors(portal.mangle); - sound(portal, CHAN_PROJECTILE, "porto/explode.wav", VOL_BASE, ATTN_NORM); + sound(portal, CH_SHOTS, "porto/explode.wav", VOL_BASE, ATTN_NORM); pointparticles(particleeffectnum("rocket_explode"), portal.origin + v_forward * 16, v_forward * 1024, 4); remove(portal); } else { Portal_MakeBrokenPortal(portal); - sound(portal, CHAN_PROJECTILE, "porto/expire.wav", VOL_BASE, ATTN_NORM); + sound(portal, CH_SHOTS, "porto/expire.wav", VOL_BASE, ATTN_NORM); SUB_SetFade(portal, time, 0.5); } } @@ -479,7 +480,7 @@ float Portal_Customize() other = other.enemy; if(other == self.aiment) { - self.modelindex = self.modelindex_lod0; + self.modelindex = self.savemodelindex; } else if(IS_INDEPENDENT_PLAYER(other) || IS_INDEPENDENT_PLAYER(self.aiment)) { @@ -487,7 +488,7 @@ float Portal_Customize() } else { - self.modelindex = self.modelindex_lod0; + self.modelindex = self.savemodelindex; } return TRUE; } @@ -617,7 +618,7 @@ entity Portal_Spawn(entity own, vector org, vector ang) portal.fade_time = time + autocvar_g_balance_portal_lifetime; portal.health = autocvar_g_balance_portal_health; setmodel(portal, "models/portal.md3"); - portal.modelindex_lod0 = portal.modelindex; + portal.savemodelindex = portal.modelindex; portal.customizeentityforclient = Portal_Customize; if(!Portal_FindSafeOrigin(portal)) diff --git a/qcsrc/server/post-builtins.qh b/qcsrc/server/post-builtins.qh deleted file mode 100644 index ad554d2ccc..0000000000 --- a/qcsrc/server/post-builtins.qh +++ /dev/null @@ -1,3 +0,0 @@ -#undef cvar -#undef cvar_string -#undef cvar_set diff --git a/qcsrc/server/pre-builtins.qh b/qcsrc/server/pre-builtins.qh deleted file mode 100644 index 764fa38362..0000000000 --- a/qcsrc/server/pre-builtins.qh +++ /dev/null @@ -1,6 +0,0 @@ -var float(string var) cvar; -var string(string var) cvar_string; -var void(string var, string val) cvar_set; -#define cvar cvar_builtin -#define cvar_string cvar_string_builtin -#define cvar_set cvar_set_builtin diff --git a/qcsrc/server/progs.src b/qcsrc/server/progs.src index c76395fdbc..9a459c5fd4 100644 --- a/qcsrc/server/progs.src +++ b/qcsrc/server/progs.src @@ -1,12 +1,10 @@ ../../progs.dat // output filename ../common/util-pre.qh - -sys.qh -pre-builtins.qh -builtins.qh -extensions.qh -post-builtins.qh +sys-pre.qh +../dpdefs/progsdefs.qc +../dpdefs/dpextensions.qc +sys-post.qh ../warpzonelib/anglestransform.qh ../warpzonelib/mathlib.qh @@ -17,6 +15,12 @@ post-builtins.qh ../common/constants.qh ../common/util.qh ../common/items.qh +../common/explosion_equation.qh +../common/urllib.qh +../common/command/markup.qh +../common/command/rpn.qh +../common/command/generic.qh +../common/command/shared_defs.qh autocvars.qh constants.qh @@ -29,14 +33,25 @@ mutators/mutator_dodging.qh //// tZork Turrets //// tturrets/include/turrets_early.qh +vehicles/vehicles_def.qh campaign.qh ../common/campaign_common.qh ../common/mapinfo.qh -../common/util.qc + +command/common.qh +command/banning.qh +command/radarmap.qh +command/vote.qh +command/getreplies.qh +command/cmd.qh +command/sv_cmd.qh accuracy.qh csqcprojectile.qh +../common/csqcmodel_settings.qh +../csqcmodellib/common.qh +../csqcmodellib/sv_model.qh csqceffects.qc anticheat.qh @@ -57,10 +72,12 @@ race.qh antilag.qh -vote.qh - playerdemo.qh +// singleplayer stuff +item_key.qh +secret.qh + scores_rules.qc miscfunctions.qc @@ -95,11 +112,14 @@ t_jumppads.qc t_teleporters.qc sv_main.qc -sv_stats.qc g_triggers.qc g_models.qc +// singleplayer stuff +item_key.qc +secret.qc + cl_weaponsystem.qc w_common.qc @@ -124,16 +144,21 @@ g_hook.qc t_swamp.qc -clientcommands.qc - -vote.qc - campaign.qc ../common/campaign_file.qc ../common/campaign_setup.qc - -../common/gamecommand.qc -gamecommand.qc +../common/urllib.qc + +../common/command/markup.qc +../common/command/rpn.qc +../common/command/generic.qc +command/common.qc +command/banning.qc +command/radarmap.qc +command/vote.qc +command/getreplies.qc +command/cmd.qc +command/sv_cmd.qc assault.qc @@ -141,9 +166,6 @@ ipban.qc ../common/mapinfo.qc - - - t_quake3.qc t_halflife.qc t_quake.qc @@ -165,12 +187,9 @@ target_music.qc ../common/items.qc -monsters/defs.qc -monsters/fight.qc -monsters/ai.qc -monsters/m_monsters.qc -monsters/monster_zombie.qc + accuracy.qc +../csqcmodellib/sv_model.qc csqcprojectile.qc playerdemo.qc @@ -179,17 +198,26 @@ anticheat.qc cheats.qc playerstats.qc +../common/explosion_equation.qc + mutators/base.qc mutators/gamemode_keyhunt.qc mutators/gamemode_freezetag.qc mutators/gamemode_keepaway.qc +mutators/mutator_invincibleproj.qc mutators/mutator_nix.qc mutators/mutator_dodging.qc mutators/mutator_rocketflying.qc mutators/mutator_vampire.qc +mutators/mutator_spawn_near_teammate.qc +mutators/sandbox.qc ../warpzonelib/anglestransform.qc ../warpzonelib/mathlib.qc ../warpzonelib/common.qc ../warpzonelib/util_server.qc ../warpzonelib/server.qc + +../common/util.qc + +../common/if-this-file-errors-scroll-up-and-fix-the-warnings.fteqccfail diff --git a/qcsrc/server/race.qc b/qcsrc/server/race.qc index 9817b3b0e1..911106a305 100644 --- a/qcsrc/server/race.qc +++ b/qcsrc/server/race.qc @@ -635,7 +635,7 @@ void trigger_race_checkpoint_verify() // race only (middle of the race) g_race_qualifying = 0; self.race_place = 0; - if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), world, 0, FALSE, FALSE)) + if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), 0, FALSE)) error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(self.race_place), " (used for respawning in race) - bailing out")); if(i == 0) @@ -643,7 +643,7 @@ void trigger_race_checkpoint_verify() // qualifying only g_race_qualifying = 1; self.race_place = race_lowest_place_spawn; - if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), world, 0, FALSE, FALSE)) + if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), 0, FALSE)) error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(self.race_place), " (used for qualifying) - bailing out")); // race only (initial spawn) @@ -651,7 +651,7 @@ void trigger_race_checkpoint_verify() for(p = 1; p <= race_highest_place_spawn; ++p) { self.race_place = p; - if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), world, 0, FALSE, FALSE)) + if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), 0, FALSE)) error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(self.race_place), " (used for initially spawning in race) - bailing out")); } } @@ -663,7 +663,7 @@ void trigger_race_checkpoint_verify() self.race_checkpoint = race_NextCheckpoint(0); g_race_qualifying = 1; self.race_place = race_lowest_place_spawn; - if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), world, 0, FALSE, FALSE)) + if(!Spawn_FilterOutBadSpots(findchain(classname, "info_player_deathmatch"), 0, FALSE)) error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(self.race_place), " (used for qualifying) - bailing out")); } else @@ -764,6 +764,38 @@ void trigger_race_checkpoint_verify() self = oldself; } +vector trigger_race_checkpoint_spawn_evalfunc(entity player, entity spot, vector current) +{ + if(g_race_qualifying) + { + // spawn at first + if(self.race_checkpoint != 0) + return '-1 0 0'; + if(spot.race_place != race_lowest_place_spawn) + return '-1 0 0'; + } + else + { + if(self.race_checkpoint != player.race_respawn_checkpoint) + return '-1 0 0'; + // try reusing the previous spawn + if(self == player.race_respawn_spotref || spot == player.race_respawn_spotref) + current_x += SPAWN_PRIO_RACE_PREVIOUS_SPAWN; + if(self.race_checkpoint == 0) + { + float pl; + pl = player.race_place; + if(pl > race_highest_place_spawn) + pl = 0; + if(pl == 0 && !player.race_started) + pl = race_highest_place_spawn; // use last place if he has not even touched finish yet + if(spot.race_place != pl) + return '-1 0 0'; + } + } + return current; +} + void spawnfunc_trigger_race_checkpoint() { vector o; @@ -805,12 +837,13 @@ void spawnfunc_trigger_race_checkpoint() if(!self.race_penalty) { if(self.race_checkpoint) - WaypointSprite_SpawnFixed("race-checkpoint", o, self, sprite); + WaypointSprite_SpawnFixed("race-checkpoint", o, self, sprite, RADARICON_NONE, '1 0.5 0'); else - WaypointSprite_SpawnFixed("race-finish", o, self, sprite); + WaypointSprite_SpawnFixed("race-start-finish", o, self, sprite, RADARICON_NONE, '1 0.5 0'); } self.sprite.waypointsprite_visible_for_player = race_waypointsprite_visible_for_player; + self.spawn_evalfunc = trigger_race_checkpoint_spawn_evalfunc; InitializeEntity(self, trigger_race_checkpoint_verify, INITPRIO_FINDTARGET); } @@ -851,9 +884,9 @@ void spawnfunc_target_checkpoint() // defrag entity race_timed_checkpoint = 1; if(self.race_checkpoint == 0) - WaypointSprite_SpawnFixed("race-start", o, self, sprite); + WaypointSprite_SpawnFixed("race-start", o, self, sprite, RADARICON_NONE, '1 0.5 0'); else - WaypointSprite_SpawnFixed("race-checkpoint", o, self, sprite); + WaypointSprite_SpawnFixed("race-checkpoint", o, self, sprite, RADARICON_NONE, '1 0.5 0'); self.sprite.waypointsprite_visible_for_player = race_waypointsprite_visible_for_player; diff --git a/qcsrc/server/scores.qc b/qcsrc/server/scores.qc index 2c5e2b1449..b56065deda 100644 --- a/qcsrc/server/scores.qc +++ b/qcsrc/server/scores.qc @@ -56,7 +56,7 @@ float TeamScore_SendEntity(entity to, float sendflags) longflags = 0; for(i = 0, p = 1; i < MAX_TEAMSCORE; ++i, p *= 2) - if(self.teamscores[i] > 127 || self.teamscores[i] <= -128) + if(self.(teamscores[i]) > 127 || self.(teamscores[i]) <= -128) longflags |= p; #if MAX_TEAMSCORE <= 8 @@ -70,9 +70,9 @@ float TeamScore_SendEntity(entity to, float sendflags) if(sendflags & p) { if(longflags & p) - WriteInt24_t(MSG_ENTITY, self.teamscores[i]); + WriteInt24_t(MSG_ENTITY, self.(teamscores[i])); else - WriteChar(MSG_ENTITY, self.teamscores[i]); + WriteChar(MSG_ENTITY, self.(teamscores[i])); } return TRUE; @@ -88,6 +88,7 @@ void TeamScore_Spawn(float t, string name) Net_LinkEntity(ts, FALSE, 0, TeamScore_SendEntity); teamscorekeepers[t - 1] = ts; ++teamscores_entities_count; + PlayerStats_AddTeam(t); } float TeamScore_AddToTeam(float t, float scorefield, float score) @@ -150,6 +151,11 @@ void ScoreInfo_SetLabel_PlayerScore(float i, string label, float scoreflags) scores_primary = scores[i]; scores_flags_primary = scoreflags; } + if(label != "") + { + PlayerStats_AddEvent(strcat(PLAYERSTATS_TOTAL, label)); + PlayerStats_AddEvent(strcat(PLAYERSTATS_SCOREBOARD, label)); + } } void ScoreInfo_SetLabel_TeamScore(float i, string label, float scoreflags) @@ -167,7 +173,7 @@ float ScoreInfo_SendEntity(entity to, float sf) { float i; WriteByte(MSG_ENTITY, ENT_CLIENT_SCORES_INFO); - WriteByte(MSG_ENTITY, game); + WriteInt24_t(MSG_ENTITY, MapInfo_LoadedGametype); for(i = 0; i < MAX_SCORE; ++i) { WriteString(MSG_ENTITY, scores_label[i]); @@ -216,7 +222,7 @@ float PlayerScore_SendEntity(entity to, float sendflags) longflags = 0; for(i = 0, p = 1; i < MAX_SCORE; ++i, p *= 2) - if(self.scores[i] > 127 || self.scores[i] <= -128) + if(self.(scores[i]) > 127 || self.(scores[i]) <= -128) longflags |= p; #if MAX_SCORE <= 8 @@ -230,9 +236,9 @@ float PlayerScore_SendEntity(entity to, float sendflags) if(sendflags & p) { if(longflags & p) - WriteInt24_t(MSG_ENTITY, self.scores[i]); + WriteInt24_t(MSG_ENTITY, self.(scores[i])); else - WriteChar(MSG_ENTITY, self.scores[i]); + WriteChar(MSG_ENTITY, self.(scores[i])); } return TRUE; @@ -245,6 +251,7 @@ void PlayerScore_Clear(entity player) if(teamscores_entities_count) return; + if(g_lms) return; if(g_arena || g_ca) return; if(g_race && !g_race_qualifying) return; @@ -330,6 +337,8 @@ float PlayerScore_Add(entity player, float scorefield, float score) if(score) if(scores_label[scorefield] != "") s.SendFlags |= pow(2, scorefield); + if(!inWarmupStage) + PlayerStats_Event(s.owner, strcat(PLAYERSTATS_TOTAL, scores_label[scorefield]), score); return (s.(scores[scorefield]) += score); } @@ -367,9 +376,17 @@ void WinningConditionHelper() entity secondscorekeeper; entity sk; + // format: + // gametype:P<pure>:S<slots>::plabel,plabel:tlabel,tlabel:teamid:tscore,tscore:teamid:tscore,tscore + // score labels always start with a symbol or with lower case + // so to match pure, match for :P0: + // to match full, match for :S0: + s = GetGametype(); s = strcat(s, ":", autocvar_g_xonoticversion); s = strcat(s, ":P", ftos(cvar_purechanges_count)); + s = strcat(s, ":S", ftos(nJoinAllowed(0))); + s = strcat(s, ":F", ftos(serverflags)); s = strcat(s, "::", GetPlayerScoreString(world, 1)); // make this 1 once we can, note: this doesn't contain any :<letter> fullstatus = autocvar_g_full_getstatus_responses; @@ -864,3 +881,30 @@ void Score_NicePrint(entity to) } } +void PlayerScore_PlayerStats(entity p) +{ + entity s; + float i; + s = p.scorekeeper; + + for(i = 0; i < MAX_SCORE; ++i) + if(s.(scores[i]) != 0) + if(scores_label[i] != "") + PlayerStats_Event(s.owner, strcat(PLAYERSTATS_SCOREBOARD, scores_label[i]), s.(scores[i])); +} + +void PlayerScore_TeamStats(void) +{ + entity sk; + float t, i; + for(t = 0; t < 16; ++t) + { + sk = teamscorekeepers[t]; + if(!sk) + continue; + for(i = 0; i < MAX_TEAMSCORE; ++i) + if(sk.(teamscores[i]) != 0) + if(teamscores_label[i] != "") + PlayerStats_TeamScore(t, strcat(PLAYERSTATS_SCOREBOARD, teamscores_label[i]), sk.(teamscores[i])); + } +} diff --git a/qcsrc/server/scores_rules.qc b/qcsrc/server/scores_rules.qc index a4c993d83f..806e245079 100644 --- a/qcsrc/server/scores_rules.qc +++ b/qcsrc/server/scores_rules.qc @@ -17,12 +17,12 @@ void ScoreRules_basics(float teams, float sprio, float stprio, float score_enabl if(score_enabled) ScoreInfo_SetLabel_TeamScore (ST_SCORE, "score", stprio); - if not(independent_players) + if not(INDEPENDENT_PLAYERS) ScoreInfo_SetLabel_PlayerScore(SP_KILLS, "kills", 0); ScoreInfo_SetLabel_PlayerScore(SP_DEATHS, "deaths", SFL_LOWER_IS_BETTER); - if not(independent_players) + if not(INDEPENDENT_PLAYERS) ScoreInfo_SetLabel_PlayerScore(SP_SUICIDES, "suicides", SFL_LOWER_IS_BETTER); if(score_enabled) @@ -34,8 +34,7 @@ void ScoreRules_basics_end() } void ScoreRules_generic() { - CheckAllowedTeams(world); - if(teams_matter) + if(teamplay) { CheckAllowedTeams(world); ScoreRules_basics(((c4>=0) ? 4 : (c3>=0) ? 3 : 2), SFL_SORT_PRIO_PRIMARY, SFL_SORT_PRIO_PRIMARY, TRUE); @@ -54,27 +53,9 @@ void ScoreRules_generic() #define SP_CTF_RETURNS 8 void ScoreRules_ctf() { - float sp_score, sp_caps; - sp_score = sp_caps = 0; - switch(g_ctf_win_mode) - { - case 0: // caps only - sp_caps = SFL_SORT_PRIO_PRIMARY; - break; - case 1: // caps, then score - sp_caps = SFL_SORT_PRIO_PRIMARY; - sp_score = SFL_SORT_PRIO_SECONDARY; - break; - case 2: // score only - default: - sp_caps = SFL_SORT_PRIO_SECONDARY; // looks better ;) - sp_score = SFL_SORT_PRIO_PRIMARY; - break; - } - CheckAllowedTeams(world); - ScoreRules_basics(2 + (c3>=0), SFL_SORT_PRIO_PRIMARY, sp_score, TRUE); // NOTE this assumes that the rogue team is team 3 - ScoreInfo_SetLabel_TeamScore (ST_CTF_CAPS, "caps", sp_caps); + ScoreRules_basics(2 + (c3>=0), SFL_SORT_PRIO_PRIMARY, 0, TRUE); // NOTE this assumes that the rogue team is team 3 + ScoreInfo_SetLabel_TeamScore (ST_CTF_CAPS, "caps", SFL_SORT_PRIO_PRIMARY); ScoreInfo_SetLabel_PlayerScore(SP_CTF_CAPS, "caps", SFL_SORT_PRIO_SECONDARY); ScoreInfo_SetLabel_PlayerScore(SP_CTF_PICKUPS, "pickups", 0); ScoreInfo_SetLabel_PlayerScore(SP_CTF_FCKILLS, "fckills", 0); @@ -191,14 +172,22 @@ void ScoreRules_nexball(float teams) // Keep Away stuff #define SP_KEEPAWAY_PICKUPS 4 #define SP_KEEPAWAY_CARRIERKILLS 5 -#define SP_KEEPAWAY_DROPS 6 -#define SP_KEEPAWAY_SCORE 7 +#define SP_KEEPAWAY_BCTIME 6 void ScoreRules_keepaway() { - ScoreRules_basics(0, SFL_SORT_PRIO_PRIMARY, 0, FALSE); // SFL_SORT_PRIO_PRIMARY - ScoreInfo_SetLabel_PlayerScore(SP_KEEPAWAY_SCORE, "score", SFL_SORT_PRIO_PRIMARY); - ScoreInfo_SetLabel_PlayerScore(SP_KEEPAWAY_PICKUPS, "pickups", 0); + ScoreRules_basics(0, SFL_SORT_PRIO_PRIMARY, 0, TRUE); // SFL_SORT_PRIO_PRIMARY + ScoreInfo_SetLabel_PlayerScore(SP_KEEPAWAY_PICKUPS, "pickups", 0); ScoreInfo_SetLabel_PlayerScore(SP_KEEPAWAY_CARRIERKILLS, "bckills", 0); - ScoreInfo_SetLabel_PlayerScore(SP_KEEPAWAY_DROPS, "drops", SFL_LOWER_IS_BETTER); + ScoreInfo_SetLabel_PlayerScore(SP_KEEPAWAY_BCTIME, "bctime", SFL_SORT_PRIO_SECONDARY); + ScoreRules_basics_end(); +} + +// FreezeTag stuff +#define SP_FREEZETAG_REVIVALS 4 +void ScoreRules_freezetag() +{ + CheckAllowedTeams(world); + ScoreRules_basics(((c4>=0) ? 4 : (c3>=0) ? 3 : 2), SFL_SORT_PRIO_PRIMARY, SFL_SORT_PRIO_PRIMARY, TRUE); // SFL_SORT_PRIO_PRIMARY + ScoreInfo_SetLabel_PlayerScore(SP_FREEZETAG_REVIVALS, "revivals", 0); ScoreRules_basics_end(); } diff --git a/qcsrc/server/secret.qc b/qcsrc/server/secret.qc new file mode 100644 index 0000000000..2694cb3d6f --- /dev/null +++ b/qcsrc/server/secret.qc @@ -0,0 +1,76 @@ + + +void secrets_setstatus() { + self.stat_secrets_total = secrets_total; + self.stat_secrets_found = secrets_found; +} + +/** + * A secret has been found (maybe :P) + */ +void trigger_secret_touch() { + // only a player can trigger this + if (other.classname != "player") + return; + + // update secrets found counter + secrets_found += 1; + //print("Secret found: ", ftos(secret_counter.cnt), "/"); + //print(ftos(secret_counter.count), "\n"); + + // centerprint message (multi_touch() doesn't always call centerprint()) + centerprint(other, self.message); + self.message = ""; + + // handle normal trigger features + multi_touch(); + remove(self); +} + +/*QUAKED trigger_secret (.5 .5 .5) ? +Variable sized secret trigger. Can be targeted at one or more entities. +Basically, it's a trigger_once (with restrictions, see notes) that additionally updates the number of secrets found. +-------- KEYS -------- +sounds: 1 to play misc/secret.wav, 2 to play misc/talk.wav, 3 to play misc/trigger1.wav (default: 1) +noise: path to sound file, if you want to play something else +target: trigger all entities with this targetname when triggered +message: print this message to the player who activated the trigger instead of the standard 'You found a secret!' +killtarget: remove all entities with this targetname when triggered +-------- NOTES -------- +You should create a common/trigger textured brush covering the entrance to a secret room/area. +Trigger secret can only be trigger by a player's touch and can not be a target itself. +*/ +void spawnfunc_trigger_secret() { + // FIXME: should it be disabled in most modes? + + // update secrets count + secrets_total += 1; + + // add default message + if (self.message == "") + self.message = "You found a secret!"; + + // set default sound + if (self.noise == "") + if not(self.sounds) + self.sounds = 1; // misc/secret.wav + + // this entity can't be a target itself!!!! + self.targetname = ""; + + // you can't just shoot a room to find it, can you? + self.health = 0; + + // a secret can not be delayed + self.delay = 0; + + // convert this trigger to trigger_once + self.classname = "trigger_once"; + spawnfunc_trigger_once(); + + // take over the touch() function, so we can mark secret as found + self.touch = trigger_secret_touch; + // ignore triggering; + self.use = SUB_Null; +} + diff --git a/qcsrc/server/secret.qh b/qcsrc/server/secret.qh new file mode 100644 index 0000000000..dd94b19219 --- /dev/null +++ b/qcsrc/server/secret.qh @@ -0,0 +1,19 @@ +/** + * Total number of secrets on the map. + */ +float secrets_total; + +/** + * Total numbe of secrets found on the map. + */ +float secrets_found; + + +.float stat_secrets_total; +.float stat_secrets_found; + +/** + * update secrets status. + */ +void secrets_setstatus(); + diff --git a/qcsrc/server/steerlib.qc b/qcsrc/server/steerlib.qc index d512cf95f2..a586252555 100644 --- a/qcsrc/server/steerlib.qc +++ b/qcsrc/server/steerlib.qc @@ -424,7 +424,7 @@ vector steerlib_beamsteer(vector dir, float length, float step, float step_up, f vr = vectoangles(dir); //vr_x *= -1; - tracebox(self.origin , self.mins,self.maxs,self.origin + (dir * length) ,MOVE_NOMONSTERS,self); + tracebox(self.origin + '0 0 1' * step_up, self.mins, self.maxs, ('0 0 1' * step_up) + self.origin + (dir * length), MOVE_NOMONSTERS, self); if(trace_fraction == 1.0) { //te_lightning1(self,self.origin,self.origin + (dir * length)); @@ -493,8 +493,6 @@ vector steerlib_beamsteer(vector dir, float length, float step, float step_up, f #ifdef TLIBS_TETSLIBS void flocker_die() { - sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); - pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1); self.owner.cnt += 1; diff --git a/qcsrc/server/sv_main.qc b/qcsrc/server/sv_main.qc index c73f0355f8..73c444afec 100644 --- a/qcsrc/server/sv_main.qc +++ b/qcsrc/server/sv_main.qc @@ -1,26 +1,31 @@ - void CreatureFrame (void) { - local entity oldself; - local float dm, maxspeed; + entity oldself; + float dm; + oldself = self; - self = findfloat(world, iscreature, TRUE); - while (self) + for(self = world; (self = findfloat(self, damagedbycontents, TRUE)); ) { - if (self.movetype != MOVETYPE_NOCLIP) + if (self.movetype == MOVETYPE_NOCLIP) { continue; } + + float vehic = (self.vehicle_flags & VHF_ISVEHICLE); + float projectile = (self.flags & FL_PROJECTILE); + + if (self.watertype <= CONTENT_WATER && self.waterlevel > 0) // workaround a retarded bug made by id software :P (yes, it's that old of a bug) { - if (self.waterlevel) + if (!(self.flags & FL_INWATER)) + { + self.flags |= FL_INWATER; + self.dmgtime = 0; + } + + if(!vehic && !projectile) // vehicles and projectiles don't drown { - if (!(self.flags & FL_INWATER)) - { - self.flags |= FL_INWATER; - self.dmgtime = 0; - } if (self.waterlevel != WATERLEVEL_SUBMERGED) { - if(self.air_finished < time + 9) - PlayerSound(playersound_gasp, CHAN_PLAYER, VOICETYPE_PLAYERSOUND); - self.air_finished = time + 12; + if(self.air_finished < time) + PlayerSound(playersound_gasp, CH_PLAYER, VOICETYPE_PLAYERSOUND); + self.air_finished = time + autocvar_g_balance_contents_drowndelay; self.dmg = 2; } else if (self.air_finished < time) @@ -28,48 +33,62 @@ void CreatureFrame (void) if (!self.deadflag) if (self.pain_finished < time) { - Damage (self, world, world, 5, DEATH_DROWN, self.origin, '0 0 0'); + Damage (self, world, world, autocvar_g_balance_contents_playerdamage_drowning * autocvar_g_balance_contents_damagerate, DEATH_DROWN, self.origin, '0 0 0'); self.pain_finished = time + 0.5; } } - if (self.dmgtime < time) + } + + if (self.dmgtime < time) + { + self.dmgtime = time + autocvar_g_balance_contents_damagerate; + + if (!projectile) { - self.dmgtime = time + 0.2; if (self.watertype == CONTENT_LAVA) { if (self.watersound_finished < time) { self.watersound_finished = time + 0.5; - sound (self, CHAN_PLAYER, "player/lava.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_PLAYER, "player/lava.wav", VOL_BASE, ATTN_NORM); } - Damage (self, world, world, 6 * self.waterlevel, DEATH_LAVA, self.origin, '0 0 0'); + Damage (self, world, world, autocvar_g_balance_contents_playerdamage_lava * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_LAVA, self.origin, '0 0 0'); } else if (self.watertype == CONTENT_SLIME) { if (self.watersound_finished < time) { self.watersound_finished = time + 0.5; - sound (self, CHAN_PLAYER, "player/slime.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_PLAYER, "player/slime.wav", VOL_BASE, ATTN_NORM); } - Damage (self, world, world, 2 * self.waterlevel, DEATH_SLIME, self.origin, '0 0 0'); + Damage (self, world, world, autocvar_g_balance_contents_playerdamage_slime * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_SLIME, self.origin, '0 0 0'); } } - } - else - { - if (self.flags & FL_INWATER) + else if ((self.watertype == CONTENT_LAVA) || (self.watertype == CONTENT_SLIME)) { - // play leave water sound - self.flags &~= FL_INWATER; - self.dmgtime = 0; + Damage (self, world, world, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_SLIME, self.origin, '0 0 0'); } - self.air_finished = time + 12; - self.dmg = 2; } + } + else + { + if (self.flags & FL_INWATER) + { + // play leave water sound + self.flags &~= FL_INWATER; + self.dmgtime = 0; + } + self.air_finished = time + 12; + self.dmg = 2; + } + + if(!vehic && !projectile) // vehicles don't get falling damage + { // check for falling damage + float velocity_len = vlen(self.velocity); if(!self.hook.state && !g_ca && !(g_cts && !autocvar_g_cts_selfdamage)) { - dm = vlen(self.oldvelocity) - vlen(self.velocity); // dm is now the velocity DECREASE. Velocity INCREASE should never cause a sound or any damage. + dm = vlen(self.oldvelocity) - velocity_len; // dm is now the velocity DECREASE. Velocity INCREASE should never cause a sound or any damage. if (self.deadflag) dm = (dm - autocvar_g_balance_falldamage_deadminspeed) * autocvar_g_balance_falldamage_factor; else @@ -78,15 +97,13 @@ void CreatureFrame (void) Damage (self, world, world, dm, DEATH_FALL, self.origin, '0 0 0'); } - maxspeed = autocvar_g_maxspeed; - if(maxspeed > 0 && vlen(self.velocity) > maxspeed) + if(autocvar_g_maxspeed > 0 && velocity_len > autocvar_g_maxspeed) Damage (self, world, world, 100000, DEATH_SHOOTING_STAR, self.origin, '0 0 0'); - // play stupid sounds if (g_footsteps) if (!gameover) if (self.flags & FL_ONGROUND) - if (vlen(self.velocity) > autocvar_sv_maxspeed * 0.6) + if (velocity_len > autocvar_sv_maxspeed * 0.6) if (!self.deadflag) if (time < self.lastground + 0.2) { @@ -104,15 +121,15 @@ void CreatureFrame (void) if not(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS) { if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS) - GlobalSound(globalsound_metalstep, CHAN_PLAYER, VOICETYPE_PLAYERSOUND); + GlobalSound(globalsound_metalstep, CH_PLAYER, VOICETYPE_PLAYERSOUND); else - GlobalSound(globalsound_step, CHAN_PLAYER, VOICETYPE_PLAYERSOUND); + GlobalSound(globalsound_step, CH_PLAYER, VOICETYPE_PLAYERSOUND); } } } - self.oldvelocity = self.velocity; } - self = findfloat(self, iscreature, TRUE); + + self.oldvelocity = self.velocity; } self = oldself; } @@ -179,7 +196,7 @@ void StartFrame (void) if(sys_frametime <= 0) sys_frametime = 1.0 / 60.0; // somewhat safe fallback - if (timeoutStatus == 1) // just before the timeout (when timeoutStatus will be 2) + if (timeout_status == TIMEOUT_LEADTIME) // just before the timeout (when timeout_status will be TIMEOUT_ACTIVE) orig_slowmo = autocvar_slowmo; // slowmo will be restored after the timeout skill = autocvar_skill; @@ -214,17 +231,10 @@ void StartFrame (void) RuneMatchGivePoints(); bot_serverframe(); - if(autocvar_spawn_debugview) - { - RandomSelection_Init(); - for(self = world; (self = find(self, classname, "player")); ) - RandomSelection_Add(self, 0, string_null, 1, 0); - self = RandomSelection_chosen_ent; - SelectSpawnPoint(0); - } - FOR_EACH_PLAYER(self) self.porto_forbidden = max(0, self.porto_forbidden - 1); + + MUTATOR_CALLHOOK(SV_StartFrame); } .vector originjitter; @@ -232,10 +242,12 @@ void StartFrame (void) .float anglejitter; .string gametypefilter; .string cvarfilter; +float DoesQ3ARemoveThisEntity(); void SV_OnEntityPreSpawnFunction() { - if(self.gametypefilter != "") - if not(isGametypeInFilter(game, teams_matter, self.gametypefilter)) + if (self) + if (self.gametypefilter != "") + if not(isGametypeInFilter(MapInfo_LoadedGametype, teamplay, have_team_spawns, self.gametypefilter)) { remove(self); return; @@ -257,7 +269,7 @@ void SV_OnEntityPreSpawnFunction() s = substring(s, 1, -1); } - n = tokenize(s); + n = tokenize_console(s); for(i = 0; i < n; ++i) { s = argv(i); @@ -350,6 +362,12 @@ void SV_OnEntityPreSpawnFunction() } } + if(DoesQ3ARemoveThisEntity()) + { + remove(self); + return; + } + // support special -1 and -2 angle from radiant if (self.angles == '0 -1 0') self.angles = '-90 0 0'; @@ -377,3 +395,20 @@ void SV_OnEntityPreSpawnFunction() return; } } + +void WarpZone_PostInitialize_Callback(void) +{ + // create waypoint links for warpzones + entity e; + for(e = world; (e = find(e, classname, "trigger_warpzone")); ) + { + vector src, dst; + src = (e.absmin + e.absmax) * 0.5; + makevectors(e.warpzone_angles); + src = src + ((e.warpzone_origin - src) * v_forward) * v_forward + 16 * v_right; + dst = (e.enemy.absmin + e.enemy.absmax) * 0.5; + makevectors(e.enemy.warpzone_angles); + dst = dst + ((e.enemy.warpzone_origin - dst) * v_forward) * v_forward - 16 * v_right; + waypoint_spawnforteleporter_v(e, src, dst, 0); + } +} diff --git a/qcsrc/server/sv_stats.qc b/qcsrc/server/sv_stats.qc deleted file mode 100644 index 0924cbac29..0000000000 --- a/qcsrc/server/sv_stats.qc +++ /dev/null @@ -1,5 +0,0 @@ - -// Accuracy -//.float shots; -//.float hits; - diff --git a/qcsrc/server/sys-post.qh b/qcsrc/server/sys-post.qh new file mode 100644 index 0000000000..919ed6b8d9 --- /dev/null +++ b/qcsrc/server/sys-post.qh @@ -0,0 +1,14 @@ +#pragma noref 0 + +#undef ATTN_NORM +#undef objerror +#undef droptofloor +#undef sound +#undef remove +#undef cvar_set +#undef cvar_string +#undef cvar + +var float(string var) cvar; +var string(string var) cvar_string; +var void(string var, string val) cvar_set; diff --git a/qcsrc/server/sys-pre.qh b/qcsrc/server/sys-pre.qh new file mode 100644 index 0000000000..b259b2b6c3 --- /dev/null +++ b/qcsrc/server/sys-pre.qh @@ -0,0 +1,12 @@ +#define SVQC + +#define ATTN_NORM builtin_ATTN_NORM +#define objerror builtin_objerror +#define droptofloor builtin_droptofloor +#define sound builtin_sound +#define remove builtin_remove +#define cvar_set builtin_cvar_set +#define cvar_string builtin_cvar_string +#define cvar builtin_cvar + +#pragma noref 1 diff --git a/qcsrc/server/sys.qh b/qcsrc/server/sys.qh deleted file mode 100644 index 75a5985048..0000000000 --- a/qcsrc/server/sys.qh +++ /dev/null @@ -1,147 +0,0 @@ -#pragma flag off fastarrays // make dp behave with new fteqcc versions. remove when dp bug with fteqcc fastarrays is fixed -#define SVQC - -// DO NOT modify the contents of this file, or you will risk incompatibility with the game engine. - -entity self; -entity other; -entity world; - -float time; -float frametime; -float force_retouch; -string mapname; -float deathmatch; -float coop; -float teamplay; -float serverflags; -float total_secrets; -float total_monsters; -float found_secrets; -float killed_monsters; -float parm1, parm2, parm3, parm4, parm5, parm6, parm7, parm8, parm9, parm10, parm11, parm12, parm13, parm14, parm15, parm16; -vector v_forward, v_up, v_right; -float trace_allsolid; -float trace_startsolid; -float trace_fraction; -vector trace_endpos; -vector trace_plane_normal; -float trace_plane_dist; -entity trace_ent; -float trace_inopen; -float trace_inwater; - -entity msg_entity; - -void main (void); -void StartFrame (void); -void PlayerPreThink (void); -void PlayerPostThink (void); -void ClientKill (void); -void ClientConnect (void); -void PutClientInServer (void); -void ClientDisconnect (void); -void SetNewParms (void); -void SetChangeParms (void); - -///////////////////////////////////////////////////////// -void end_sys_globals; -///////////////////////////////////////////////////////// - -.float modelindex; - -.vector absmin, absmax; - -.float ltime; -.float movetype; -.float solid; - -.vector origin; -.vector oldorigin; -.vector velocity; -.vector angles; -.vector avelocity; -.vector punchangle; - -.string classname; -.string model; - -.float frame; -.float skin; -.float effects; - -.vector mins, maxs; -.vector size; - -.void() touch; -.void() use; -.void() think; -.void() blocked; - -.float nextthink; - -.entity groundentity; - -.float health; -.float frags; - -.float weapon; -.string weaponmodel; -.float weaponframe; - -.float currentammo; -.float ammo_shells, ammo_nails, ammo_rockets, ammo_cells; -.float items; - -.float takedamage; - -.entity chain; - -.float deadflag; - -.vector view_ofs; - -.float button0; -.float button1; -.float button2; -.float impulse; -.float fixangle; -.vector v_angle; -.float idealpitch; - -.string netname; -.entity enemy; - -.float flags; -.float colormap; -.float team; -.float max_health; -.float teleport_time; -.float armortype; -.float armorvalue; -.float waterlevel; -.float watertype; -.float ideal_yaw; -.float yaw_speed; - -.entity aiment; -.entity goalentity; - -.float spawnflags; - -.string target; -.string targetname; - -.float dmg_take; -.float dmg_save; -.entity dmg_inflictor; - -.entity owner; -.vector movedir; -.string message; -.float sounds; -.string noise, noise1, noise2, noise3; - -///////////////////////////////////////////////////////// -void end_sys_fields; -///////////////////////////////////////////////////////// diff --git a/qcsrc/server/t_halflife.qc b/qcsrc/server/t_halflife.qc index fb03e55e3f..0a95b78d06 100644 --- a/qcsrc/server/t_halflife.qc +++ b/qcsrc/server/t_halflife.qc @@ -6,55 +6,57 @@ .float rendermode; .vector rendercolor; -void spawnfunc_weapon_crossbow() {}; -void spawnfunc_weapon_handgrenade() {}; -void spawnfunc_ammo_crossbow() {}; -void spawnfunc_ammo_9mmclip() {}; -void spawnfunc_ammo_gaussclip() {}; -void spawnfunc_weapon_rpg() {}; -void spawnfunc_weapon_357() {}; -void ammo_ARgrenades() {}; -void spawnfunc_item_battery() {}; -void spawnfunc_ammo_rpgclip() {}; -void weapon_9mmAR() {}; -void spawnfunc_weapon_tripmine() {}; -void spawnfunc_weapon_snark() {}; -void spawnfunc_ammo_buckshot() {}; -void ammo_9mmAR() {}; -void spawnfunc_ammo_357() {}; -void spawnfunc_weapon_gauss() {}; -void spawnfunc_weapon_hornetgun() {}; -//void spawnfunc_weapon_shotgun() {}; -void spawnfunc_item_healthkit() {}; -void spawnfunc_item_longjump() {}; -void spawnfunc_item_antidote() {}; -void spawnfunc_func_recharge() {}; -void spawnfunc_info_node() {}; -void spawnfunc_env_sound() {}; -void spawnfunc_light_spot() {}; -void spawnfunc_func_healthcharger() {}; +void spawnfunc_weapon_crossbow() {} +void spawnfunc_weapon_handgrenade() {} +void spawnfunc_ammo_crossbow() {} +void spawnfunc_ammo_9mmclip() {} +void spawnfunc_ammo_gaussclip() {} +void spawnfunc_weapon_rpg() {} +void spawnfunc_weapon_357() {} +void ammo_ARgrenades() {} +void spawnfunc_item_battery() {} +void spawnfunc_ammo_rpgclip() {} +void weapon_9mmAR() {} +void spawnfunc_weapon_tripmine() {} +void spawnfunc_weapon_snark() {} +void spawnfunc_ammo_buckshot() {} +void ammo_9mmAR() {} +void spawnfunc_ammo_357() {} +void spawnfunc_weapon_gauss() {} +void spawnfunc_weapon_hornetgun() {} +//void spawnfunc_weapon_shotgun() {} +void spawnfunc_item_healthkit() {} +void spawnfunc_item_longjump() {} +void spawnfunc_item_antidote() {} +void spawnfunc_func_recharge() {} +void spawnfunc_info_node() {} +void spawnfunc_env_sound() {} +void spawnfunc_light_spot() {} +void spawnfunc_func_healthcharger() {} void func_ladder_touch() { if not(other.iscreature) return; + if (other.vehicle_flags & VHF_ISVEHICLE) + return; EXACTTRIGGER_TOUCH; other.ladder_time = time + 0.1; other.ladder_entity = self; -}; +} void spawnfunc_func_ladder() { EXACTTRIGGER_INIT; self.touch = func_ladder_touch; -}; +} void spawnfunc_func_water() { EXACTTRIGGER_INIT; self.touch = func_ladder_touch; -}; +} diff --git a/qcsrc/server/t_items.qc b/qcsrc/server/t_items.qc index 2ca9162f85..46c7342f4e 100644 --- a/qcsrc/server/t_items.qc +++ b/qcsrc/server/t_items.qc @@ -1,3 +1,40 @@ +float have_pickup_item(void) +{ + // minstagib: only allow filtered items + if(g_minstagib) + if(self.classname != "minstagib") + return FALSE; + + if(self.flags & FL_POWERUP) + { + if(autocvar_g_powerups > 0) + return TRUE; + if(autocvar_g_powerups == 0) + return FALSE; + if(g_lms) + return FALSE; + if(g_ca) + return FALSE; + if(g_arena) + return FALSE; + } + else + { + if(autocvar_g_pickup_items > 0) + return TRUE; + if(autocvar_g_pickup_items == 0) + return FALSE; + if(g_lms) + return FALSE; + if(g_ca) + return FALSE; + if(g_weaponarena) + if((self.weapons & WEPBIT_ALL) || (self.items & IT_AMMO)) + return FALSE; + } + return TRUE; +} + #define ITEM_RESPAWN_TICKS 10 #define ITEM_RESPAWNTIME(i) ((i).respawntime + crandom() * (i).respawntimejitter) @@ -94,9 +131,9 @@ void Item_Show (entity e, float mode) e.spawnshieldtime = 1; } - else if((e.flags & FL_WEAPON) && (g_weapon_stay == 3)) + else if((e.flags & FL_WEAPON) && g_weapon_stay) { - // make the item translucent green and not touchable + // make the item translucent and not touchable e.model = e.mdl; e.solid = SOLID_TRIGGER; // can STILL be picked up! e.colormod = '0 0 0'; @@ -108,7 +145,7 @@ void Item_Show (entity e, float mode) } else if(g_ghost_items) { - // make the item translucent green and not touchable + // make the item translucent and not touchable e.model = e.mdl; e.solid = SOLID_NOT; e.colormod = stov(autocvar_g_ghost_items_color); @@ -123,7 +160,7 @@ void Item_Show (entity e, float mode) // hide the item completely e.model = string_null; e.solid = SOLID_NOT; - e.colormod = stov(autocvar_g_ghost_items_color); + e.colormod = '0 0 0'; e.glowmod = e.colormod; e.alpha = 0; e.customizeentityforclient = func_null; @@ -146,11 +183,11 @@ void Item_Respawn (void) { Item_Show(self, 1); if(!g_minstagib && self.items == IT_STRENGTH) - sound (self, CHAN_TRIGGER, "misc/strength_respawn.wav", VOL_BASE, ATTN_NORM); // play respawn sound + sound (self, CH_TRIGGER, "misc/strength_respawn.wav", VOL_BASE, ATTN_NORM); // play respawn sound else if(!g_minstagib && self.items == IT_INVINCIBLE) - sound (self, CHAN_TRIGGER, "misc/shield_respawn.wav", VOL_BASE, ATTN_NORM); // play respawn sound + sound (self, CH_TRIGGER, "misc/shield_respawn.wav", VOL_BASE, ATTN_NORM); // play respawn sound else - sound (self, CHAN_TRIGGER, "misc/itemrespawn.wav", VOL_BASE, ATTN_NORM); // play respawn sound + sound (self, CH_TRIGGER, "misc/itemrespawn.wav", VOL_BASE, ATTN_NORM); // play respawn sound setorigin (self, self.origin); //pointparticles(particleeffectnum("item_respawn"), self.origin + self.mins_z * '0 0 1' + '0 0 48', '0 0 0', 1); @@ -196,18 +233,19 @@ void Item_RespawnCountdown (void) case IT_FUEL_REGEN: name = "item-fuelregen"; rgb = '1 0.5 0'; break; case IT_JETPACK: name = "item-jetpack"; rgb = '0.5 0.5 0.5'; break; } + if(!name) + { + print("Unknown powerup-marked item is wanting to respawn\n"); + localcmd(sprintf("prvm_edict server %d\n", num_for_edict(self))); + } if(name) { - WaypointSprite_Spawn(name, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, TRUE); + WaypointSprite_Spawn(name, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, TRUE, RADARICON_POWERUP, rgb); if(self.waypointsprite_attached) - { - WaypointSprite_UpdateTeamRadar(self.waypointsprite_attached, RADARICON_POWERUP, rgb); - //WaypointSprite_UpdateMaxHealth(self.waypointsprite_attached, ITEM_RESPAWN_TICKS + 1); WaypointSprite_UpdateBuildFinished(self.waypointsprite_attached, time + ITEM_RESPAWN_TICKS); - } } } - sound (self, CHAN_TRIGGER, "misc/itemrespawncountdown.wav", VOL_BASE, ATTN_NORM); // play respawn sound + sound (self, CH_TRIGGER, "misc/itemrespawncountdown.wav", VOL_BASE, ATTN_NORM); // play respawn sound if(self.waypointsprite_attached) { WaypointSprite_Ping(self.waypointsprite_attached); @@ -248,6 +286,53 @@ void Item_ScheduleInitialRespawn(entity e) Item_ScheduleRespawnIn(e, game_starttime - time + ITEM_RESPAWNTIME_INITIAL(e)); } +float ITEM_MODE_NONE = 0; +float ITEM_MODE_HEALTH = 1; +float ITEM_MODE_ARMOR = 2; +float ITEM_MODE_FUEL = 3; +float Item_GiveAmmoTo(entity item, entity player, .float ammofield, float ammomax, float mode) +{ + if (!item.ammofield) + return FALSE; + + if (item.spawnshieldtime) + { + if ((player.ammofield < ammomax) || item.pickup_anyway) + { + player.ammofield = bound(player.ammofield, ammomax, player.ammofield + item.ammofield); + goto YEAH; + } + } + else if(g_weapon_stay == 2) + { + float mi = min(item.ammofield, ammomax); + if (player.ammofield < mi) + { + player.ammofield = mi; + goto YEAH; + } + } + + return FALSE; + +:YEAH + switch(mode) + { + case ITEM_MODE_FUEL: + player.pauserotfuel_finished = max(player.pauserotfuel_finished, time + autocvar_g_balance_pause_fuel_rot); + break; + case ITEM_MODE_HEALTH: + player.pauserothealth_finished = max(player.pauserothealth_finished, time + autocvar_g_balance_pause_health_rot); + break; + case ITEM_MODE_ARMOR: + player.pauserotarmor_finished = max(player.pauserotarmor_finished, time + autocvar_g_balance_pause_armor_rot); + break; + default: + break; + } + return TRUE; +} + float Item_GiveTo(entity item, entity player) { float _switchweapon; @@ -262,93 +347,71 @@ float Item_GiveTo(entity item, entity player) if (g_minstagib) { - if(item.spawnshieldtime) + float prevcells = player.ammo_cells; + + pickedup |= Item_GiveAmmoTo(item, player, ammo_fuel, g_pickup_fuel_max, ITEM_MODE_FUEL); + pickedup |= Item_GiveAmmoTo(item, player, ammo_cells, 999, ITEM_MODE_NONE); + + if(player.ammo_cells > prevcells) { - if (item.ammo_fuel) - if (player.ammo_fuel < g_pickup_fuel_max) - { - pickedup = TRUE; - player.ammo_fuel = bound(player.ammo_fuel, g_pickup_fuel_max, player.ammo_fuel + item.ammo_fuel); - player.pauserotfuel_finished = max(player.pauserotfuel_finished, time + autocvar_g_balance_pause_fuel_rot); - } - if((it = (item.items - (item.items & player.items)) & IT_PICKUPMASK)) + _switchweapon = TRUE; + + // play some cool sounds ;) + if (clienttype(player) == CLIENTTYPE_REAL) { - pickedup = TRUE; - player.items |= it; - sprint (player, strcat("You got the ^2", item.netname, "\n")); + if(player.health <= 5) + AnnounceTo(player, "lastsecond"); + else if(player.health < 50) + AnnounceTo(player, "narrowly"); } + // sound not available + // else if(item.items == IT_CELLS) + // AnnounceTo(player, "ammo"); - _switchweapon = TRUE; + if (item.weapons & WEPBIT_MINSTANEX) + W_GiveWeapon (player, WEP_MINSTANEX, item.netname); if (item.ammo_cells) - { - pickedup = TRUE; - // play some cool sounds ;) - centerprint(player, "\n"); - if (clienttype(player) == CLIENTTYPE_REAL) - { - if(player.health <= 5) - AnnounceTo(player, "lastsecond"); - else if(player.health < 50) - AnnounceTo(player, "narrowly"); - } - // sound not available - // else if(item.items == IT_CELLS) - // AnnounceTo(player, "ammo"); - - if (item.weapons & WEPBIT_MINSTANEX) - W_GiveWeapon (player, WEP_MINSTANEX, item.netname); - if (item.ammo_cells) - player.ammo_cells = bound(player.ammo_cells, 999, player.ammo_cells + autocvar_g_minstagib_ammo_drop); - player.health = 100; - } + player.ammo_cells = bound(player.ammo_cells, 999, player.ammo_cells + autocvar_g_minstagib_ammo_drop); + player.health = 100; + } - // extralife powerup - if (item.max_health) - { - pickedup = TRUE; - // sound not available - // AnnounceTo(player, "_lives"); - player.armorvalue = bound(player.armorvalue, 999, player.armorvalue + autocvar_g_minstagib_extralives); - sprint(player, "^3You picked up some extra lives\n"); - } + if((it = (item.items - (item.items & player.items)) & IT_PICKUPMASK)) + { + pickedup = TRUE; + player.items |= it; + sprint (player, strcat("You got the ^2", item.netname, "\n")); + } - // invis powerup - if (item.strength_finished) - { - pickedup = TRUE; - // sound not available - // AnnounceTo(player, "invisible"); - player.strength_finished = max(player.strength_finished, time) + autocvar_g_balance_powerup_strength_time; - } + // extralife powerup + if (item.max_health) + { + pickedup = TRUE; + // sound not available + // AnnounceTo(player, "_lives"); + player.armorvalue = bound(player.armorvalue, 999, player.armorvalue + autocvar_g_minstagib_extralives); + sprint(player, "^3You picked up some extra lives\n"); + } - // speed powerup - if (item.invincible_finished) - { - pickedup = TRUE; - // sound not available - // AnnounceTo(player, "speed"); - player.invincible_finished = max(player.invincible_finished, time) + autocvar_g_balance_powerup_strength_time; - } + // invis powerup + if (item.strength_finished) + { + pickedup = TRUE; + // sound not available + // AnnounceTo(player, "invisible"); + player.strength_finished = max(player.strength_finished, time) + autocvar_g_balance_powerup_strength_time; + } + + // speed powerup + if (item.invincible_finished) + { + pickedup = TRUE; + // sound not available + // AnnounceTo(player, "speed"); + player.invincible_finished = max(player.invincible_finished, time) + autocvar_g_balance_powerup_strength_time; } } else { - if (g_weapon_stay == 1) - if not(item.flags & FL_NO_WEAPON_STAY) - if (item.flags & FL_WEAPON) - { - if(item.classname == "droppedweapon") - { - if (player.weapons & item.weapons) // don't let players stack ammo by tossing weapons - goto skip; - } - else - { - if (player.weapons & item.weapons) - goto skip; - } - } - // in case the player has autoswitch enabled do the following: // if the player is using their best weapon before items are given, they // probably want to switch to an even better weapon after items are given @@ -359,43 +422,16 @@ float Item_GiveTo(entity item, entity player) if not(player.weapons & W_WeaponBit(player.switchweapon)) _switchweapon = TRUE; - if(item.spawnshieldtime) - { - if (item.ammo_shells) - if ((player.ammo_shells < g_pickup_shells_max) || item.pickup_anyway) - { - pickedup = TRUE; - player.ammo_shells = bound(player.ammo_shells, g_pickup_shells_max, player.ammo_shells + item.ammo_shells); - } - if (item.ammo_nails) - if ((player.ammo_nails < g_pickup_nails_max) || item.pickup_anyway) - { - pickedup = TRUE; - player.ammo_nails = bound(player.ammo_nails, g_pickup_nails_max, player.ammo_nails + item.ammo_nails); - } - if (item.ammo_rockets) - if ((player.ammo_rockets < g_pickup_rockets_max) || item.pickup_anyway) - { - pickedup = TRUE; - player.ammo_rockets = bound(player.ammo_rockets, g_pickup_rockets_max, player.ammo_rockets + item.ammo_rockets); - } - if (item.ammo_cells) - if ((player.ammo_cells < g_pickup_cells_max) || item.pickup_anyway) - { - pickedup = TRUE; - player.ammo_cells = bound(player.ammo_cells, g_pickup_cells_max, player.ammo_cells + item.ammo_cells); - } - if (item.ammo_fuel) - if ((player.ammo_fuel < g_pickup_fuel_max) || item.pickup_anyway) - { - pickedup = TRUE; - player.ammo_fuel = bound(player.ammo_fuel, g_pickup_fuel_max, player.ammo_fuel + item.ammo_fuel); - player.pauserotfuel_finished = max(player.pauserotfuel_finished, time + autocvar_g_balance_pause_fuel_rot); - } - } + pickedup |= Item_GiveAmmoTo(item, player, ammo_fuel, g_pickup_fuel_max, ITEM_MODE_FUEL); + pickedup |= Item_GiveAmmoTo(item, player, ammo_shells, g_pickup_shells_max, ITEM_MODE_NONE); + pickedup |= Item_GiveAmmoTo(item, player, ammo_nails, g_pickup_nails_max, ITEM_MODE_NONE); + pickedup |= Item_GiveAmmoTo(item, player, ammo_rockets, g_pickup_rockets_max, ITEM_MODE_NONE); + pickedup |= Item_GiveAmmoTo(item, player, ammo_cells, g_pickup_cells_max, ITEM_MODE_NONE); + pickedup |= Item_GiveAmmoTo(item, player, health, item.max_health, ITEM_MODE_HEALTH); + pickedup |= Item_GiveAmmoTo(item, player, armorvalue, item.max_armorvalue, ITEM_MODE_ARMOR); if (item.flags & FL_WEAPON) - if ((it = item.weapons - (item.weapons & player.weapons)) || g_pickup_weapons_anyway) + if ((it = item.weapons - (item.weapons & player.weapons)) || (item.spawnshieldtime && g_pickup_weapons_anyway)) { pickedup = TRUE; for(i = WEP_FIRST; i <= WEP_LAST; ++i) @@ -413,33 +449,15 @@ float Item_GiveTo(entity item, entity player) sprint (player, strcat("You got the ^2", item.netname, "\n")); } - if(item.spawnshieldtime) + if (item.strength_finished) { - if (item.strength_finished) - { - pickedup = TRUE; - player.strength_finished = max(player.strength_finished, time) + autocvar_g_balance_powerup_strength_time; - } - if (item.invincible_finished) - { - pickedup = TRUE; - player.invincible_finished = max(player.invincible_finished, time) + autocvar_g_balance_powerup_invincible_time; - } - - if (item.health) - if ((player.health < item.max_health) || item.pickup_anyway) - { - pickedup = TRUE; - player.health = bound(player.health, item.max_health, player.health + item.health); - player.pauserothealth_finished = max(player.pauserothealth_finished, time + autocvar_g_balance_pause_health_rot); - } - if (item.armorvalue) - if ((player.armorvalue < item.max_armorvalue) || item.pickup_anyway) - { - pickedup = TRUE; - player.armorvalue = bound(player.armorvalue, item.max_armorvalue, player.armorvalue + item.armorvalue); - player.pauserotarmor_finished = max(player.pauserotarmor_finished, time + autocvar_g_balance_pause_armor_rot); - } + pickedup = TRUE; + player.strength_finished = max(player.strength_finished, time) + autocvar_g_balance_powerup_strength_time; + } + if (item.invincible_finished) + { + pickedup = TRUE; + player.invincible_finished = max(player.invincible_finished, time) + autocvar_g_balance_powerup_invincible_time; } } @@ -451,7 +469,7 @@ float Item_GiveTo(entity item, entity player) if (!pickedup) return 0; - sound (player, CHAN_AUTO, item.item_pickupsound, VOL_BASE, ATTN_NORM); + sound (player, CH_TRIGGER, item.item_pickupsound, VOL_BASE, ATTN_NORM); if (_switchweapon) if (player.switchweapon != w_getbestweapon(player)) W_SwitchWeapon_Force(player, w_getbestweapon(player)); @@ -489,8 +507,6 @@ void Item_Touch (void) remove (self); else if not(self.spawnshieldtime) return; - else if((self.flags & FL_WEAPON) && !(self.flags & FL_NO_WEAPON_STAY) && (g_weapon_stay == 1 || g_weapon_stay == 2)) - return; else { if(self.team) @@ -564,7 +580,7 @@ void RemoveItem(void) // pickup evaluation functions // these functions decide how desirable an item is to the bots -float generic_pickupevalfunc(entity player, entity item) {return item.bot_pickupbasevalue;}; +float generic_pickupevalfunc(entity player, entity item) {return item.bot_pickupbasevalue;} float weapon_pickupevalfunc(entity player, entity item) { @@ -574,7 +590,7 @@ float weapon_pickupevalfunc(entity player, entity item) if(player.weapons & item.weapons == item.weapons) { // If I can pick it up - if(g_weapon_stay == 1 || g_weapon_stay == 2 || !item.spawnshieldtime) + if(!item.spawnshieldtime) c = 0; else if(player.ammo_cells || player.ammo_shells || player.ammo_nails || player.ammo_rockets) { @@ -621,7 +637,7 @@ float weapon_pickupevalfunc(entity player, entity item) } return item.bot_pickupbasevalue * c; -}; +} float commodity_pickupevalfunc(entity player, entity item) { @@ -674,7 +690,7 @@ float commodity_pickupevalfunc(entity player, entity item) c = c + max(0, 1 - player.health / item.max_health); return item.bot_pickupbasevalue * c; -}; +} .float is_item; @@ -684,6 +700,7 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, self.items = itemid; self.weapons = weaponid; + self.flags = FL_ITEM | itemflags; // is it a dropped weapon? if (self.classname == "droppedweapon") @@ -712,6 +729,13 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, return; } + if(!have_pickup_item()) + { + startitem_failed = TRUE; + remove (self); + return; + } + if(self.model != "") itemmodel = self.model; if(self.item_pickupsound != "") @@ -740,36 +764,6 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, waypoint_spawnforitem(self); } - if(teams_matter) - { - if(self.notteam) - { - print("removed non-teamplay ", self.classname, "\n"); - startitem_failed = TRUE; - remove (self); - return; - } - } - else - { - if(self.notfree) - { - print("removed non-FFA ", self.classname, "\n"); - startitem_failed = TRUE; - remove (self); - return; - } - } - - if(self.notq3a) - { - // We aren't TA or something like that, so we keep the Q3A entities - print("removed non-Q3A ", self.classname, "\n"); - startitem_failed = TRUE; - remove (self); - return; - } - /* * can't do it that way, as it would break maps * TODO make a target_give like entity another way, that perhaps has @@ -799,35 +793,6 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, self.is_item = TRUE; } - if(g_lms || g_ca) - { - startitem_failed = TRUE; - remove(self); - return; - } - else if (g_weaponarena && ((weaponid & WEPBIT_ALL) || (itemid & IT_AMMO))) - { - startitem_failed = TRUE; - remove(self); - return; - } - else if (g_minstagib) - { - // don't remove dropped items and powerups - if (self.classname != "minstagib") - { - startitem_failed = TRUE; - remove (self); - return; - } - } - else if (!autocvar_g_pickup_items && itemid != IT_STRENGTH && itemid != IT_INVINCIBLE && itemid != IT_HEALTH) - { - startitem_failed = TRUE; - remove (self); - return; - } - weaponsInMap |= weaponid; precache_model (itemmodel); @@ -857,7 +822,6 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, self.respawntimejitter = defaultrespawntimejitter; } self.netname = itemname; - self.flags = FL_ITEM | itemflags; self.touch = Item_Touch; setmodel (self, self.mdl); // precision set below self.effects |= EF_LOWPRECISION; @@ -895,13 +859,13 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, */ void minstagib_items (float itemid) { - local float rnd; + float rnd; self.classname = "minstagib"; // replace rocket launchers and nex guns with ammo cells if (itemid == IT_CELLS) { - self.ammo_cells = 1; + self.ammo_cells = autocvar_g_minstagib_ammo_drop; StartItem ("models/items/a_cells.md3", "misc/itempickup.wav", 45, 0, "MinstaNex Ammo", IT_CELLS, 0, 0, generic_pickupevalfunc, 100); @@ -1064,16 +1028,6 @@ void weapon_defaultspawnfunc(float wpn) if(self.team) self.flags |= FL_NO_WEAPON_STAY; - if(g_weapon_stay == 2 && self.classname != "droppedweapon") - { - self.ammo_shells = 0; - self.ammo_nails = 0; - self.ammo_cells = 0; - self.ammo_rockets = 0; - // weapon stay 2: don't use ammo on weapon pickups; instead - // initialize all ammo types to the pickup ammo unless set by g_start_ammo_* - } - StartItem(e.model, "weapons/weaponpickup.wav", self.respawntime, self.respawntimejitter, e.message, 0, e.weapons, FL_WEAPON, weapon_pickupevalfunc, e.bot_pickupbasevalue); if (self.modelindex) // don't precache if self was removed weapon_action(e.weapon, WR_PRECACHE); @@ -1081,7 +1035,7 @@ void weapon_defaultspawnfunc(float wpn) void spawnfunc_weapon_shotgun (void); void spawnfunc_weapon_uzi (void) { - if(q3acompat_machineshotgunswap) + if(autocvar_sv_q3acompat_machineshotgunswap) if(self.classname != "droppedweapon") { weapon_defaultspawnfunc(WEP_SHOTGUN); @@ -1091,7 +1045,7 @@ void spawnfunc_weapon_uzi (void) { } void spawnfunc_weapon_shotgun (void) { - if(q3acompat_machineshotgunswap) + if(autocvar_sv_q3acompat_machineshotgunswap) if(self.classname != "droppedweapon") { weapon_defaultspawnfunc(WEP_UZI); @@ -1147,7 +1101,7 @@ void spawnfunc_item_rockets (void) { void spawnfunc_item_shells (void); void spawnfunc_item_bullets (void) { if(!weaponswapping) - if(q3acompat_machineshotgunswap) + if(autocvar_sv_q3acompat_machineshotgunswap) if(self.classname != "droppedweapon") { weaponswapping = TRUE; @@ -1173,7 +1127,7 @@ void spawnfunc_item_cells (void) { void spawnfunc_item_shells (void) { if(!weaponswapping) - if(q3acompat_machineshotgunswap) + if(autocvar_sv_q3acompat_machineshotgunswap) if(self.classname != "droppedweapon") { weaponswapping = TRUE; @@ -1260,12 +1214,6 @@ void spawnfunc_item_health_large (void) { } void spawnfunc_item_health_mega (void) { - if(!autocvar_g_powerup_superhealth) - return; - - if((g_arena || g_ca) && !autocvar_g_arena_powerups) - return; - if(g_minstagib) { minstagib_items(IT_NAILS); } else { @@ -1287,12 +1235,6 @@ void spawnfunc_item_health25() { spawnfunc_item_health_medium(); } void spawnfunc_item_health100() { spawnfunc_item_health_mega(); } void spawnfunc_item_strength (void) { - if(!autocvar_g_powerup_strength) - return; - - if((g_arena || g_ca) && !autocvar_g_arena_powerups) - return; - if(g_minstagib) { minstagib_items(IT_STRENGTH); } else { @@ -1303,12 +1245,6 @@ void spawnfunc_item_strength (void) { } void spawnfunc_item_invincible (void) { - if(!autocvar_g_powerup_shield) - return; - - if((g_arena || g_ca) && !autocvar_g_arena_powerups) - return; - if(g_minstagib) { minstagib_items(IT_INVINCIBLE); } else { @@ -1571,12 +1507,12 @@ void GiveSound(entity e, float v0, float v1, float t, string snd_incr, string sn if(v1 <= v0 - t) { if(snd_decr != "") - sound (e, CHAN_AUTO, snd_decr, VOL_BASE, ATTN_NORM); + sound (e, CH_TRIGGER, snd_decr, VOL_BASE, ATTN_NORM); } else if(v0 >= v0 + t) { if(snd_incr != "") - sound (e, CHAN_AUTO, snd_incr, VOL_BASE, ATTN_NORM); + sound (e, CH_TRIGGER, snd_incr, VOL_BASE, ATTN_NORM); } } diff --git a/qcsrc/server/t_jumppads.qc b/qcsrc/server/t_jumppads.qc index 36048e8601..bf17e3faf0 100644 --- a/qcsrc/server/t_jumppads.qc +++ b/qcsrc/server/t_jumppads.qc @@ -10,7 +10,7 @@ float trigger_push_calculatevelocity_flighttime; void trigger_push_use() { - if(teams_matter) + if(teamplay) self.team = activator.team; } @@ -30,8 +30,8 @@ void trigger_push_use() vector trigger_push_calculatevelocity(vector org, entity tgt, float ht) { - local float grav, sdist, zdist, vs, vz, jumpheight; - local vector sdir, torg; + float grav, sdist, zdist, vs, vz, jumpheight; + vector sdir, torg; torg = tgt.origin + (tgt.mins + tgt.maxs) * 0.5; @@ -127,21 +127,10 @@ vector trigger_push_calculatevelocity(vector org, entity tgt, float ht) void trigger_push_touch() { - if (self.active == ACTIVE_NOT) - return; - - // FIXME: add a .float for whether an entity should be tossed by jumppads - if (!other.iscreature) - if (other.classname != "corpse") - if (other.classname != "body") - if (other.classname != "gib") - if (other.classname != "casing") - if (other.classname != "droppedweapon") - if (other.classname != "keepawayball") - if (!other.projectiledeathtype || other.classname == "bullet") + if (self.active == ACTIVE_NOT) return; - if (other.deadflag && other.iscreature) + if (!isPushable(other)) return; if(self.team) @@ -150,13 +139,30 @@ void trigger_push_touch() EXACTTRIGGER_TOUCH; - if(self.target) - self.movedir = trigger_push_calculatevelocity(other.origin, self.enemy, self.height); + if(self.enemy) + { + other.velocity = trigger_push_calculatevelocity(other.origin, self.enemy, self.height); + } + else if(self.target) + { + entity e; + RandomSelection_Init(); + for(e = world; (e = find(e, targetname, self.target)); ) + { + if(e.cnt) + RandomSelection_Add(e, 0, string_null, e.cnt, 1); + else + RandomSelection_Add(e, 0, string_null, 1, 1); + } + other.velocity = trigger_push_calculatevelocity(other.origin, RandomSelection_chosen_ent, self.height); + } + else + { + other.velocity = self.movedir; + } other.flags &~= FL_ONGROUND; - other.velocity = self.movedir; - if (other.classname == "player") { // reset tracking of oldvelocity for impact damage (sudden velocity changes) @@ -166,15 +172,15 @@ void trigger_push_touch() { // flash when activated pointparticles(particleeffectnum("jumppad_activate"), other.origin, other.velocity, 1); - sound (other, CHAN_AUTO, self.noise, VOL_BASE, ATTN_NORM); + sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTN_NORM); self.pushltime = time + 0.2; } - local float ct; + float ct; ct = clienttype(other); - if( ct == CLIENTTYPE_REAL) + if( ct == CLIENTTYPE_REAL || ct == CLIENTTYPE_BOT) { - local float i; - local float found; + float i; + float found; found = FALSE; for(i = 0; i < other.jumppadcount && i < NUM_JUMPPADSUSED; ++i) if(other.(jumppadsused[i]) == self) @@ -185,11 +191,22 @@ void trigger_push_touch() other.jumppadcount = other.jumppadcount + 1; } - if(self.message) - centerprint(other, self.message); + if(ct == CLIENTTYPE_REAL) + { + if(self.message) + centerprint(other, self.message); + } + else + other.lastteleporttime = time; + + if (!other.animstate_override) + { + if (other.crouch) + setanim(other, other.anim_duckjump, FALSE, TRUE, TRUE); + else + setanim(other, other.anim_jump, FALSE, TRUE, TRUE); + } } - else if(ct == CLIENTTYPE_BOT) - other.lastteleporttime = time; else other.jumppadcount = TRUE; @@ -230,14 +247,13 @@ void trigger_push_touch() self.think = SUB_Remove; self.nextthink = time; } -}; +} .vector dest; void trigger_push_findtarget() { - local entity e; - local vector org; - local float flighttime; + entity e, t; + vector org; // first calculate a typical start point for the jump org = (self.absmin + self.absmax) * 0.5; @@ -245,32 +261,49 @@ void trigger_push_findtarget() if (self.target) { - // find the target - self.enemy = find(world, targetname, self.target); - if (!self.enemy) + float n; + n = 0; + for(t = world; (t = find(t, targetname, self.target)); ) { - objerror("trigger_push: target not found\n"); - remove(self); - return; + ++n; + e = spawn(); + setorigin(e, org); + setsize(e, PL_MIN, PL_MAX); + e.velocity = trigger_push_calculatevelocity(org, t, self.height); + tracetoss(e, e); + if(e.movetype == MOVETYPE_NONE) + waypoint_spawnforteleporter(self, trace_endpos, vlen(trace_endpos - org) / vlen(e.velocity)); + remove(e); } - self.movedir = trigger_push_calculatevelocity(org, self.enemy, self.height); - flighttime = trigger_push_calculatevelocity_flighttime; + if(n == 0) + { + // no dest! + objerror ("Jumppad with nonexistant target"); + return; + } + else if(n == 1) + { + // exactly one dest - bots love that + self.enemy = find(e, targetname, self.target); + } + else + { + // have to use random selection every single time + self.enemy = world; + } } else - flighttime = 0; - - // calculate the destination and spawn a teleporter spawnfunc_waypoint - e = spawn(); - setorigin(e, org); - setsize(e, PL_MIN, PL_MAX); - e.velocity = self.movedir; - tracetoss(e, e); - self.dest = trace_endpos; - remove(e); - - waypoint_spawnforteleporter(self, self.dest, flighttime); -}; + { + e = spawn(); + setorigin(e, org); + setsize(e, PL_MIN, PL_MAX); + e.velocity = self.movedir; + tracetoss(e, e); + waypoint_spawnforteleporter(self, trace_endpos, vlen(trace_endpos - org) / vlen(e.velocity)); + remove(e); + } +} /* * ENTITY PARAMETERS: @@ -289,8 +322,8 @@ void spawnfunc_trigger_push() SetMovedir (); EXACTTRIGGER_INIT; - - self.active = ACTIVE_ACTIVE; + + self.active = ACTIVE_ACTIVE; self.use = trigger_push_use; self.touch = trigger_push_touch; @@ -305,8 +338,8 @@ void spawnfunc_trigger_push() // this must be called to spawn the teleport waypoints for bots InitializeEntity(self, trigger_push_findtarget, INITPRIO_FINDTARGET); -}; +} -void spawnfunc_target_push() {}; -void spawnfunc_info_notnull() {}; -void spawnfunc_target_position() {}; +void spawnfunc_target_push() {} +void spawnfunc_info_notnull() {} +void spawnfunc_target_position() {} diff --git a/qcsrc/server/t_plats.qc b/qcsrc/server/t_plats.qc index 3089ab650a..087a048c30 100644 --- a/qcsrc/server/t_plats.qc +++ b/qcsrc/server/t_plats.qc @@ -31,8 +31,8 @@ float PLAT_LOW_TRIGGER = 1; void plat_spawn_inside_trigger() { - local entity trigger; - local vector tmin, tmax; + entity trigger; + vector tmin, tmax; trigger = spawn(); trigger.touch = plat_center_touch; @@ -57,36 +57,46 @@ void plat_spawn_inside_trigger() tmax_y = tmin_y + 1; } - setsize (trigger, tmin, tmax); -}; + if(tmin_x > tmax_x) + if(tmin_y > tmax_y) + if(tmin_z > tmax_z) + { + setsize (trigger, tmin, tmax); + return; + } + + // otherwise, something is fishy... + remove(trigger); + objerror("plat_spawn_inside_trigger: platform has odd size or lip, can't spawn"); +} void plat_hit_top() { - sound (self, CHAN_TRIGGER, self.noise1, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM); self.state = 1; self.think = plat_go_down; self.nextthink = self.ltime + 3; -}; +} void plat_hit_bottom() { - sound (self, CHAN_TRIGGER, self.noise1, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM); self.state = 2; -}; +} void plat_go_down() { - sound (self, CHAN_TRIGGER, self.noise, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_NORM); self.state = 3; SUB_CalcMove (self.pos2, self.speed, plat_hit_bottom); -}; +} void plat_go_up() { - sound (self, CHAN_TRIGGER, self.noise, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_NORM); self.state = 4; SUB_CalcMove (self.pos1, self.speed, plat_hit_top); -}; +} void plat_center_touch() { @@ -101,7 +111,7 @@ void plat_center_touch() plat_go_up (); else if (self.state == 1) self.nextthink = self.ltime + 1; // delay going down -}; +} void plat_outside_touch() { @@ -114,14 +124,14 @@ void plat_outside_touch() self = self.enemy; if (self.state == 1) plat_go_down (); -}; +} void plat_trigger_use() { if (self.think) return; // already activated plat_go_down(); -}; +} void plat_crush() @@ -140,10 +150,11 @@ void plat_crush() plat_go_down (); else if (self.state == 3) plat_go_up (); - else - objerror ("plat_crush: bad self.state\n"); + // when in other states, then the plat_crush event came delayed after + // plat state already had changed + // this isn't a bug per se! } -}; +} void plat_use() { @@ -151,7 +162,7 @@ void plat_use() if (self.state != 4) objerror ("plat_use: not in up state"); plat_go_down(); -}; +} .string sound1, sound2; @@ -171,14 +182,9 @@ void plat_reset() } } -void spawnfunc_path_corner() { }; +void spawnfunc_path_corner() { } void spawnfunc_func_plat() { - if (!self.t_length) - self.t_length = 80; - if (!self.t_width) - self.t_width = 10; - if (self.sounds == 0) self.sounds = 2; @@ -230,60 +236,70 @@ void spawnfunc_func_plat() if (!self.speed) self.speed = 150; + if (!self.lip) + self.lip = 16; + if (!self.height) + self.height = self.size_z - self.lip; self.pos1 = self.origin; self.pos2 = self.origin; - self.pos2_z = self.origin_z - self.size_z + 8; - - plat_spawn_inside_trigger (); // the "start moving" trigger + self.pos2_z = self.origin_z - self.height; self.reset = plat_reset; plat_reset(); -}; + + plat_spawn_inside_trigger (); // the "start moving" trigger +} void() train_next; void train_wait() { - self.think = train_next; - self.nextthink = self.ltime + self.wait; - if(self.noise != "") - stopsoundto(MSG_BROADCAST, self, CHAN_TRIGGER); // send this as unreliable only, as the train will resume operation shortly anyway -}; + stopsoundto(MSG_BROADCAST, self, CH_TRIGGER_SINGLE); // send this as unreliable only, as the train will resume operation shortly anyway + + if(self.wait < 0) + { + train_next(); + } + else + { + self.think = train_next; + self.nextthink = self.ltime + self.wait; + } + + entity oldself; + oldself = self; + self = self.enemy; + SUB_UseTargets(); + self = oldself; + self.enemy = world; +} void train_next() { - local entity targ; + entity targ; targ = find(world, targetname, self.target); + self.enemy = targ; self.target = targ.target; if (!self.target) objerror("train_next: no next target"); self.wait = targ.wait; if (!self.wait) self.wait = 0.1; - if(self.wait < 0) - { - if (targ.speed) - SUB_CalcMove(targ.origin - self.mins, targ.speed, train_next); - else - SUB_CalcMove(targ.origin - self.mins, self.speed, train_next); - } + + if (targ.speed) + SUB_CalcMove(targ.origin - self.mins, targ.speed, train_wait); else - { - if (targ.speed) - SUB_CalcMove(targ.origin - self.mins, targ.speed, train_wait); - else - SUB_CalcMove(targ.origin - self.mins, self.speed, train_wait); - } + SUB_CalcMove(targ.origin - self.mins, self.speed, train_wait); if(self.noise != "") - sound(self, CHAN_TRIGGER, self.noise, VOL_BASE, ATTN_IDLE); -}; + sound(self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE); +} void func_train_find() { - local entity targ; + entity targ; targ = find(world, targetname, self.target); self.target = targ.target; if (!self.target) @@ -291,7 +307,7 @@ void func_train_find() setorigin(self, targ.origin - self.mins); self.nextthink = self.ltime + 1; self.think = train_next; -}; +} /*QUAKED spawnfunc_func_train (0 .5 .8) ? Ridable platform, targets spawnfunc_path_corner path to follow. @@ -325,7 +341,7 @@ void spawnfunc_func_train() self.dmgtime2 = time; // TODO make a reset function for this one -}; +} void func_rotating_setactive(float astate) { @@ -401,12 +417,12 @@ void spawnfunc_func_rotating() self.think = SUB_Null; // TODO make a reset function for this one -}; +} .float height; void func_bobbing_controller_think() { - local vector v; + vector v; self.nextthink = time + 0.1; if not (self.owner.active == ACTIVE_ACTIVE) @@ -421,7 +437,7 @@ void func_bobbing_controller_think() if(self.owner.classname == "func_bobbing") // don't brake stuff if the func_bobbing was killtarget'ed // * 10 so it will arrive in 0.1 sec self.owner.velocity = (v - self.owner.origin) * 10; -}; +} /*QUAKED spawnfunc_func_bobbing (0 .5 .8) ? X_AXIS Y_AXIS Brush model that moves back and forth on one axis (default Z). @@ -434,11 +450,11 @@ dmgtime : See above. */ void spawnfunc_func_bobbing() { - local entity controller; + entity controller; if (self.noise != "") { precache_sound(self.noise); - soundto(MSG_INIT, self, CHAN_TRIGGER, self.noise, VOL_BASE, ATTN_IDLE); + soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE); } if (!self.speed) self.speed = 4; @@ -485,12 +501,12 @@ void spawnfunc_func_bobbing() self.effects |= EF_LOWPRECISION; // TODO make a reset function for this one -}; +} .float freq; void func_pendulum_controller_think() { - local float v; + float v; self.nextthink = time + 0.1; if not (self.owner.active == ACTIVE_ACTIVE) @@ -507,15 +523,15 @@ void func_pendulum_controller_think() // * 10 so it will arrive in 0.1 sec self.owner.avelocity_z = (remainder(v - self.owner.angles_z, 360)) * 10; } -}; +} void spawnfunc_func_pendulum() { - local entity controller; + entity controller; if (self.noise != "") { precache_sound(self.noise); - soundto(MSG_INIT, self, CHAN_TRIGGER, self.noise, VOL_BASE, ATTN_IDLE); + soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE); } self.active = ACTIVE_ACTIVE; @@ -536,6 +552,7 @@ void spawnfunc_func_pendulum() self.blocked = generic_plat_blocked; + self.avelocity_z = 0.0000001; if not(InitMovingBrushTrigger()) return; @@ -560,7 +577,7 @@ void spawnfunc_func_pendulum() //self.effects |= EF_LOWPRECISION; // TODO make a reset function for this one -}; +} // button and multiple button @@ -575,12 +592,12 @@ void button_wait() activator = self.enemy; SUB_UseTargets(); self.frame = 1; // use alternate textures -}; +} void button_done() { self.state = STATE_BOTTOM; -}; +} void button_return() { @@ -589,13 +606,13 @@ void button_return() self.frame = 0; // use normal textures if (self.health) self.takedamage = DAMAGE_YES; // can be shot again -}; +} void button_blocked() { // do nothing, just don't come all the way back out -}; +} void button_fire() @@ -607,11 +624,11 @@ void button_fire() return; if (self.noise != "") - sound (self, CHAN_TRIGGER, self.noise, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTN_NORM); self.state = STATE_UP; SUB_CalcMove (self.pos2, self.speed, button_wait); -}; +} void button_reset() { @@ -636,7 +653,7 @@ void button_use() self.enemy = activator; button_fire (); -}; +} void button_touch() { @@ -655,7 +672,7 @@ void button_touch() if (other.owner) self.enemy = other.owner; button_fire (); -}; +} void button_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) { @@ -673,7 +690,7 @@ void button_damage(entity inflictor, entity attacker, float damage, float deatht self.enemy = damage_attacker; button_fire (); } -}; +} /*QUAKED spawnfunc_func_button (0 .5 .8) ? @@ -730,7 +747,7 @@ void spawnfunc_func_button() self.flags |= FL_NOTARGET; button_reset(); -}; +} float DOOR_START_OPEN = 1; @@ -812,13 +829,13 @@ void door_blocked() door_go_down (); } */ -}; +} void door_hit_top() { if (self.noise1 != "") - sound (self, CHAN_TRIGGER, self.noise1, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM); self.state = STATE_TOP; if (self.spawnflags & DOOR_TOGGLE) return; // don't come down automatically @@ -830,19 +847,19 @@ void door_hit_top() self.think = door_rotating_go_down; } self.nextthink = self.ltime + self.wait; -}; +} void door_hit_bottom() { if (self.noise1 != "") - sound (self, CHAN_TRIGGER, self.noise1, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM); self.state = STATE_BOTTOM; -}; +} void door_go_down() { if (self.noise2 != "") - sound (self, CHAN_TRIGGER, self.noise2, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); if (self.max_health) { self.takedamage = DAMAGE_YES; @@ -851,7 +868,7 @@ void door_go_down() self.state = STATE_DOWN; SUB_CalcMove (self.pos1, self.speed, door_hit_bottom); -}; +} void door_go_up() { @@ -865,7 +882,7 @@ void door_go_up() } if (self.noise2 != "") - sound (self, CHAN_TRIGGER, self.noise2, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); self.state = STATE_UP; SUB_CalcMove (self.pos2, self.speed, door_hit_top); @@ -874,7 +891,8 @@ void door_go_up() self.message = ""; SUB_UseTargets(); self.message = oldmessage; -}; +} + /* @@ -885,10 +903,54 @@ ACTIVATION FUNCTIONS ============================================================================= */ +float door_check_keys(void) { + local entity door; + + + if (self.owner) + door = self.owner; + else + door = self; + + // no key needed + if not(door.itemkeys) + return TRUE; + + // this door require a key + // only a player can have a key + if (other.classname != "player") + return FALSE; + + if (item_keys_usekey(door, other)) { + // some keys were used + if (other.key_door_messagetime <= time) { + play2(other, "misc/talk.wav"); + centerprint(other, strcat("You also need ", item_keys_keylist(door.itemkeys), "!")); + other.key_door_messagetime = time + 2; + } + } else { + // no keys were used + if (other.key_door_messagetime <= time) { + play2(other, "misc/talk.wav"); + centerprint(other, strcat("You need ", item_keys_keylist(door.itemkeys), "!")); + other.key_door_messagetime = time + 2; + } + } + + if (door.itemkeys) { + // door is now unlocked + play2(other, "misc/talk.wav"); + centerprint(other, "Door unlocked!"); + return TRUE; + } else + return FALSE; +} + + void door_fire() { - local entity oself; - local entity starte; + entity oself; + entity starte; if (self.owner != self) objerror ("door_fire: self.owner != self"); @@ -942,14 +1004,15 @@ void door_fire() self = self.enemy; } while ( (self != starte) && (self != world) ); self = oself; -}; +} void door_use() { - local entity oself; + entity oself; //dprint("door_use (model: ");dprint(self.model);dprint(")\n"); + if (self.owner) { oself = self; @@ -957,33 +1020,44 @@ void door_use() door_fire (); self = oself; } -}; +} void door_trigger_touch() { if (other.health < 1) - if not(other.iscreature && other.deadflag == DEAD_NO) - return; + if not(other.iscreature && other.deadflag == DEAD_NO) + return; if (time < self.attack_finished_single) return; + + // check if door is locked + if (!door_check_keys()) + return; + self.attack_finished_single = time + 1; activator = other; self = self.owner; door_use (); -}; +} void door_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) { - local entity oself; + entity oself; if(self.spawnflags & DOOR_NOSPLASH) if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH)) return; self.health = self.health - damage; + + if (self.itemkeys) { + // don't allow opening doors through damage if keys are required + return; + } + if (self.health <= 0) { oself = self; @@ -993,7 +1067,7 @@ void door_damage(entity inflictor, entity attacker, float damage, float deathtyp door_use (); self = oself; } -}; +} /* @@ -1018,7 +1092,7 @@ void door_touch() centerprint (other, self.owner.message); play2(other, "misc/talk.wav"); } -}; +} void door_generic_plat_blocked() @@ -1058,36 +1132,36 @@ void door_generic_plat_blocked() door_rotating_go_down (); } */ -}; +} void door_rotating_hit_top() { if (self.noise1 != "") - sound (self, CHAN_TRIGGER, self.noise1, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM); self.state = STATE_TOP; if (self.spawnflags & DOOR_TOGGLE) return; // don't come down automatically self.think = door_rotating_go_down; self.nextthink = self.ltime + self.wait; -}; +} void door_rotating_hit_bottom() { if (self.noise1 != "") - sound (self, CHAN_TRIGGER, self.noise1, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM); if (self.lip==666) // self.lip is used to remember reverse opening direction for door_rotating { self.pos2 = '0 0 0' - self.pos2; self.lip = 0; } self.state = STATE_BOTTOM; -}; +} void door_rotating_go_down() { if (self.noise2 != "") - sound (self, CHAN_TRIGGER, self.noise2, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); if (self.max_health) { self.takedamage = DAMAGE_YES; @@ -1096,7 +1170,7 @@ void door_rotating_go_down() self.state = STATE_DOWN; SUB_CalcAngleMove (self.pos1, self.speed, door_rotating_hit_bottom); -}; +} void door_rotating_go_up() { @@ -1109,7 +1183,7 @@ void door_rotating_go_up() return; } if (self.noise2 != "") - sound (self, CHAN_TRIGGER, self.noise2, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); self.state = STATE_UP; SUB_CalcAngleMove (self.pos2, self.speed, door_rotating_hit_top); @@ -1118,7 +1192,7 @@ void door_rotating_go_up() self.message = ""; SUB_UseTargets(); self.message = oldmessage; -}; +} @@ -1134,8 +1208,8 @@ SPAWNING FUNCTIONS entity spawn_field(vector fmins, vector fmaxs) { - local entity trigger; - local vector t1, t2; + entity trigger; + vector t1, t2; trigger = spawn(); trigger.classname = "doortriggerfield"; @@ -1148,7 +1222,7 @@ entity spawn_field(vector fmins, vector fmaxs) t2 = fmaxs; setsize (trigger, t1 - '60 60 8', t2 + '60 60 8'); return (trigger); -}; +} float EntitiesTouching(entity e1, entity e2) @@ -1166,7 +1240,7 @@ float EntitiesTouching(entity e1, entity e2) if (e1.absmax_z < e2.absmin_z) return FALSE; return TRUE; -}; +} /* @@ -1178,8 +1252,8 @@ LinkDoors */ void LinkDoors() { - local entity t, starte; - local vector cmins, cmaxs; + entity t, starte; + vector cmins, cmaxs; if (self.enemy) return; // already linked by another door @@ -1260,16 +1334,20 @@ void LinkDoors() } } while (1 ); -}; +} -/*QUAKED spawnfunc_func_door (0 .5 .8) ? START_OPEN x DOOR_DONT_LINK x x TOGGLE +/*QUAKED spawnfunc_func_door (0 .5 .8) ? START_OPEN x DOOR_DONT_LINK GOLD_KEY SILVER_KEY TOGGLE if two doors touch, they are assumed to be connected and operate as a unit. TOGGLE causes the door to wait in both the start and end states for a trigger event. START_OPEN causes the door to move to its destination when spawned, and operate in reverse. It is used to temporarily or permanently close off an area when triggered (not useful for touch or takedamage doors). +GOLD_KEY causes the door to open only if the activator holds a gold key. + +SILVER_KEY causes the door to open only if the activator holds a silver key. + "message" is printed when the door is touched if it is a trigger door and it hasn't been fired yet "angle" determines the opening direction "targetname" if set, no touch field will be spawned and a remote button or trigger field activates the door. @@ -1303,8 +1381,17 @@ void door_reset() self.think = SUB_Null; } +// spawnflags require key (for now only func_door) +#define SPAWNFLAGS_GOLD_KEY 8 +#define SPAWNFLAGS_SILVER_KEY 16 void spawnfunc_func_door() { + // Quake 1 keys compatibility + if (self.spawnflags & SPAWNFLAGS_GOLD_KEY) + self.itemkeys |= ITEM_KEY_BIT(0); + if (self.spawnflags & SPAWNFLAGS_SILVER_KEY) + self.itemkeys |= ITEM_KEY_BIT(1); + //if (!self.deathtype) // map makers can override this // self.deathtype = " got in the way"; SetMovedir (); @@ -1318,8 +1405,9 @@ void spawnfunc_func_door() self.blocked = door_blocked; self.use = door_use; - if(self.spawnflags & 8) - self.dmg = 10000; + // FIXME: undocumented flag 8, originally (Q1) GOLD_KEY + // if(self.spawnflags & 8) + // self.dmg = 10000; if(self.dmg && (!self.message)) self.message = "was squished"; @@ -1367,7 +1455,7 @@ void spawnfunc_func_door() InitializeEntity(self, LinkDoors, INITPRIO_LINKDOORS); self.reset = door_reset; -}; +} /*QUAKED spawnfunc_func_door_rotating (0 .5 .8) ? START_OPEN BIDIR DOOR_DONT_LINK BIDIR_IN_DOWN x TOGGLE X_AXIS Y_AXIS if two doors touch, they are assumed to be connected and operate as a unit. @@ -1433,8 +1521,10 @@ void spawnfunc_func_door_rotating() self.angles = '0 0 0'; self.max_health = self.health; + self.avelocity = self.movedir; if not(InitMovingBrushTrigger()) return; + self.velocity = '0 0 0'; //self.effects |= EF_LOWPRECISION; self.classname = "door_rotating"; @@ -1489,7 +1579,7 @@ void spawnfunc_func_door_rotating() InitializeEntity(self, LinkDoors, INITPRIO_LINKDOORS); self.reset = door_rotating_reset; -}; +} /* ============================================================================= @@ -1516,7 +1606,7 @@ float SECRET_YES_SHOOT = 16; // shootable even if targeted void fd_secret_use() { - local float temp; + float temp; string message_save; self.health = 10000; @@ -1536,7 +1626,7 @@ void fd_secret_use() // Make a sound, wait a little... if (self.noise1 != "") - sound(self, CHAN_TRIGGER, self.noise1, VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM); self.nextthink = self.ltime + 0.1; temp = 1 - (self.spawnflags & SECRET_1ST_LEFT); // 1 or -1 @@ -1561,8 +1651,8 @@ void fd_secret_use() self.dest2 = self.dest1 + v_forward * self.t_length; SUB_CalcMove(self.dest1, self.speed, fd_secret_move1); if (self.noise2 != "") - sound(self, CHAN_TRIGGER, self.noise2, VOL_BASE, ATTN_NORM); -}; + sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); +} // Wait after first movement... void fd_secret_move1() @@ -1570,36 +1660,36 @@ void fd_secret_move1() self.nextthink = self.ltime + 1.0; self.think = fd_secret_move2; if (self.noise3 != "") - sound(self, CHAN_TRIGGER, self.noise3, VOL_BASE, ATTN_NORM); -}; + sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_NORM); +} // Start moving sideways w/sound... void fd_secret_move2() { if (self.noise2 != "") - sound(self, CHAN_TRIGGER, self.noise2, VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); SUB_CalcMove(self.dest2, self.speed, fd_secret_move3); -}; +} // Wait here until time to go back... void fd_secret_move3() { if (self.noise3 != "") - sound(self, CHAN_TRIGGER, self.noise3, VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_NORM); if (!(self.spawnflags & SECRET_OPEN_ONCE)) { self.nextthink = self.ltime + self.wait; self.think = fd_secret_move4; } -}; +} // Move backward... void fd_secret_move4() { if (self.noise2 != "") - sound(self, CHAN_TRIGGER, self.noise2, VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); SUB_CalcMove(self.dest1, self.speed, fd_secret_move5); -}; +} // Wait 1 second... void fd_secret_move5() @@ -1607,15 +1697,15 @@ void fd_secret_move5() self.nextthink = self.ltime + 1.0; self.think = fd_secret_move6; if (self.noise3 != "") - sound(self, CHAN_TRIGGER, self.noise3, VOL_BASE, ATTN_NORM); -}; + sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_NORM); +} void fd_secret_move6() { if (self.noise2 != "") - sound(self, CHAN_TRIGGER, self.noise2, VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); SUB_CalcMove(self.oldorigin, self.speed, fd_secret_done); -}; +} void fd_secret_done() { @@ -1626,8 +1716,8 @@ void fd_secret_done() //self.th_pain = fd_secret_use; } if (self.noise3 != "") - sound(self, CHAN_TRIGGER, self.noise3, VOL_BASE, ATTN_NORM); -}; + sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_NORM); +} void secret_blocked() { @@ -1635,7 +1725,7 @@ void secret_blocked() return; self.attack_finished_single = time + 0.5; //T_Damage (other, self, self, self.dmg, self.dmg, self.deathtype, DT_IMPACT, (self.absmin + self.absmax) * 0.5, '0 0 0', Obituary_Generic); -}; +} /* ============== @@ -1659,7 +1749,7 @@ void secret_touch() centerprint (other, self.message); play2(other, "misc/talk.wav"); } -}; +} void secret_reset() { @@ -1727,7 +1817,7 @@ void spawnfunc_func_door_secret() self.reset = secret_reset; secret_reset(); -}; +} /*QUAKED spawnfunc_func_fourier (0 .5 .8) ? Brush model that moves in a pattern of added up sine waves, can be used e.g. for circular motions. @@ -1742,7 +1832,7 @@ dmgtime: See above. void func_fourier_controller_think() { - local vector v; + vector v; float n, i, t; self.nextthink = time + 0.1; @@ -1767,15 +1857,15 @@ void func_fourier_controller_think() if(self.owner.classname == "func_fourier") // don't brake stuff if the func_fourier was killtarget'ed // * 10 so it will arrive in 0.1 sec self.owner.velocity = (v - self.owner.origin) * 10; -}; +} void spawnfunc_func_fourier() { - local entity controller; + entity controller; if (self.noise != "") { precache_sound(self.noise); - soundto(MSG_INIT, self, CHAN_TRIGGER, self.noise, VOL_BASE, ATTN_IDLE); + soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE); } if (!self.speed) @@ -1815,7 +1905,7 @@ void spawnfunc_func_fourier() self.effects |= EF_LOWPRECISION; // TODO make a reset function for this one -}; +} // reusing some fields havocbots declared .entity wp00, wp01, wp02, wp03; @@ -1908,7 +1998,7 @@ void func_vectormamamam_findtarget() self.destvec = self.origin - func_vectormamamam_origin(self.owner, 0); - local entity controller; + entity controller; controller = spawn(); controller.classname = "func_vectormamamam_controller"; controller.owner = self; @@ -1921,7 +2011,7 @@ void spawnfunc_func_vectormamamam() if (self.noise != "") { precache_sound(self.noise); - soundto(MSG_INIT, self, CHAN_TRIGGER, self.noise, VOL_BASE, ATTN_IDLE); + soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE); } if(!self.targetfactor) @@ -1974,3 +2064,91 @@ void spawnfunc_func_vectormamamam() InitializeEntity(self, func_vectormamamam_findtarget, INITPRIO_FINDTARGET); } + +void conveyor_think() +{ + entity e; + + // set myself as current conveyor where possible + for(e = world; (e = findentity(e, conveyor, self)); ) + e.conveyor = world; + + if(self.state) + { + for(e = findradius((self.absmin + self.absmax) * 0.5, vlen(self.absmax - self.absmin) * 0.5); e; e = e.chain) + if(!e.conveyor.state) + if(isPushable(e)) + { + vector emin = e.absmin; + vector emax = e.absmax; + if(self.solid == SOLID_BSP) + { + emin -= '1 1 1'; + emax += '1 1 1'; + } + if(boxesoverlap(emin, emax, self.absmin, self.absmax)) // quick + if(WarpZoneLib_BoxTouchesBrush(emin, emax, self, e)) // accurate + e.conveyor = self; + } + + for(e = world; (e = findentity(e, conveyor, self)); ) + { + if(e.flags & FL_CLIENT) // doing it via velocity has quite some advantages + continue; // done in SV_PlayerPhysics + + setorigin(e, e.origin + self.movedir * sys_frametime); + move_out_of_solid(e); + UpdateCSQCProjectile(e); + /* + // stupid conveyor code + tracebox(e.origin, e.mins, e.maxs, e.origin + self.movedir * sys_frametime, MOVE_NORMAL, e); + if(trace_fraction > 0) + setorigin(e, trace_endpos); + */ + } + } + + self.nextthink = time; +} + +void conveyor_use() +{ + self.state = !self.state; +} + +void conveyor_reset() +{ + self.state = (self.spawnflags & 1); +} + +void conveyor_init() +{ + if (!self.speed) + self.speed = 200; + self.movedir = self.movedir * self.speed; + self.think = conveyor_think; + self.nextthink = time; + IFTARGETED + { + self.use = conveyor_use; + self.reset = conveyor_reset; + conveyor_reset(); + } + else + self.state = 1; +} + +void spawnfunc_trigger_conveyor() +{ + SetMovedir(); + EXACTTRIGGER_INIT; + conveyor_init(); +} + +void spawnfunc_func_conveyor() +{ + SetMovedir(); + InitMovingBrushTrigger(); + self.movetype = MOVETYPE_NONE; + conveyor_init(); +} diff --git a/qcsrc/server/t_quake.qc b/qcsrc/server/t_quake.qc index ada78846b9..ab49c6db5d 100644 --- a/qcsrc/server/t_quake.qc +++ b/qcsrc/server/t_quake.qc @@ -16,52 +16,3 @@ void spawnfunc_item_health (void) {if (self.spawnflags & 2) spawnfunc_item_healt -// garbage function to reduce warnings in compiling about unused variables -void junk_function () -{ - self.exteriormodeltoclient = world; - self.glow_trail = 0; - self.tag_entity = world; - self.BUTTON_HOOK = 0; - self.BUTTON_INFO = 0; - self.button8 = 0; - self.pitch_speed = 0; - self.drawonlytoclient = world; - self.nodrawtoclient = world; - self.cursor_active = 0; - self.cursor_screen = '0 0 0'; - self.cursor_trace_start = '0 0 0'; - self.cursor_trace_endpos = '0 0 0'; - self.ping = 0; - self.roomtype = 0; - self.radius = 0; - self.pitch = 0; - self.renderamt = 0; - self.rendermode = 0; - self.rendercolor = '0 0 0'; - self.light_lev = 0; - self.color = '0 0 0'; - self.style = 0; - self.jumppadsused = world; - self.disableclientprediction = 0; - self.contentstransition = SUB_Null; - self.dphitcontentsmask = 0; - self.modelflags = 0; - self.attack_finished_for = 0; // why is this even valid? Spiiiiiiiiiiiiiiiiiiiiike! - self.notsingle = 0; - trace_dphittexturename = ""; - require_spawnfunc_prefix = 1; - self.movetypesteplandevent = SUB_Null; - self.viewzoom = 0; - self.cvar_cl_weaponpriorities = ""; - self.scores = 0; - self.teamscores = 0; - gettaginfo_parent = 0; - gettaginfo_name = ""; - gettaginfo_offset = '0 0 0'; - gettaginfo_forward = '0 0 0'; - gettaginfo_right = '0 0 0'; - gettaginfo_up = '0 0 0'; - self.mass = 0; -} - diff --git a/qcsrc/server/t_quake3.qc b/qcsrc/server/t_quake3.qc index 44036ade49..f415e1fd1d 100644 --- a/qcsrc/server/t_quake3.qc +++ b/qcsrc/server/t_quake3.qc @@ -23,7 +23,7 @@ void spawnfunc_weapon_plasmagun() { spawnfunc_weapon_hagar(); } void spawnfunc_ammo_cells() { spawnfunc_item_rockets(); } // Rail -> Rifle -void spawnfunc_weapon_railgun() { spawnfunc_weapon_campingrifle(); } +void spawnfunc_weapon_railgun() { spawnfunc_weapon_rifle(); } void spawnfunc_ammo_slugs() { spawnfunc_item_bullets(); } // BFG -> Crylink @@ -130,3 +130,54 @@ void spawnfunc_team_CTF_redspawn() { spawnfunc_info_player_team1(); } void spawnfunc_team_CTF_bluespawn() { spawnfunc_info_player_team2(); } void spawnfunc_item_flight() { spawnfunc_item_jetpack(); } + +.float notteam; +.float notsingle; +.float notfree; +.float notq3a; +.float notta; +.string gametype; +float DoesQ3ARemoveThisEntity() +{ + // Q3 style filters (DO NOT USE, THIS IS COMPAT ONLY) + + if(self.notq3a) + if(!teamplay || g_tdm || g_ctf) + return 1; + + if(self.notta) + if not(!teamplay || g_tdm || g_ctf) + return 1; + + if(self.notsingle) + if(maxclients == 1) + return 1; + + if(self.notteam) + if(teamplay) + return 1; + + if(self.notfree) + if(!teamplay) + return 1; + + if(self.gametype) + { + string gametypename; + // static char *gametypeNames[] = {"ffa", "tournament", "single", "team", "ctf", "oneflag", "obelisk", "harvester", "teamtournament"} + gametypename = "ffa"; + if(teamplay) + gametypename = "team"; + if(g_arena) + gametypename = "tournament"; + if(g_ctf) + gametypename = "ctf"; + if(maxclients == 1) + gametypename = "single"; + // we do not have the other types (oneflag, obelisk, harvester, teamtournament) + if(strstrofs(self.gametype, gametypename, 0) < 0) + return 1; + } + + return 0; +} diff --git a/qcsrc/server/t_swamp.qc b/qcsrc/server/t_swamp.qc index 5ad7e62cb7..4f3e54420c 100644 --- a/qcsrc/server/t_swamp.qc +++ b/qcsrc/server/t_swamp.qc @@ -98,4 +98,4 @@ void spawnfunc_trigger_swamp(void) self.swamp_interval = 1; if(self.swamp_slowdown <= 0) self.swamp_slowdown = 0.5; -}; +} diff --git a/qcsrc/server/t_teleporters.qc b/qcsrc/server/t_teleporters.qc index 93ced82670..1705d8f8ea 100644 --- a/qcsrc/server/t_teleporters.qc +++ b/qcsrc/server/t_teleporters.qc @@ -1,6 +1,6 @@ void trigger_teleport_use() { - if(teams_matter) + if(teamplay) self.team = activator.team; } @@ -33,7 +33,7 @@ float check_tdeath(entity player, vector org, vector telefragmin, vector telefra { TDEATHLOOP(org) { - if not(teams_matter && autocvar_g_telefrags_teamplay && head.team == player.team) + if not(teamplay && autocvar_g_telefrags_teamplay && head.team == player.team) if(head.classname == "player") if(head.health >= 1) return 1; @@ -48,7 +48,7 @@ void tdeath(entity player, entity teleporter, entity telefragger, vector telefra { if (player.classname == "player" && player.health >= 1) { - if not(teams_matter && autocvar_g_telefrags_teamplay && head.team == player.team) + if not(teamplay && autocvar_g_telefrags_teamplay && head.team == player.team) { if(head.classname == "player") if(head.health >= 1) @@ -77,7 +77,6 @@ void spawn_tdeath(vector v0, entity e, vector v) #define TELEPORT_FLAGS_TELEPORTER (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH) void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags) { - entity oldself; entity telefragger; vector from; @@ -88,16 +87,19 @@ void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angle makevectors (to_angles); - if(self.pushltime < time) // only show one teleport effect per teleporter per 0.2 seconds, for better fps + if(player.classname == "player") // don't play sounds or show particles for anything that isn't a player, maybe change later to block only observers { - if(tflags & TELEPORT_FLAG_SOUND) - sound (player, CHAN_TRIGGER, "misc/teleport.wav", VOL_BASE, ATTN_NORM); - if(tflags & TELEPORT_FLAG_PARTICLES) + if(self.pushltime < time) // only show one teleport effect per teleporter per 0.2 seconds, for better fps { - pointparticles(particleeffectnum("teleport"), player.origin, '0 0 0', 1); - pointparticles(particleeffectnum("teleport"), to + v_forward * 32, '0 0 0', 1); + if(tflags & TELEPORT_FLAG_SOUND) + sound (player, CH_TRIGGER, "misc/teleport.wav", VOL_BASE, ATTN_NORM); + if(tflags & TELEPORT_FLAG_PARTICLES) + { + pointparticles(particleeffectnum("teleport"), player.origin, '0 0 0', 1); + pointparticles(particleeffectnum("teleport"), to + v_forward * 32, '0 0 0', 1); + } + self.pushltime = time + 0.2; } - self.pushltime = time + 0.2; } // Relocate the player @@ -136,81 +138,90 @@ void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angle } player.lastteleporttime = time; - - // stop player name display - { - oldself = self; - self = player; - ClearSelectedPlayer(); - self = oldself; - } } } -void Teleport_Touch (void) +entity Simple_TeleportPlayer(entity teleporter, entity player) { - entity oldself, e; - vector o; + vector locout; + entity e; float p; - string s; - - if (self.active != ACTIVE_ACTIVE) - return; - if (other.health < 1) - return; - if not(other.flags & FL_CLIENT) // FIXME: Make missiles firable through the teleport too - return; - - if(self.team) - if((self.spawnflags & 4 == 0) == (self.team != other.team)) - return; - - EXACTTRIGGER_TOUCH; - - makevectors(self.enemy.mangle); - - if(other.classname == "player") - RemoveGrapplingHook(other); - - if(self.enemy) + // Find the output teleporter + if(teleporter.enemy) { - e = self.enemy; + e = teleporter.enemy; } else - { + { RandomSelection_Init(); - for(e = world; (e = find(e, targetname, self.target)); ) + for(e = world; (e = find(e, targetname, teleporter.target)); ) { p = 1; if(autocvar_g_telefrags_avoid) { - o = e.origin + '0 0 1' * (1 - other.mins_z - 24); - if(check_tdeath(other, o, '0 0 0', '0 0 0')) + locout = e.origin + '0 0 1' * (1 - player.mins_z - 24); + if(check_tdeath(player, locout, '0 0 0', '0 0 0')) p = 0; } - if(e.cnt) - RandomSelection_Add(e, 0, string_null, e.cnt, p); - else - RandomSelection_Add(e, 0, string_null, 1, p); + RandomSelection_Add(e, 0, string_null, (e.cnt ? e.cnt : 1), p); } e = RandomSelection_chosen_ent; } - if(!e) - { - sprint(other, "Teleport destination vanished. Sorry... please complain to the mapper.\n"); - } + if(!e) { sprint(player, "Teleport destination vanished. Sorry... please complain to the mapper.\n"); } + + makevectors(e.mangle); if(e.speed) - if(vlen(other.velocity) > e.speed) - other.velocity = normalize(other.velocity) * max(0, e.speed); + if(vlen(player.velocity) > e.speed) + player.velocity = normalize(player.velocity) * max(0, e.speed); + if(autocvar_g_teleport_maxspeed) - if(vlen(other.velocity) > autocvar_g_teleport_maxspeed) - other.velocity = normalize(other.velocity) * max(0, autocvar_g_teleport_maxspeed); + if(vlen(player.velocity) > autocvar_g_teleport_maxspeed) + player.velocity = normalize(player.velocity) * max(0, autocvar_g_teleport_maxspeed); + + locout = e.origin + '0 0 1' * (1 - player.mins_z - 24); + TeleportPlayer(teleporter, player, locout, e.mangle, v_forward * vlen(player.velocity), '0 0 0', '0 0 0', TELEPORT_FLAGS_TELEPORTER); - o = e.origin + '0 0 1' * (1 - other.mins_z - 24); - TeleportPlayer(self, other, o, e.mangle, v_forward * vlen(other.velocity), '0 0 0', '0 0 0', TELEPORT_FLAGS_TELEPORTER); + return e; +} + +void Teleport_Touch (void) +{ + entity oldself; + string s; + + if (self.active != ACTIVE_ACTIVE) + return; + + if not(other.iscreature) + return; + + // for gameplay: vehicles can't teleport + if (other.vehicle_flags & VHF_ISVEHICLE) + return; + + if(other.vehicle) + return; + + if(other.turrcaps_flags & TFL_TURRCAPS_ISTURRET) + return; + + if (other.deadflag != DEAD_NO) + return; + + if(self.team) + if((self.spawnflags & 4 == 0) == (self.team != other.team)) + return; + + EXACTTRIGGER_TOUCH; + + if(other.classname == "player") + RemoveGrapplingHook(other); + + entity e; + e = Simple_TeleportPlayer(self, other); activator = other; s = self.target; self.target = string_null; @@ -255,18 +266,15 @@ void teleport_findtarget (void) entity e; float n; - RandomSelection_Init(); n = 0; for(e = world; (e = find(e, targetname, self.target)); ) { ++n; if(e.movetype == MOVETYPE_NONE) - RandomSelection_Add(e, 0, string_null, 1, 1); + waypoint_spawnforteleporter(self, e.origin, 0); if(e.classname != "info_teleport_destination") print("^3MAPPER ERROR: teleporter does target an invalid teleport destination entity. Angles will not work.\n"); } - if(RandomSelection_chosen_ent) - waypoint_spawnforteleporter(self, RandomSelection_chosen_ent.origin, 0); if(n == 0) { @@ -278,7 +286,6 @@ void teleport_findtarget (void) { // exactly one dest - bots love that self.enemy = find(e, targetname, self.target); - self.dest = self.enemy.origin; } else { @@ -290,6 +297,17 @@ void teleport_findtarget (void) self.touch = Teleport_Touch; } +entity Teleport_Find(vector mi, vector ma) +{ + entity e; + for(e = world; (e = find(e, classname, "trigger_teleport")); ) + if(WarpZoneLib_BoxTouchesBrush(mi, ma, e, world)) + return e; + return world; +} + +entity teleport_first; +.entity teleport_next; void spawnfunc_trigger_teleport (void) { self.angles = '0 0 0'; @@ -308,11 +326,22 @@ void spawnfunc_trigger_teleport (void) objerror ("Teleporter with no target"); return; } + + self.teleport_next = teleport_first; + teleport_first = self; } void WarpZone_PostTeleportPlayer_Callback(entity pl) { UpdateCSQCProjectileAfterTeleport(pl); + // "disown" projectiles after teleport + if(pl.owner) + if(pl.owner == pl.realowner) + { + if(!(pl.flags & FL_PROJECTILE)) + print("A non-projectile got through a warpzone and its owner cleared. It's a ", pl.classname, ".\n"); + pl.owner = world; + } if(pl.classname == "player") { // reset tracking of oldvelocity for impact damage (sudden velocity changes) diff --git a/qcsrc/server/target_spawn.qc b/qcsrc/server/target_spawn.qc index 1253fe1c07..e04e2cad88 100644 --- a/qcsrc/server/target_spawn.qc +++ b/qcsrc/server/target_spawn.qc @@ -345,4 +345,4 @@ void trigger_relay_if_use() void spawnfunc_trigger_relay_if() { self.use = trigger_relay_if_use; -}; +} diff --git a/qcsrc/server/teamplay.qc b/qcsrc/server/teamplay.qc index 9cb52c1daa..f0ce8fd142 100644 --- a/qcsrc/server/teamplay.qc +++ b/qcsrc/server/teamplay.qc @@ -12,7 +12,7 @@ float IsTeamBalanceForced() { if(intermission_running) return 0; // no rebalancing whatsoever please - if(!teams_matter) + if(!teamplay) return 0; if(autocvar_g_campaign) return 0; @@ -85,74 +85,6 @@ void LogTeamchange(float player_id, float team_number, float type) GameLogEcho(strcat(":team:", ftos(player_id), ":", ftos(team_number), ":", ftos(type))); } -void WriteGameCvars() -{ - cvar_set("g_dm", ftos(g_dm)); - cvar_set("g_tdm", ftos(g_tdm)); - cvar_set("g_domination", ftos(g_domination)); - cvar_set("g_ctf", ftos(g_ctf)); - cvar_set("g_runematch", ftos(g_runematch)); - cvar_set("g_lms", ftos(g_lms)); - cvar_set("g_arena", ftos(g_arena)); - cvar_set("g_ca", ftos(g_ca)); - cvar_set("g_keyhunt", ftos(g_keyhunt)); - cvar_set("g_assault", ftos(g_assault)); - cvar_set("g_onslaught", ftos(g_onslaught)); - cvar_set("g_race", ftos(g_race)); - cvar_set("g_nexball", ftos(g_nexball)); - cvar_set("g_cts", ftos(g_cts)); - cvar_set("g_freezetag", ftos(g_freezetag)); - cvar_set("g_keepaway", ftos(g_keepaway)); -} - -void ReadGameCvars() -{ - float found; - float prev; - float i; - - found = 0; - prev = autocvar_gamecfg; - for(i = 0; i < 2; ++i) - { -//#NO AUTOCVARS START - found += (g_dm = (!found && (prev != GAME_DEATHMATCH) && cvar("g_dm"))); - found += (g_tdm = (!found && (prev != GAME_TEAM_DEATHMATCH) && cvar("g_tdm"))); - found += (g_domination = (!found && (prev != GAME_DOMINATION) && cvar("g_domination"))); - found += (g_ctf = (!found && (prev != GAME_CTF) && cvar("g_ctf"))); - found += (g_runematch = (!found && (prev != GAME_RUNEMATCH) && cvar("g_runematch"))); - found += (g_lms = (!found && (prev != GAME_LMS) && cvar("g_lms"))); - found += (g_arena = (!found && (prev != GAME_ARENA) && cvar("g_arena"))); - found += (g_ca = (!found && (prev != GAME_CA) && cvar("g_ca"))); - found += (g_keyhunt = (!found && (prev != GAME_KEYHUNT) && cvar("g_keyhunt"))); - found += (g_assault = (!found && (prev != GAME_ASSAULT) && cvar("g_assault"))); - found += (g_onslaught = (!found && (prev != GAME_ONSLAUGHT) && cvar("g_onslaught"))); - found += (g_race = (!found && (prev != GAME_RACE) && cvar("g_race"))); - found += (g_nexball = (!found && (prev != GAME_NEXBALL) && cvar("g_nexball"))); - found += (g_cts = (!found && (prev != GAME_CTS) && cvar("g_cts"))); - found += (g_freezetag = (!found && (prev != GAME_FREEZETAG) && cvar("g_freezetag"))); - found += (g_keepaway = (!found && (prev != GAME_KEEPAWAY) && cvar("g_keepaway"))); -//#NO AUTOCVARS END - - if(found) - break; - - prev = -1; // second attempt takes place WITHOUT prev set - } - - if(!found) - g_dm = 1; - - if(g_dm && autocvar_deathmatch_force_teamplay) - { - g_dm = 0; - g_tdm = 1; - } - - teams_matter = 0; - serverflags &~= SERVERFLAG_TEAMPLAY; -} - void default_delayedinit() { if(!scores_initialized) @@ -162,7 +94,7 @@ void default_delayedinit() void ActivateTeamplay() { serverflags |= SERVERFLAG_TEAMPLAY; - teams_matter = 1; + teamplay = 1; } void InitGameplayMode() @@ -173,16 +105,14 @@ void InitGameplayMode() VoteReset(); - // make sure only ONE type is selected - ReadGameCvars(); - WriteGameCvars(); - // find out good world mins/maxs bounds, either the static bounds found by looking for solid, or the mapinfo specified bounds get_mi_min_max(1); world.mins = mi_min; world.maxs = mi_max; MapInfo_LoadMapSettings(mapname); + teamplay = 0; + serverflags &~= SERVERFLAG_TEAMPLAY; if not(cvar_value_issafe(world.fog)) { @@ -198,24 +128,18 @@ void InitGameplayMode() MapInfo_ClearTemps(); - // in case mapinfo switched the type - ReadGameCvars(); - // set both here, gamemode can override it later timelimit_override = autocvar_timelimit_override; fraglimit_override = autocvar_fraglimit_override; leadlimit_override = autocvar_leadlimit_override; + gamemode_name = MapInfo_Type_ToText(MapInfo_LoadedGametype); if(g_dm) { - game = GAME_DEATHMATCH; - gamemode_name = "Deathmatch"; } if(g_tdm) { - game = GAME_TEAM_DEATHMATCH; - gamemode_name = "Team Deathmatch"; ActivateTeamplay(); tdm_init(); if(autocvar_g_tdm_team_spawns) @@ -224,8 +148,6 @@ void InitGameplayMode() if(g_domination) { - game = GAME_DOMINATION; - gamemode_name = "Domination"; ActivateTeamplay(); fraglimit_override = autocvar_g_domination_point_limit; leadlimit_override = autocvar_g_domination_point_leadlimit; @@ -235,30 +157,17 @@ void InitGameplayMode() if(g_ctf) { - game = GAME_CTF; - gamemode_name = "Capture the Flag"; ActivateTeamplay(); g_ctf_ignore_frags = autocvar_g_ctf_ignore_frags; - if(g_ctf_win_mode == 2) - { - fraglimit_override = autocvar_g_ctf_capture_limit; - leadlimit_override = autocvar_g_ctf_capture_leadlimit; - } - else - { - fraglimit_override = autocvar_capturelimit_override; - leadlimit_override = autocvar_captureleadlimit_override; - } + fraglimit_override = autocvar_capturelimit_override; + leadlimit_override = autocvar_captureleadlimit_override; ctf_init(); have_team_spawns = -1; // request team spawns } if(g_runematch) { - game = GAME_RUNEMATCH; - gamemode_name = "Rune Match"; - if(autocvar_deathmatch_force_teamplay) - ActivateTeamplay(); + // ActivateTeamplay(); fraglimit_override = autocvar_g_runematch_point_limit; leadlimit_override = autocvar_g_runematch_point_leadlimit; runematch_init(); @@ -266,8 +175,6 @@ void InitGameplayMode() if(g_lms) { - game = GAME_LMS; - gamemode_name = "Last Man Standing"; fraglimit_override = autocvar_g_lms_lives_override; leadlimit_override = 0; // not supported by LMS if(fraglimit_override == 0) @@ -279,8 +186,6 @@ void InitGameplayMode() if(g_arena) { - game = GAME_ARENA; - gamemode_name = "Arena"; fraglimit_override = autocvar_g_arena_point_limit; leadlimit_override = autocvar_g_arena_point_leadlimit; maxspawned = autocvar_g_arena_maxspawned; @@ -291,8 +196,6 @@ void InitGameplayMode() if(g_ca) { - game = GAME_CA; - gamemode_name = "Clan Arena"; ActivateTeamplay(); fraglimit_override = autocvar_g_ca_point_limit; leadlimit_override = autocvar_g_ca_point_leadlimit; @@ -301,8 +204,6 @@ void InitGameplayMode() } if(g_keyhunt) { - game = GAME_KEYHUNT; - gamemode_name = "Key Hunt"; ActivateTeamplay(); fraglimit_override = autocvar_g_keyhunt_point_limit; leadlimit_override = autocvar_g_keyhunt_point_leadlimit; @@ -311,8 +212,6 @@ void InitGameplayMode() if(g_freezetag) { - game = GAME_FREEZETAG; - gamemode_name = "Freeze Tag"; ActivateTeamplay(); fraglimit_override = autocvar_g_freezetag_point_limit; leadlimit_override = autocvar_g_freezetag_point_leadlimit; @@ -321,8 +220,6 @@ void InitGameplayMode() if(g_assault) { - game = GAME_ASSAULT; - gamemode_name = "Assault"; ActivateTeamplay(); ScoreRules_assault(); have_team_spawns = -1; // request team spawns @@ -330,16 +227,12 @@ void InitGameplayMode() if(g_onslaught) { - game = GAME_ONSLAUGHT; - gamemode_name = "Onslaught"; ActivateTeamplay(); have_team_spawns = -1; // request team spawns } if(g_race) { - game = GAME_RACE; - gamemode_name = "Race"; if(autocvar_g_race_teams) { @@ -357,8 +250,6 @@ void InitGameplayMode() if(g_cts) { - game = GAME_CTS; - gamemode_name = "CTS"; g_race_qualifying = 1; fraglimit_override = 0; leadlimit_override = 0; @@ -366,8 +257,6 @@ void InitGameplayMode() if(g_nexball) { - game = GAME_NEXBALL; - gamemode_name = "Nexball"; fraglimit_override = autocvar_g_nexball_goallimit; leadlimit_override = autocvar_g_nexball_goalleadlimit; ActivateTeamplay(); @@ -377,17 +266,12 @@ void InitGameplayMode() if(g_keepaway) { - game = GAME_KEEPAWAY; - gamemode_name = "Keepaway"; MUTATOR_ADD(gamemode_keepaway); } - if(teams_matter) + if(teamplay) entcs_init(); - // save it (for the next startup) - cvar_set("gamecfg", ftos(game)); - cache_mutatormsg = strzone(""); cache_lastmutatormsg = strzone(""); @@ -437,7 +321,7 @@ void InitGameplayMode() } string GetClientVersionMessage() { - local string versionmsg; + string versionmsg; if (self.version_mismatch) { if(self.version < autocvar_gameversion) { versionmsg = "^3Your client version is outdated.\n\n\n### YOU WON'T BE ABLE TO PLAY ON THIS SERVER ###\n\n\nPlease update!!!^8"; @@ -450,56 +334,10 @@ string GetClientVersionMessage() { return versionmsg; } - -void PrintWelcomeMessage(entity pl) +string getwelcomemessage(void) { string s, modifications, motd; - if(self.cvar_scr_centertime == 0) return; - - if(autocvar_g_campaign) - { - if(self.classname == "player" && !self.BUTTON_INFO) - return; - } - else - { - if((time - self.jointime) > autocvar_welcome_message_time && !self.BUTTON_INFO) - return; - } - - if( !(timeoutStatus >= 1) ) { //really print the WelcomeMessage to the player every frame when timeout-seconds are shown or the game is restarted, to make sure that the shown number is accurate - if(self.welcomemessage_time > time) return; - self.welcomemessage_time = time + max(0.5, self.cvar_scr_centertime * 0.6); - } - - if(autocvar_g_campaign) - { - centerprint(pl, campaign_message); - return; - } - -//TODO GreEn`mArine: make the timeout-messages clientside as well (just like the ready restart countdown)! - if(!self.BUTTON_INFO) - { - // TODO get rid of this too - local string specString; - specString = NEWLINES; - //if(time < game_starttime) //also show the countdown when being a spectator - // specString = strcat(specString, "\n\n^1Game starts in ", ftos(ceil(game_starttime - time)), " seconds^7"); - //else - if (timeoutStatus != 0) - specString = strcat(specString, "\n\n", getTimeoutText(1)); - else - { - if(self.classname == "player") - return; - goto normal; - } - return centerprint_atprio(self, CENTERPRIO_SPAM, specString); - } - -:normal ret_string = ""; MUTATOR_CALLHOOK(BuildMutatorsPrettyString); modifications = ret_string; @@ -524,27 +362,28 @@ void PrintWelcomeMessage(entity pl) if(g_midair) modifications = strcat(modifications, ", Midair"); if(g_pinata) - modifications = strcat(modifications, ", Pinata"); + modifications = strcat(modifications, ", Piñata"); if(g_weapon_stay && !g_cts) modifications = strcat(modifications, ", Weapons stay"); if(g_bloodloss > 0) - modifications = strcat(modifications, ", Bloodloss"); + modifications = strcat(modifications, ", Blood loss"); if(g_jetpack) modifications = strcat(modifications, ", Jet pack"); + if(autocvar_g_powerups == 0) + modifications = strcat(modifications, ", No powerups"); + if(autocvar_g_powerups > 0) + modifications = strcat(modifications, ", Powerups"); modifications = substring(modifications, 2, strlen(modifications) - 2); - local string versionmessage; + string versionmessage; versionmessage = GetClientVersionMessage(); - s = strcat(s, NEWLINES, "This is Xonotic ", autocvar_g_xonoticversion, "\n", versionmessage); + s = strcat("This is Xonotic ", autocvar_g_xonoticversion, "\n", versionmessage); s = strcat(s, "^8\n\nmatch type is ^1", gamemode_name, "^8\n"); if(modifications != "") s = strcat(s, "^8\nactive modifications: ^3", modifications, "^8\n"); - if(timeoutStatus != 0) - s = strcat(s, "\n\n", getTimeoutText(1)); - if (g_grappling_hook) s = strcat(s, "\n\n^3grappling hook^8 is enabled, press 'e' to use it\n"); @@ -566,12 +405,9 @@ void PrintWelcomeMessage(entity pl) if (motd != "") { s = strcat(s, "\n\n^8MOTD: ^7", strreplace("\\n", "\n", motd)); } - s = strcat(s, "\n"); - - centerprint(pl, s); + return s; } - void SetPlayerColors(entity pl, float _color) { /*string s; @@ -586,7 +422,7 @@ void SetPlayerColors(entity pl, float _color) shirt = _color & 0xF0; - if(teams_matter) { + if(teamplay) { setcolor(pl, 16*pants + pants); } else { setcolor(pl, shirt + pants); @@ -903,7 +739,7 @@ float JoinBestTeam(entity pl, float only_return_best, float forcebestteam) float smallest, selectedteam; // don't join a team if we're not playing a team game - if(!teams_matter) + if(!teamplay) return 0; // find out what teams are available @@ -980,7 +816,7 @@ void SV_ChangeTeam(float _color) float scolor, dcolor, steam, dteam, dbotcount, scount, dcount; // in normal deathmatch we can just apply the color and we're done - if(!teams_matter) { + if(!teamplay) { SetPlayerColors(self, _color); return; } @@ -1327,13 +1163,13 @@ void AuditTeams() // code from here on is just to support maps that don't have team entities void tdm_spawnteam (string teamname, float teamcolor) { - local entity e; + entity e; e = spawn(); e.classname = "tdm_team"; e.netname = teamname; e.cnt = teamcolor; e.team = e.cnt + 1; -}; +} // spawn some default teams if the map is not set up for tdm void tdm_spawnteams() @@ -1351,16 +1187,16 @@ void tdm_spawnteams() tdm_spawnteam("Yellow", COLOR_TEAM3-1); if(numteams >= 4) tdm_spawnteam("Pink", COLOR_TEAM4-1); -}; +} void tdm_delayedinit() { // if no teams are found, spawn defaults if (find(world, classname, "tdm_team") == world) tdm_spawnteams(); -}; +} void tdm_init() { InitializeEntity(world, tdm_delayedinit, INITPRIO_GAMETYPE); -}; +} diff --git a/qcsrc/server/todo.txt b/qcsrc/server/todo.txt index c8f83abf78..bbe81a2f6d 100644 --- a/qcsrc/server/todo.txt +++ b/qcsrc/server/todo.txt @@ -1 +1,3 @@ -http://www.alientrap.org/devwiki/index.php?n=Xonotic.Todo (and get this Todo actually updated :P) +http://dev.xonotic.org/projects/xonotic/issues + +also: Maybe actually decide upon what to do with this todo file? No one uses it :P Just use the development tracker. \ No newline at end of file diff --git a/qcsrc/server/tturrets/include/turrets_early.qh b/qcsrc/server/tturrets/include/turrets_early.qh index 8cdd0f5097..9d108c6ae8 100644 --- a/qcsrc/server/tturrets/include/turrets_early.qh +++ b/qcsrc/server/tturrets/include/turrets_early.qh @@ -2,8 +2,8 @@ #define TTURRETS_ENABLED #ifdef TTURRETS_ENABLED - -#message "with tZork turrets" +#ifdef SVQC +//#message "with tZork turrets" float turret_count; @@ -37,6 +37,8 @@ vector real_origin(entity ent); #define TSF_NO_PATHBREAK 8 /// Dont respawn #define TSL_NO_RESPAWN 16 +/// Let this turret roam when idle. +#define TSL_ROAM 32 /// target selection flags .float target_select_flags; @@ -73,26 +75,16 @@ vector real_origin(entity ent); .float aim_flags; /// Dont aim. #define TFL_AIM_NO 1 -/// Go for ground, not direct hit -//#define TFL_AIM_GROUND 2 /// Go for ground, not direct hit, but only if target is on ground. -#define TFL_AIM_GROUND2 4 -/// Use balistic aim. FIXME: not implemented -#define TFL_AIM_BALISTIC 8 +#define TFL_AIM_GROUNDGROUND 2 /// Try to predict target movement (does not account for gravity) -#define TFL_AIM_LEAD 16 +#define TFL_AIM_LEAD 4 /// Compensate for shot traveltime when lead -#define TFL_AIM_SHOTTIMECOMPENSATE 32 -/// Aim slightly in front of target -#define TFL_AIM_INFRONT 64 -/// Aim slightly behind target -#define TFL_AIM_BEHIND 128 -/// blend real and predicted z positions. (fake bounce prediction) -// #define TFL_AIM_ZEASE 256 +#define TFL_AIM_SHOTTIMECOMPENSATE 8 /// Try to do real prediction of targets z pos at impact. -#define TFL_AIM_ZPREDICT 512 +#define TFL_AIM_ZPREDICT 16 /// Simply aim at target's current location -#define TFL_AIM_SIMPLE 1024 +#define TFL_AIM_SIMPLE 32 /// track (turn and pitch head) flags .float track_flags; @@ -109,7 +101,7 @@ vector real_origin(entity ent); #define TFL_TRACKTYPE_STEPMOTOR 1 /// Smoth absolute movement. Looks ok, fair accuracy. #define TFL_TRACKTYPE_FLUIDPRECISE 2 -/// Simulated inertia. "Wobbly mode" Looks kool, can mean really bad accuracy depending on how the feilds below are set +/// Simulated inertia. "Wobbly mode" Looks kool, can mean really bad accuracy depending on how the fields below are set #define TFL_TRACKTYPE_FLUIDINERTIA 3 /// TFL_TRACKTYPE_FLUIDINERTIA: pitch multiplier .float track_accel_pitch; @@ -120,8 +112,6 @@ vector real_origin(entity ent); /// How prefire check is preformed .float firecheck_flags; -/// Dont kill the world -#define TFL_FIRECHECK_WORLD 2 /// Dont kill the dead #define TFL_FIRECHECK_DEAD 4 /// Range limits apply @@ -145,7 +135,7 @@ vector real_origin(entity ent); /// Check own .attack_finished_single vs time #define TFL_FIRECHECK_REFIRE 4096 /// Move the acctual target to aimspot before tracing impact (and back after) -#define TFL_FIRECHECK_VERIFIED 8192 +//#define TFL_FIRECHECK_VERIFIED 8192 /// Dont do any chekcs #define TFL_FIRECHECK_NO 16384 @@ -201,7 +191,8 @@ vector real_origin(entity ent); #define TFL_TURRCAPS_ISTURRET 65536 /// Ammo types needed and/or provided -.float ammo_flags; +//.float ammo_flags; +#define ammo_flags currentammo /// Has and needs no ammo #define TFL_AMMO_NONE 64 /// Uses power @@ -235,8 +226,6 @@ vector real_origin(entity ent); #define TFL_DMG_HEADSHAKE 128 /// Die and stay dead. #define TFL_DMG_DEATH_NORESPAWN 256 -/// Supress std turret gibs on death -#define TFL_DMG_DEATH_NOGIBS 512 // Spawnflags /// Spawn in teambased modes @@ -263,9 +252,6 @@ vector real_origin(entity ent); /// Defend this entity (or ratehr this entitys position) .entity tur_defend; -/// on/off toggle. -.float tur_active; - /// and shoot from here. (can be non constant, think MLRS) .vector tur_shotorg; @@ -340,9 +326,10 @@ vector real_origin(entity ent); .float target_select_playerbias; /// Field of view //.float target_select_fov; -/// Last thimestamp this surret aquierd a valid target +/// Last timestamp this turret aquierd a valid target .float target_select_time; - +/// Throttle re-validation of current target +.float target_validate_time; /* * Aim refers to real aiming, not gun pos (thats done by track) */ @@ -399,33 +386,20 @@ void turret_fire(); .void() turret_diehook; .void() turret_respawnhook; -/* -#define TEH_THINK 2 -#define TEH_DAMAGE 4 -#define TEH_DIE 8 -#define TEH_RESPAWN 16 -#define TEH_TRACK 32 -#define TEH_AIM 64 -#define TEH_SELECT 128 -.float(float event_id) turret_eventhook; -*/ - - /* * Target selection, preferably but not nessesarely * return a normalized result. */ /// Function to use for target evaluation. usualy turret_stdproc_targetscore_generic -.float(entity e_turret, entity e_target) turret_score_target; - +.float(entity _turret, entity _target) turret_score_target; /* * Target selection */ /// Generic, fairly smart, bias-aware target selection. -float turret_stdproc_targetscore_generic(entity e_turret, entity e_target); +float turret_stdproc_targetscore_generic(entity _turret, entity _target); /// Experimental supportunits targetselector -float turret_stdproc_targetscore_support(entity e_turret,entity e_target); +float turret_stdproc_targetscore_support(entity _turret,entity _target); /* * Aim functions @@ -464,8 +438,35 @@ void turret_do_updates(entity e_turret); .vector tur_shotdir_updated; void turrets_precash(); - - +#endif // SVQC + +// common +.float turret_type; +float TID_COMMON = 1; +float TID_EWHEEL = 2; +float TID_FLAC = 3; +float TID_FUSION = 4; +float TID_HELLION = 5; +float TID_HK = 6; +float TID_MACHINEGUN = 7; +float TID_MLRS = 8; +float TID_PHASER = 9; +float TID_PLASMA = 10; +float TID_PLASMA_DUAL = 11; +float TID_TESLA = 12; +float TID_WALKER = 13; +float TID_LAST = 13; + +float TNSF_UPDATE = 2; +float TNSF_STATUS = 4; +float TNSF_SETUP = 8; +float TNSF_ANG = 16; +float TNSF_AVEL = 32; +float TNSF_MOVE = 64; +.float anim_start_time; +float TNSF_ANIM = 128; + +float TNSF_FULL_UPDATE = 16777215; #endif // TTURRETS_ENABLED diff --git a/qcsrc/server/tturrets/system/system_aimprocs.qc b/qcsrc/server/tturrets/system/system_aimprocs.qc index 80344a9e1f..a291e3ab15 100644 --- a/qcsrc/server/tturrets/system/system_aimprocs.qc +++ b/qcsrc/server/tturrets/system/system_aimprocs.qc @@ -3,41 +3,26 @@ supports: TFL_AIM_NO -TFL_AIM_GROUND2 +TFL_AIM_GROUNDGROUND TFL_AIM_LEAD TFL_AIM_SHOTTIMECOMPENSATE -TFL_AIM_INFRONT -TFL_AIM_BEHIND - -not supported: -TFL_AIM_BALISTIC - -removed -TFL_AIM_ZEASE -TFL_AIM_GROUND */ vector turret_stdproc_aim_generic() { - vector pre_pos,prep; - float distance,impact_time,i,mintime; + vector pre_pos, prep; + float distance, impact_time, i, mintime; turret_tag_fire_update(); if(self.aim_flags & TFL_AIM_SIMPLE) return real_origin(self.enemy); - mintime = max(self.attack_finished_single - time,0) + sys_frametime ; + mintime = max(self.attack_finished_single - time,0) + sys_frametime; // Baseline pre_pos = real_origin(self.enemy); - if (self.aim_flags & TFL_AIM_INFRONT) // Aim a bit in front of the target - pre_pos = pre_pos + (normalize(self.enemy.velocity) * 64); - - if (self.aim_flags & TFL_AIM_BEHIND) // Aim a bit behind the target - pre_pos = pre_pos - (normalize(self.enemy.velocity) * 32); - // Lead? if (self.aim_flags & TFL_AIM_LEAD) { @@ -73,7 +58,7 @@ vector turret_stdproc_aim_generic() pre_pos = pre_pos + self.enemy.velocity * mintime; } - if(self.aim_flags & TFL_AIM_GROUND2) + if(self.aim_flags & TFL_AIM_GROUNDGROUND) { //tracebox(pre_pos + '0 0 32',self.enemy.mins,self.enemy.maxs,pre_pos -'0 0 64',MOVE_WORLDONLY,self.enemy); traceline(pre_pos + '0 0 32',pre_pos -'0 0 64',MOVE_WORLDONLY,self.enemy); diff --git a/qcsrc/server/tturrets/system/system_damage.qc b/qcsrc/server/tturrets/system/system_damage.qc index b7af33af82..48f76219bd 100644 --- a/qcsrc/server/tturrets/system/system_damage.qc +++ b/qcsrc/server/tturrets/system/system_damage.qc @@ -1,180 +1,28 @@ /* -* Trow a turret gib +* Spawn a boom, trow fake bits arround +* and hide the real ones. */ -void turret_gib_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce) -{ - self.velocity += vforce; -} - -void turret_trowgib( - vector v_from, vector v_to, vector v_colormod, - string smodel, - float f_lifetime, float f_fadetime, float b_burn) +void turret_hide() { - local entity gib; - local entity burn; - - gib = spawn(); - - gib.classname = "turret_gib"; - setmodel(gib, smodel); - setorigin(gib, v_from); - SUB_SetFade(gib,time + f_lifetime, 2); - - gib.solid = SOLID_BBOX; - gib.movetype = MOVETYPE_BOUNCE; - gib.takedamage = DAMAGE_YES; - gib.event_damage = turret_gib_damage; - gib.health = -1; - gib.effects = EF_LOWPRECISION; - gib.flags = FL_NOTARGET; - gib.colormod = v_colormod; - gib.velocity = v_to; - - if (b_burn) - { - burn = spawn(); - burn.effects = EF_LOWPRECISION;//|EF_FLAME; - setattachment(burn,gib,""); - setorigin(burn,(gib.mins + gib.maxs) * 0.5); - SUB_SetFade(burn,time + (f_lifetime * 0.5), 2); - } -} - -void turret_gib_boom() -{ - entity gib; - float i; - string s; - - for (i = 1; i < 5; i = i +1) - { - gib = spawn(); - gib.classname = "turret_gib"; - - s = strcat("models/turrets/head-gib",ftos(i)); - s = strcat(s,".md3"); - setmodel(gib, s); - - setorigin(gib,self.origin); - - SUB_SetFade(gib,time + 5,2); - - gib.solid = SOLID_BBOX; - gib.movetype = MOVETYPE_BOUNCE; - gib.gravity = 0.5; - gib.damageforcescale = 2; - gib.takedamage = DAMAGE_YES; - gib.event_damage = turret_gib_damage; - gib.health = -1; - gib.effects = EF_LOWPRECISION; - gib.flags = FL_NOTARGET; - gib.velocity = self.velocity + (randomvec() * 700); - gib.avelocity = randomvec() * 64; - } - - WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); - WriteByte (MSG_BROADCAST, 78); - WriteCoord (MSG_BROADCAST, self.origin_x); - WriteCoord (MSG_BROADCAST, self.origin_y); - WriteCoord (MSG_BROADCAST, self.origin_z); - - remove(self); + self.effects |= EF_NODRAW; + self.nextthink = time + self.respawntime - 0.2; + self.think = turret_stdproc_respawn; } -void turret_trowgib2( - vector v_from, vector v_to, vector v_colormod, - entity e_mimic, float boomtime) -{ - entity gib; - - gib = spawn(); - - gib.classname = "turret_gib"; - setmodel(gib,e_mimic.model); - setorigin(gib,v_from); - - gib.solid = SOLID_BBOX; - - gib.movetype = MOVETYPE_BOUNCE; - gib.gravity = 0.75; - gib.damageforcescale = 2; - gib.takedamage = DAMAGE_YES; - gib.event_damage = turret_gib_damage; - gib.health = -1; - gib.effects = EF_LOWPRECISION; - gib.flags = FL_NOTARGET; - gib.colormod = v_colormod; - gib.velocity = v_to; - gib.avelocity = randomvec() * 32; - gib.think = turret_gib_boom; - gib.nextthink = boomtime; - //gib.effects = EF_FLAME; - - -} -/* -* Spawn a boom, trow fake bits arround -* and hide the real ones. -*/ void turret_stdproc_die() { - vector org2; - vector t_dir; - self.deadflag = DEAD_DEAD; self.tur_head.deadflag = self.deadflag; - sound (self, CHAN_PLAYER, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); - org2 = self.origin + '0 0 40'; - -// Explotion grafix - WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); - WriteByte (MSG_BROADCAST, 78); - WriteCoord (MSG_BROADCAST, org2_x); - WriteCoord (MSG_BROADCAST, org2_y); - WriteCoord (MSG_BROADCAST, org2_z); - // Unsolidify and hide real parts self.solid = SOLID_NOT; self.tur_head.solid = self.solid; - self.alpha = -1; - self.tur_head.alpha = self.alpha; - self.customizeentityforclient = SUB_False; - self.tur_head.customizeentityforclient = SUB_False; - self.event_damage = SUB_Null; self.takedamage = DAMAGE_NO; - self.effects = 0; - self.tur_head.effects = self.effects; self.health = 0; -// Trow fake parts arround - // base - if not(self.damage_flags & TFL_DMG_DEATH_NOGIBS) - { - makevectors(self.angles); - if (random() > 0.5) - { - turret_trowgib(self.origin, '0 0 0', '1 1 1', "models/turrets/base-gib2.md3", min(self.respawntime, 20), 1, 1); - - t_dir = (v_up * 700) + (randomvec() * 300); - turret_trowgib(self.origin, t_dir, '1 1 1', "models/turrets/base-gib3.md3", min(self.respawntime, 10), 1, 1); - - t_dir = (v_up * 700) + (randomvec() * 300); - turret_trowgib(self.origin, t_dir, '1 1 1', "models/turrets/base-gib4.md3", min(self.respawntime, 10), 1, 1); - } - else - { - turret_trowgib(self.origin, '0 0 0', '1 1 1', "models/turrets/base-gib1.md3", min(self.respawntime, 20), 1, 1); - } - - // Blow the top part up into the air - turret_trowgib2( self.origin + (v_up * 50), v_up * 150 + randomvec() * 50, '0.2 0.2 0.2', self.tur_head,time + 0.5 + (random() * 0.5)); - } - // Go boom //RadiusDamage (self,self, min(self.ammo,50),min(self.ammo,50) * 0.25,250,world,min(self.ammo,50)*5,DEATH_TURRET,world); @@ -189,52 +37,26 @@ void turret_stdproc_die() else { // Setup respawn - self.nextthink = time + self.respawntime; - self.think = turret_stdproc_respawn; + self.SendFlags |= TNSF_STATUS; + self.nextthink = time + 0.2; + self.think = turret_hide; if (self.turret_diehook) self.turret_diehook(); } } -var const float SUB_NullFloat(); void turret_stdproc_respawn() { // Make sure all parts belong to the same team since // this function doubles as "teamchange" function. - self.tur_head.team = self.team; - self.colormod = '0 0 0'; - - switch(self.team) - { - case COLOR_TEAM1: // Red - self.colormod = '1.4 0.8 0.8'; - break; - - case COLOR_TEAM2: // Blue - self.colormod = '0.8 0.8 1.4'; - break; - - case COLOR_TEAM3: // Yellow - self.colormod = '1.4 1.4 0.6'; - break; - - case COLOR_TEAM4: // Pink - self.colormod = '1.4 0.6 1.4'; - break; - } + self.effects &~= EF_NODRAW; self.deadflag = DEAD_NO; self.effects = EF_LOWPRECISION; - self.tur_head.effects = self.effects; self.solid = SOLID_BBOX; - self.alpha = 1; - self.tur_head.alpha = self.alpha; - self.customizeentityforclient = SUB_NullFloat; - self.tur_head.customizeentityforclient = SUB_NullFloat; - self.takedamage = DAMAGE_AIM; self.event_damage = turret_stdproc_damage; @@ -249,10 +71,11 @@ void turret_stdproc_respawn() self.nextthink = time + self.ticrate; self.think = turret_think; + + self.SendFlags = TNSF_FULL_UPDATE; if (self.turret_respawnhook) self.turret_respawnhook(); - } /* @@ -260,16 +83,15 @@ void turret_stdproc_respawn() */ void turret_stdproc_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce) { - // Enougth allready! - if (self.health <= 0) + if(self.deadflag == DEAD_DEAD) return; // Inactive turrets take no damage. (hm..) - if not (self.tur_active) + if not (self.active) return; - if (teams_matter) + if (teamplay) if (self.team == attacker.team) { // This does not happen anymore. Re-enable if you fix that. @@ -287,20 +109,15 @@ void turret_stdproc_damage (entity inflictor, entity attacker, float damage, flo // thorw head slightly off aim when hit? if (self.damage_flags & TFL_DMG_HEADSHAKE) { - //baseent.tur_aimoff_x += (random() * damage); - //baseent.tur_aimoff_y += ((random()*0.75) * damage); self.tur_head.angles_x = self.tur_head.angles_x + (-0.5 + random()) * damage; self.tur_head.angles_y = self.tur_head.angles_y + (-0.5 + random()) * damage; + + self.SendFlags |= TNSF_ANG; } if (self.turrcaps_flags & TFL_TURRCAPS_MOVE) self.velocity = self.velocity + vforce; - - // FIXME: Better damage feedback - // Start burning when we have 10% or less health left - //if (self.health < (self.tur_health * 0.1)) - // self.effects = EF_FLAME; - + if (self.health <= 0) { self.event_damage = SUB_Null; @@ -309,4 +126,6 @@ void turret_stdproc_damage (entity inflictor, entity attacker, float damage, flo self.nextthink = time; self.think = turret_stdproc_die; } + + self.SendFlags |= TNSF_STATUS; } diff --git a/qcsrc/server/tturrets/system/system_main.qc b/qcsrc/server/tturrets/system/system_main.qc index 4a2e886af8..7247a3a347 100644 --- a/qcsrc/server/tturrets/system/system_main.qc +++ b/qcsrc/server/tturrets/system/system_main.qc @@ -1,23 +1,80 @@ #define cvar_base "g_turrets_unit_" - -/* -float turret_customizeentityforclient() -{ +.float clientframe; +void turrets_setframe(float _frame, float client_only) +{ + if((client_only ? self.clientframe : self.frame ) != _frame) + { + self.SendFlags |= TNSF_ANIM; + self.anim_start_time = time; + } + + if(client_only) + self.clientframe = _frame; + else + self.frame = _frame; + } -float Turret_SendEntity(entity to, float sf) +float turret_send(entity to, float sf) { + + WriteByte(MSG_ENTITY, ENT_CLIENT_TURRET); + WriteByte(MSG_ENTITY, sf); + if(sf & TNSF_SETUP) + { + WriteByte(MSG_ENTITY, self.turret_type); + + WriteCoord(MSG_ENTITY, self.origin_x); + WriteCoord(MSG_ENTITY, self.origin_y); + WriteCoord(MSG_ENTITY, self.origin_z); + + WriteAngle(MSG_ENTITY, self.angles_x); + WriteAngle(MSG_ENTITY, self.angles_y); + } + + if(sf & TNSF_ANG) + { + WriteShort(MSG_ENTITY, rint(self.tur_head.angles_x)); + WriteShort(MSG_ENTITY, rint(self.tur_head.angles_y)); + } + + if(sf & TNSF_AVEL) + { + WriteShort(MSG_ENTITY, rint(self.tur_head.avelocity_x)); + WriteShort(MSG_ENTITY, rint(self.tur_head.avelocity_y)); + } + + if(sf & TNSF_MOVE) + { + WriteShort(MSG_ENTITY, rint(self.origin_x)); + WriteShort(MSG_ENTITY, rint(self.origin_y)); + WriteShort(MSG_ENTITY, rint(self.origin_z)); - WriteByte(MSG_ENTITY, ENT_CLIENT_TURRET); - WriteCoord(MSG_ENTITY, self.tur_head.angles_x); - WriteCoord(MSG_ENTITY, self.tur_head.angles_y); - WriteByte(MSG_ENTITY, self.tur_head.frame); - - //WriteCoord(MSG_ENTITY, self.tur_head.angles_z); - + WriteShort(MSG_ENTITY, rint(self.velocity_x)); + WriteShort(MSG_ENTITY, rint(self.velocity_y)); + WriteShort(MSG_ENTITY, rint(self.velocity_z)); + + WriteShort(MSG_ENTITY, rint(self.angles_y)); + } + + if(sf & TNSF_ANIM) + { + WriteCoord(MSG_ENTITY, self.anim_start_time); + WriteByte(MSG_ENTITY, self.frame); + } + + if(sf & TNSF_STATUS) + { + WriteByte(MSG_ENTITY, self.team); + + if(self.health <= 0) + WriteByte(MSG_ENTITY, 0); + else + WriteByte(MSG_ENTITY, ceil((self.health / self.tur_health) * 255)); + } + return TRUE; } -*/ void load_unit_settings(entity ent, string unitname, float is_reload) { @@ -84,6 +141,71 @@ void load_unit_settings(entity ent, string unitname, float is_reload) ent.turret_respawnhook(); } +void turret_projectile_explode() +{ + + self.takedamage = DAMAGE_NO; + self.event_damage = SUB_Null; +#ifdef TURRET_DEBUG + float d; + d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world); + self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; + self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg; +#else + RadiusDamage (self, self.realowner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world); +#endif + remove(self); +} + +void turret_projectile_touch() +{ + PROJECTILE_TOUCH; + turret_projectile_explode(); +} + +void turret_projectile_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce) +{ + self.velocity += vforce; + self.health -= damage; + //self.realowner = attacker; // Dont change realowner, it does not make much sense for turrets + if(self.health <= 0) + W_PrepareExplosionByDamage(self.owner, turret_projectile_explode); +} + +entity turret_projectile(string _snd, float _size, float _health, float _death, float _proj_type, float _cull, float _cli_anim) +{ + entity proj; + + sound (self, CH_WEAPON_A, _snd, VOL_BASE, ATTN_NORM); + proj = spawn (); + setorigin(proj, self.tur_shotorg); + setsize(proj, '-0.5 -0.5 -0.5' * _size, '0.5 0.5 0.5' * _size); + proj.owner = self; + proj.realowner = self; + proj.bot_dodge = TRUE; + proj.bot_dodgerating = self.shot_dmg; + proj.think = turret_projectile_explode; + proj.touch = turret_projectile_touch; + proj.nextthink = time + 9; + proj.movetype = MOVETYPE_FLYMISSILE; + proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed; + proj.flags = FL_PROJECTILE; + proj.enemy = self.enemy; + proj.totalfrags = _death; + PROJECTILE_MAKETRIGGER(proj); + if(_health) + { + proj.health = _health; + proj.takedamage = DAMAGE_YES; + proj.event_damage = turret_projectile_damage; + } + else + proj.flags |= FL_NOTARGET; + + CSQCProjectile(proj, _cli_anim, _proj_type, _cull); + + return proj; +} /** ** updates enemy distances, predicted impact point/time @@ -91,7 +213,7 @@ void load_unit_settings(entity ent, string unitname, float is_reload) **/ void turret_do_updates(entity t_turret) { - vector enemy_pos, oldpos; + vector enemy_pos; entity oldself; oldself = self; @@ -105,22 +227,20 @@ void turret_do_updates(entity t_turret) self.tur_dist_enemy = vlen(self.tur_shotorg - enemy_pos); self.tur_dist_aimpos = vlen(self.tur_shotorg - self.tur_aimpos); - if((self.firecheck_flags & TFL_FIRECHECK_VERIFIED) && (self.enemy)) + /*if((self.firecheck_flags & TFL_FIRECHECK_VERIFIED) && (self.enemy)) { oldpos = self.enemy.origin; - setorigin(self.enemy,self.tur_aimpos); - tracebox(self.tur_shotorg, '-1 -1 -1','1 1 1',self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos),MOVE_NORMAL,self); - setorigin(self.enemy,oldpos); + setorigin(self.enemy, self.tur_aimpos); + tracebox(self.tur_shotorg, '-1 -1 -1', '1 1 1', self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos), MOVE_NORMAL,self); + setorigin(self.enemy, oldpos); if(trace_ent == self.enemy) self.tur_dist_impact_to_aimpos = 0; else self.tur_dist_impact_to_aimpos = vlen(trace_endpos - self.tur_aimpos); - - } - else - tracebox(self.tur_shotorg, '-1 -1 -1','1 1 1', self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos),MOVE_NORMAL,self); + else*/ + tracebox(self.tur_shotorg, '-1 -1 -1','1 1 1', self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos), MOVE_NORMAL,self); self.tur_dist_impact_to_aimpos = vlen(trace_endpos - self.tur_aimpos) - (vlen(self.enemy.maxs - self.enemy.mins) * 0.5); self.tur_impactent = trace_ent; @@ -199,16 +319,20 @@ vector turret_fovsearch_random() ** Handles head rotation according to ** the units .track_type and .track_flags **/ +.float turret_framecounter; void turret_stdproc_track() { vector target_angle; // This is where we want to aim vector move_angle; // This is where we can aim float f_tmp; - + vector v1, v2; + v1 = self.tur_head.angles; + v2 = self.tur_head.avelocity; + if (self.track_flags == TFL_TRACK_NO) return; - if not (self.tur_active) + if not (self.active) target_angle = self.idle_aim - ('1 0 0' * self.aim_maxpitch); else if (self.enemy == world) { @@ -226,8 +350,11 @@ void turret_stdproc_track() self.tur_head.angles_y = anglemods(self.tur_head.angles_y); // Find the diffrence between where we currently aim and where we want to aim - move_angle = target_angle - (self.angles + self.tur_head.angles); - move_angle = shortangle_vxy(move_angle,(self.angles + self.tur_head.angles)); + //move_angle = target_angle - (self.angles + self.tur_head.angles); + //move_angle = shortangle_vxy(move_angle,(self.angles + self.tur_head.angles)); + + move_angle = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(self.angles), AnglesTransform_FromAngles(target_angle))) - self.tur_head.angles; + move_angle = shortangle_vxy(move_angle, self.tur_head.angles); switch(self.track_type) { @@ -252,7 +379,10 @@ void turret_stdproc_track() if(self.tur_head.angles_y < -self.aim_maxrot) self.tur_head.angles_y = self.aim_maxrot; } - + + // CSQC + self.SendFlags |= TNSF_ANG; + return; case TFL_TRACKTYPE_FLUIDINERTIA: @@ -278,12 +408,16 @@ void turret_stdproc_track() { self.tur_head.avelocity_x = 0; self.tur_head.angles_x = self.aim_maxpitch; + + self.SendFlags |= TNSF_ANG; } if((self.tur_head.angles_x + self.tur_head.avelocity_x * self.ticrate) < -self.aim_maxpitch) { self.tur_head.avelocity_x = 0; self.tur_head.angles_x = -self.aim_maxpitch; + + self.SendFlags |= TNSF_ANG; } } @@ -296,14 +430,28 @@ void turret_stdproc_track() { self.tur_head.avelocity_y = 0; self.tur_head.angles_y = self.aim_maxrot; + + self.SendFlags |= TNSF_ANG; } if((self.tur_head.angles_y + self.tur_head.avelocity_y * self.ticrate) < -self.aim_maxrot) { self.tur_head.avelocity_y = 0; self.tur_head.angles_y = -self.aim_maxrot; + + self.SendFlags |= TNSF_ANG; } } + + self.SendFlags |= TNSF_AVEL; + + // Force a angle update every 10'th frame + self.turret_framecounter += 1; + if(self.turret_framecounter >= 10) + { + self.SendFlags |= TNSF_ANG; + self.turret_framecounter = 0; + } } @@ -332,7 +480,11 @@ void turret_stdproc_track() float turret_stdproc_firecheck() { // This one just dont care =) - if (self.firecheck_flags & TFL_FIRECHECK_NO) return 1; + if (self.firecheck_flags & TFL_FIRECHECK_NO) + return 1; + + if (self.enemy == world) + return 0; // Ready? if (self.firecheck_flags & TFL_FIRECHECK_REFIRE) @@ -349,11 +501,6 @@ float turret_stdproc_firecheck() if (self.enemy.deadflag != DEAD_NO) return 0; - // Plz stop killing the world! - if (self.firecheck_flags & TFL_FIRECHECK_WORLD) - if (self.enemy == world) - return 0; - // Own ammo? if (self.firecheck_flags & TFL_FIRECHECK_OWM_AMMO) if (self.ammo < self.shot_dmg) @@ -397,9 +544,9 @@ float turret_stdproc_firecheck() if (self.ammo < (self.shot_dmg * self.shot_volly)) return 0; - if(self.firecheck_flags & TFL_FIRECHECK_VERIFIED) + /*if(self.firecheck_flags & TFL_FIRECHECK_VERIFIED) if(self.tur_impactent != self.enemy) - return 0; + return 0;*/ return 1; } @@ -424,7 +571,7 @@ float turret_stdproc_firecheck() float turret_validate_target(entity e_turret, entity e_target, float validate_flags) { vector v_tmp; - + //if(!validate_flags & TFL_TARGETSELECT_NOBUILTIN) // return -0.5; @@ -432,7 +579,7 @@ float turret_validate_target(entity e_turret, entity e_target, float validate_fl return -0.5; if not(checkpvs(e_target.origin, e_turret)) - return -1; + return -1; if not (e_target) return -2; @@ -449,7 +596,12 @@ float turret_validate_target(entity e_turret, entity e_target, float validate_fl return -5; // Cant touch this - if (e_target.health < 0) + if(e_target.vehicle_flags & VHF_ISVEHICLE) + { + if (e_target.vehicle_health <= 0) + return -6; + } + else if (e_target.health <= 0) return -6; // player @@ -537,7 +689,7 @@ float turret_validate_target(entity e_turret, entity e_target, float validate_fl { v_tmp = real_origin(e_target) + ((e_target.mins + e_target.maxs) * 0.5); - traceline(e_turret.tur_shotorg, v_tmp, 0, e_turret); + traceline(e_turret.origin + '0 0 16', v_tmp, 0, e_turret); if (e_turret.aim_firetolerance_dist < vlen(v_tmp - trace_endpos)) return -19; @@ -586,7 +738,9 @@ entity turret_select_target() { if(e.takedamage) { - if (turret_validate_target(self, e, self.target_select_flags) > 0) + float f = turret_validate_target(self, e, self.target_select_flags); + //dprint("F is: ", ftos(f), "\n"); + if ( f > 0) { score = self.turret_score_target(self,e); if ((score > m_score) && (score > 0)) @@ -607,11 +761,11 @@ void turret_think() entity e; self.nextthink = time + self.ticrate; - + // ONS uses somewhat backwards linking. - if (teams_matter) + if (teamplay) { - if not (g_onslaught) + if (g_onslaught) if (self.target) { e = find(world, targetname,self.target); @@ -636,10 +790,10 @@ void turret_think() if not (self.spawnflags & TSF_NO_AMMO_REGEN) if (self.ammo < self.ammo_max) self.ammo = min(self.ammo + self.ammo_recharge, self.ammo_max); - + // Inactive turrets needs to run the think loop, // So they can handle animation and wake up if need be. - if not (self.tur_active) + if not (self.active) { turret_stdproc_track(); return; @@ -722,9 +876,11 @@ void turret_think() do_target_scan = 1; // Old target (if any) invalid? + if(self.target_validate_time < time) if (turret_validate_target(self, self.enemy, self.target_validate_flags) <= 0) { self.enemy = world; + self.target_validate_time = time + 0.5; do_target_scan = 1; } @@ -818,17 +974,18 @@ void turret_stdproc_use() self.team = activator.team; if(self.team == 0) - self.tur_active = 0; + self.active = ACTIVE_NOT; else - self.tur_active = 1; + self.active = ACTIVE_ACTIVE; } void turret_link() { - //Net_LinkEntity(self, FALSE, 0, Turret_SendEntity); + Net_LinkEntity(self, TRUE, 0, turret_send); self.think = turret_think; self.nextthink = time; + self.tur_head.effects = EF_NODRAW; } void turrets_manager_think() @@ -859,47 +1016,36 @@ void turrets_manager_think() * (unless you have a very good reason not to) * if the return value is 0, the turret should be removed. */ -float turret_stdproc_init (string cvar_base_name, float csqc_shared, string base, string head) +float turret_stdproc_init (string cvar_base_name, string base, string head, float _turret_type) { entity e, ee; // Are turrets allowed? if (autocvar_g_turrets == 0) return 0; - - + + if(_turret_type < 1 || _turret_type > TID_LAST) + { + dprint("Invalid / Unkown turret type\"", ftos(_turret_type), "\", aborting!\n"); + return 0; + } + self.turret_type = _turret_type; + e = find(world, classname, "turret_manager"); if not (e) { e = spawn(); - - setorigin(e,'0 0 0'); - setmodel(e,"models/turrets/plasma.md3"); - vector v; - v = gettaginfo(e,gettagindex(e,"tag_fire")); - if(v == '0 0 0') - { - //objerror("^1ERROR: Engine is borken! Turrets will NOT work. force g_turrets to 0 to run maps with turrets anyway."); - //crash(); - } - setmodel(e,""); - e.classname = "turret_manager"; e.think = turrets_manager_think; e.nextthink = time + 2; } - - if(csqc_shared) - { - dprint("WARNING: turret requested csqc_shared but this is not implemented. Expect strange things to happen.\n"); - csqc_shared = 0; - } - + if not (self.spawnflags & TSF_SUSPENDED) - droptofloor_builtin(); + builtin_droptofloor(); // why can't we use regular droptofloor here? // Terrainbase spawnflag. This puts a enlongated model // under the turret, so it looks ok on uneaven surfaces. + /* TODO: Handle this with CSQC if (self.spawnflags & TSF_TERRAINBASE) { entity tb; @@ -908,17 +1054,20 @@ float turret_stdproc_init (string cvar_base_name, float csqc_shared, string base setorigin(tb,self.origin); tb.solid = SOLID_BBOX; } + */ self.cvar_basename = cvar_base_name; - load_unit_settings(self,self.cvar_basename, 0); + load_unit_settings(self, self.cvar_basename, 0); + self.effects = EF_NODRAW; + // Handle turret teams. if (autocvar_g_assault != 0) { if not (self.team) self.team = 14; // Assume turrets are on the defending side if not explicitly set otehrwize } - else if not (teams_matter) + else if not (teamplay) self.team = MAX_SHOT_DISTANCE; // Group all turrets into the same team, so they dont kill eachother. else if(g_onslaught && self.targetname) { @@ -939,11 +1088,14 @@ float turret_stdproc_init (string cvar_base_name, float csqc_shared, string base * if it hits a glitch in my logic :P so try to set as mutch * as possible beforehand. */ - if (self.turrcaps_flags & TFL_TURRCAPS_SUPPORT) - self.ticrate = 0.2; // Support units generaly dont need to have a high speed ai-loop - else - self.ticrate = 0.1; // 10 fps for normal turrets - + if not(self.ticrate) + { + if (self.turrcaps_flags & TFL_TURRCAPS_SUPPORT) + self.ticrate = 0.2; // Support units generaly dont need to have a high speed ai-loop + else + self.ticrate = 0.1; // 10 fps for normal turrets + } + self.ticrate = bound(sys_frametime, self.ticrate, 60); // keep it sane // General stuff @@ -998,9 +1150,9 @@ float turret_stdproc_init (string cvar_base_name, float csqc_shared, string base self.shot_volly_refire = bound(self.shot_refire, self.shot_volly_refire, 60); if not (self.firecheck_flags) - self.firecheck_flags = TFL_FIRECHECK_WORLD | TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | + self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_LOS | TFL_FIRECHECK_AIMDIST | TFL_FIRECHECK_TEAMCECK | - TFL_FIRECHECK_OWM_AMMO | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_WORLD; + TFL_FIRECHECK_OWM_AMMO | TFL_FIRECHECK_REFIRE; // Range stuff. if not (self.target_range) @@ -1037,7 +1189,7 @@ float turret_stdproc_init (string cvar_base_name, float csqc_shared, string base { self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE; if(self.turrcaps_flags & TFL_TURRCAPS_RADIUSDMG) - self.aim_flags |= TFL_AIM_GROUND2; + self.aim_flags |= TFL_AIM_GROUNDGROUND; } if not (self.track_type) @@ -1101,7 +1253,6 @@ float turret_stdproc_init (string cvar_base_name, float csqc_shared, string base self.target_validate_flags = self.target_select_flags; - // Ammo stuff if not (self.ammo_max) self.ammo_max = self.shot_dmg * 10; @@ -1128,6 +1279,13 @@ float turret_stdproc_init (string cvar_base_name, float csqc_shared, string base // Offsets & origins if (!self.tur_shotorg) self.tur_shotorg = '50 0 50'; + + if (!self.health) + self.health = 150; + +// Game hooks + if(MUTATOR_CALLHOOK(TurretSpawn)) + return 0; // End of default & sanety checks, start building the turret. @@ -1146,9 +1304,6 @@ float turret_stdproc_init (string cvar_base_name, float csqc_shared, string base setorigin(self.tur_head, '0 0 0'); setattachment(self.tur_head, self, "tag_head"); - if (!self.health) - self.health = 150; - self.tur_health = self.health; self.solid = SOLID_BBOX; self.tur_head.solid = SOLID_NOT; @@ -1175,35 +1330,19 @@ float turret_stdproc_init (string cvar_base_name, float csqc_shared, string base else self.idle_aim = '0 0 0'; - // Team color - if (self.team == COLOR_TEAM1) self.colormod = '1.4 0.8 0.8'; - if (self.team == COLOR_TEAM2) self.colormod = '0.8 0.8 1.4'; - // Attach stdprocs. override when and what needed + self.turret_firecheckfunc = turret_stdproc_firecheck; + self.turret_firefunc = turret_stdproc_fire; + self.event_damage = turret_stdproc_damage; + if (self.turrcaps_flags & TFL_TURRCAPS_SUPPORT) - { self.turret_score_target = turret_stdproc_targetscore_support; - self.turret_firecheckfunc = turret_stdproc_firecheck; - self.turret_firefunc = turret_stdproc_fire; - self.event_damage = turret_stdproc_damage; - } else - { self.turret_score_target = turret_stdproc_targetscore_generic; - self.turret_firecheckfunc = turret_stdproc_firecheck; - self.turret_firefunc = turret_stdproc_fire; - self.event_damage = turret_stdproc_damage; - } self.use = turret_stdproc_use; self.bot_attack = TRUE; - // Initiate the main AI loop - if(csqc_shared) - self.think = turret_link; - else - self.think = turret_think; - ++turret_count; self.nextthink = time + 1; self.nextthink += turret_count * sys_frametime; @@ -1226,7 +1365,7 @@ float turret_stdproc_init (string cvar_base_name, float csqc_shared, string base self.classname = "turret_main"; - self.tur_active = 1; + self.active = ACTIVE_ACTIVE; // In ONS mode, and linked to a ONS ent. need to call the use to set team. if (g_onslaught && ee) @@ -1234,8 +1373,11 @@ float turret_stdproc_init (string cvar_base_name, float csqc_shared, string base activator = ee; self.use(); } - - turret_stdproc_respawn(); + + turret_link(); + turret_stdproc_respawn(); + turret_tag_fire_update(); + return 1; } diff --git a/qcsrc/server/tturrets/system/system_misc.qc b/qcsrc/server/tturrets/system/system_misc.qc index 7b2875d7dc..1c0a3bad52 100644 --- a/qcsrc/server/tturrets/system/system_misc.qc +++ b/qcsrc/server/tturrets/system/system_misc.qc @@ -113,7 +113,8 @@ vector angleofs3(vector from, vector from_a, entity to) * Update self.tur_shotorg by getting up2date bone info * NOTICE this func overwrites the global v_forward, v_right and v_up vectors. */ -float turret_tag_fire_update() +#define turret_tag_fire_update() self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire"));v_forward = normalize(v_forward) +float turret_tag_fire_update_s() { if(!self.tur_head) { @@ -135,8 +136,8 @@ void FireImoBeam (vector start, vector end, vector smin, vector smax, float bforce, float f_dmg, float f_velfactor, float deathtype) { - local vector hitloc, force, endpoint, dir; - local entity ent; + vector hitloc, force, endpoint, dir; + entity ent; dir = normalize(end - start); force = dir * bforce; @@ -221,34 +222,6 @@ void turrets_precache_debug_models() void turrets_precash() { - precache_model ("models/turrets/base-gib1.md3"); - precache_model ("models/turrets/base-gib2.md3"); - precache_model ("models/turrets/base-gib3.md3"); - precache_model ("models/turrets/base-gib4.md3"); - - precache_model ("models/turrets/head-gib1.md3"); - precache_model ("models/turrets/head-gib2.md3"); - precache_model ("models/turrets/head-gib3.md3"); - precache_model ("models/turrets/head-gib4.md3"); - precache_model ("models/turrets/terrainbase.md3"); - - //precache_model ("models/turrets/base.md3"); - //precache_model ("models/turrets/flac.md3"); - //precache_model ("models/turrets/pd_proj.md3"); - //precache_model ("models/turrets/reactor.md3"); - //precache_model ("models/turrets/mlrs_rocket.md3"); - //precache_model ("models/turrets/hellion.md3"); - //precache_model ("models/turrets/hunter2.md3"); - //precache_model ("models/turrets/hk.md3"); - //precache_model ("models/turrets/machinegun.md3"); - //precache_model ("models/turrets/rocket.md3"); - //precache_model ("models/turrets/mlrs.md3"); - //precache_model ("models/turrets/phaser.md3"); - //precache_model ("models/turrets/phaser_beam.md3"); - //precache_model ("models/turrets/plasmad.md3"); - //precache_model ("models/turrets/plasma.md3"); - //precache_model ("models/turrets/tesla_head.md3"); - //precache_model ("models/turrets/tesla_base.md3"); #ifdef TURRET_DEBUG turrets_precache_debug_models(); #endif diff --git a/qcsrc/server/tturrets/system/system_scoreprocs.qc b/qcsrc/server/tturrets/system/system_scoreprocs.qc index 32c7856a3d..05717bf184 100644 --- a/qcsrc/server/tturrets/system/system_scoreprocs.qc +++ b/qcsrc/server/tturrets/system/system_scoreprocs.qc @@ -1,28 +1,14 @@ -/* -.float target_select_flags; /// target selection flags -float TFL_TARGETSELECT_NO = 1; /// Dont select a target on its own. -float TFL_TARGETSELECT_LOS = 2; /// Need line of sight -float TFL_TARGETSELECT_PLAYERS = 4; /// Players are valid targets -float TFL_TARGETSELECT_MISSILES = 8; /// Missiles are valid targets -float TFL_TARGETSELECT_TRIGGERTARGET = 16; /// Responds to turret_trigger_target events -float TFL_TARGETSELECT_ANGLELIMITS = 32; /// Angular limitations of turret head limits target selection -float TFL_TARGETSELECT_RANGELIMTS = 64; /// Range limits apply in targetselection -float TFL_TARGETSELECT_TEAMCHECK = 128; /// Consider team own <-> targets team -float TFL_TARGETSELECT_NOBUILTIN = 256; /// Cant select targets on its own. needs to be triggerd or slaved. -float TFL_TARGETSELECT_OWNTEAM = 512; -*/ - -float turret_stdproc_targetscore_support(entity e_turret,entity e_target) +float turret_stdproc_targetscore_support(entity _turret,entity _target) { float score; // Total score - float s_score,d_score; + float s_score, d_score; - if (e_turret.enemy == e_target) s_score = 1; + if (_turret.enemy == _target) s_score = 1; - d_score = min(e_turret.target_range_optimal,tvt_dist) / max(e_turret.target_range_optimal,tvt_dist); + d_score = min(_turret.target_range_optimal,tvt_dist) / max(_turret.target_range_optimal,tvt_dist); - score = (d_score * e_turret.target_select_rangebias) + - (s_score * e_turret.target_select_samebias); + score = (d_score * _turret.target_select_rangebias) + + (s_score * _turret.target_select_samebias); return score; } @@ -30,58 +16,35 @@ float turret_stdproc_targetscore_support(entity e_turret,entity e_target) /* * Generic bias aware score system. */ -float turret_stdproc_targetscore_generic(entity e_turret, entity e_target) +float turret_stdproc_targetscore_generic(entity _turret, entity _target) { - //vector v_tmp; float d_dist; // Defendmode Distance - float score; // Total score - float d_score; // Distance score float a_score; // Angular score float m_score; // missile score float p_score; // player score - //float da_score; // Distance from aimpoint score - float ikr; // ideal kill range - /* - if(!e_target) - return 0; - */ - - if (e_turret.tur_defend) + if (_turret.tur_defend) { - d_dist = vlen(real_origin(e_target) - e_turret.tur_defend.origin); - ikr = vlen(e_turret.origin - e_turret.tur_defend.origin); - d_score = 1 - d_dist / e_turret.target_range; + d_dist = vlen(real_origin(_target) - _turret.tur_defend.origin); + ikr = vlen(_turret.origin - _turret.tur_defend.origin); + d_score = 1 - d_dist / _turret.target_range; } else { // Make a normlized value base on the targets distance from our optimal killzone - ikr = e_turret.target_range_optimal; - d_score = min(ikr,tvt_dist) / max(ikr,tvt_dist); + ikr = _turret.target_range_optimal; + d_score = min(ikr, tvt_dist) / max(ikr, tvt_dist); } - /* - // Determine the maximum time it could take this turrent to aim at someting. - max_aim_delay = (max(e_turret.aim_maxrot,e_turret.aim_maxpitch) / e_turret.aim_speed * 2); - - // Find out how long it would take to aim at this taget. - aim_delay = (thadf+0.01) / e_turret.aim_speed; - - // Turn this info into a normalized value. - aim_delay = (min(max_aim_delay,aim_delay) / max_aim_delay); - a_score = 1 - aim_delay; - */ - - //a_score = 1 - (tvt_thadf / max(e_turret.aim_maxrot,e_turret.aim_maxpitch)); - a_score = 1 - tvt_thadf / e_turret.aim_maxrot; + a_score = 1 - tvt_thadf / _turret.aim_maxrot; - if ((e_turret.target_select_missilebias > 0) && (e_target.flags & FL_PROJECTILE)) + if ((_turret.target_select_missilebias > 0) && (_target.flags & FL_PROJECTILE)) m_score = 1; - if ((e_turret.target_select_playerbias > 0) && (e_target.flags & FL_CLIENT)) + if ((_turret.target_select_playerbias > 0) && (_target.flags & FL_CLIENT)) p_score = 1; d_score = max(d_score, 0); @@ -89,14 +52,14 @@ float turret_stdproc_targetscore_generic(entity e_turret, entity e_target) m_score = max(m_score, 0); p_score = max(p_score, 0); - score = (d_score * e_turret.target_select_rangebias) + - (a_score * e_turret.target_select_anglebias) + - (m_score * e_turret.target_select_missilebias) + - (p_score * e_turret.target_select_playerbias); + score = (d_score * _turret.target_select_rangebias) + + (a_score * _turret.target_select_anglebias) + + (m_score * _turret.target_select_missilebias) + + (p_score * _turret.target_select_playerbias); - if(e_turret.target_range < vlen(e_turret.tur_shotorg - real_origin(e_target))) + if(_turret.target_range < vlen(_turret.tur_shotorg - real_origin(_target))) { - dprint("Wtf?\n"); + //dprint("Wtf?\n"); score *= 0.001; } @@ -105,28 +68,28 @@ float turret_stdproc_targetscore_generic(entity e_turret, entity e_target) string sdt,sat,smt,spt; sd = ftos(d_score); - d_score *= e_turret.target_select_rangebias; + d_score *= _turret.target_select_rangebias; sdt = ftos(d_score); //sv = ftos(v_score); - //v_score *= e_turret.target_select_samebias; + //v_score *= _turret.target_select_samebias; //svt = ftos(v_score); sa = ftos(a_score); - a_score *= e_turret.target_select_anglebias; + a_score *= _turret.target_select_anglebias; sat = ftos(a_score); sm = ftos(m_score); - m_score *= e_turret.target_select_missilebias; + m_score *= _turret.target_select_missilebias; smt = ftos(m_score); sp = ftos(p_score); - p_score *= e_turret.target_select_playerbias; + p_score *= _turret.target_select_playerbias; spt = ftos(p_score); ss = ftos(score); - bprint("^3Target scores^7 \[ ",e_turret.netname, " \] ^3for^7 \[ ", e_target.netname," \]\n"); + bprint("^3Target scores^7 \[ ",_turret.netname, " \] ^3for^7 \[ ", _target.netname," \]\n"); bprint("^5Range:\[ ",sd, " \]^2+bias:\[ ",sdt," \]\n"); bprint("^5Angle:\[ ",sa, " \]^2+bias:\[ ",sat," \]\n"); bprint("^5Missile:\[ ",sm," \]^2+bias:\[ ",smt," \]\n"); @@ -139,29 +102,29 @@ float turret_stdproc_targetscore_generic(entity e_turret, entity e_target) } /* -float turret_stdproc_targetscore_close(entity e_turret,entity e_target) +float turret_stdproc_targetscore_close(entity _turret,entity _target) { - return 1 - (tvt_dist / e_turret.target_range); + return 1 - (tvt_dist / _turret.target_range); } -float turret_stdproc_targetscore_far (entity e_turret,entity e_target) +float turret_stdproc_targetscore_far (entity _turret,entity _target) { - return tvt_dist / e_turret.target_range; + return tvt_dist / _turret.target_range; } -float turret_stdproc_targetscore_optimal(entity e_turret,entity e_target) +float turret_stdproc_targetscore_optimal(entity _turret,entity _target) { - return min(e_turret.target_range_optimal,tvt_dist) / max(e_turret.target_range_optimal,tvt_dist); + return min(_turret.target_range_optimal,tvt_dist) / max(_turret.target_range_optimal,tvt_dist); } -float turret_stdproc_score_angular(entity e_turret,entity e_target) +float turret_stdproc_score_angular(entity _turret,entity _target) { - return 1 - (tvt_thadf / e_turret.aim_maxrot); + return 1 - (tvt_thadf / _turret.aim_maxrot); } -float turret_stdproc_targetscore_defend(entity e_turret,entity e_target) +float turret_stdproc_targetscore_defend(entity _turret,entity _target) { return 0; - //min(e_target.origin,e_turret.tur_defend.origin) / max(e_target.origin,e_turret.tur_defend.origin); + //min(_target.origin,_turret.tur_defend.origin) / max(_target.origin,_turret.tur_defend.origin); } */ diff --git a/qcsrc/server/tturrets/units/unit_checkpoint.qc b/qcsrc/server/tturrets/units/unit_checkpoint.qc index 8a581ea399..481b4a285d 100644 --- a/qcsrc/server/tturrets/units/unit_checkpoint.qc +++ b/qcsrc/server/tturrets/units/unit_checkpoint.qc @@ -33,6 +33,15 @@ void turret_checkpoint_use() { } +#if 0 +void turret_checkpoint_think() +{ + if(self.enemy) + te_lightning1(self,self.origin, self.enemy.origin); + + self.nextthink = time + 0.25; +} +#endif /*QUAKED turret_checkpoint (1 0 1) (-32 -32 -32) (32 32 32) -----------KEYS------------ target: .targetname of next waypoint in chain. @@ -42,24 +51,28 @@ wait: Pause at this point # seconds. If a loop is of targets are formed, any unit entering this loop will patrol it indefinitly. If the checkpoint chain in not looped, the unit will go "Roaming" when the last point is reached. */ +//float tc_acum; void turret_checkpoint_init() { - traceline(self.origin, self.origin - '0 0 1024', MOVE_WORLDONLY, self); - setorigin(self,trace_endpos + '0 0 8'); + traceline(self.origin + '0 0 16', self.origin - '0 0 1024', MOVE_WORLDONLY, self); + setorigin(self, trace_endpos + '0 0 32'); if(self.target != "") { - self.enemy = find(world,targetname,self.target); + self.enemy = find(world, targetname, self.target); if(self.enemy == world) dprint("A turret_checkpoint faild to find its target!\n"); } + //self.think = turret_checkpoint_think; + //self.nextthink = time + tc_acum + 0.25; + //tc_acum += 0.25; } void spawnfunc_turret_checkpoint() { setorigin(self,self.origin); self.think = turret_checkpoint_init; - self.nextthink = time + 0.1; + self.nextthink = time + 0.2; } // Compat. diff --git a/qcsrc/server/tturrets/units/unit_common.qc b/qcsrc/server/tturrets/units/unit_common.qc deleted file mode 100644 index 8b13789179..0000000000 --- a/qcsrc/server/tturrets/units/unit_common.qc +++ /dev/null @@ -1 +0,0 @@ - diff --git a/qcsrc/server/tturrets/units/unit_ewheel.qc b/qcsrc/server/tturrets/units/unit_ewheel.qc index 02c0ffa601..6b8f8e7d4c 100644 --- a/qcsrc/server/tturrets/units/unit_ewheel.qc +++ b/qcsrc/server/tturrets/units/unit_ewheel.qc @@ -4,71 +4,17 @@ #define ewheel_amin_bck_slow 3 #define ewheel_amin_bck_fast 4 -float ewheel_speed_fast; -float ewheel_speed_slow; -float ewheel_speed_slower; -float ewheel_speed_stop; - -void turret_ewheel_loadcvars() -{ - ewheel_speed_fast = autocvar_g_turrets_unit_ewheel_speed_fast; - ewheel_speed_slow = autocvar_g_turrets_unit_ewheel_speed_slow; - ewheel_speed_slower = autocvar_g_turrets_unit_ewheel_speed_slower; - ewheel_speed_stop = autocvar_g_turrets_unit_ewheel_speed_stop; -} - -void turret_ewheel_projectile_explode() -{ - vector org2; - - org2 = findbetterlocation (self.origin, 8); - pointparticles(particleeffectnum("laser_impact"), org2, trace_plane_normal * 1000, 1); - //w_deathtypestring = "saw the eweel. to late."; -#ifdef TURRET_DEBUG - float d; - - d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world); - self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; - self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg; -#else - RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world); -#endif - sound (self, CHAN_PROJECTILE, "weapons/electro_impact.wav", VOL_BASE, ATTN_NORM); - - remove (self); -} - - void ewheel_attack() { - entity proj; float i; for (i = 0; i < 1; ++i) { turret_do_updates(self); - sound (self, CHAN_WEAPON, "weapons/lasergun_fire.wav", VOL_BASE, ATTN_NORM); + turret_projectile("weapons/lasergun_fire.wav", 1, 0, DEATH_TURRET_EWHEEL, PROJECTILE_LASER, TRUE, TRUE); pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1); - proj = spawn (); - setorigin(proj, self.tur_shotorg); - proj.classname = "ewheel bolt"; - proj.owner = self; - proj.bot_dodge = FALSE; - proj.bot_dodgerating = self.shot_dmg; - proj.think = turret_ewheel_projectile_explode; - proj.nextthink = time + 9; - //proj.solid = SOLID_TRIGGER; - proj.movetype = MOVETYPE_FLYMISSILE; - proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed; - proj.touch = turret_ewheel_projectile_explode; - proj.enemy = self.enemy; - proj.flags = FL_PROJECTILE | FL_NOTARGET; - PROJECTILE_MAKETRIGGER(proj); - - CSQCProjectile(proj, TRUE, PROJECTILE_LASER, TRUE); - self.tur_head.frame += 2; if (self.tur_head.frame > 3) @@ -76,10 +22,10 @@ void ewheel_attack() } } - +//#define EWHEEL_FANCYPATH void ewheel_move_path() { - +#ifdef EWHEEL_FANCYPATH // Are we close enougth to a path node to switch to the next? if (vlen(self.origin - self.pathcurrent.origin) < 64) if (self.pathcurrent.path_next == world) @@ -105,7 +51,10 @@ void ewheel_move_path() else self.pathcurrent = self.pathcurrent.path_next; - +#else + if (vlen(self.origin - self.pathcurrent.origin) < 64) + self.pathcurrent = self.pathcurrent.enemy; +#endif if (self.pathcurrent) { @@ -113,15 +62,15 @@ void ewheel_move_path() self.moveto = self.pathcurrent.origin; self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95); - movelib_move_simple(v_forward, ewheel_speed_fast, 0.4); - - return; + movelib_move_simple(v_forward, autocvar_g_turrets_unit_ewheel_speed_fast, 0.4); } } void ewheel_move_enemy() { + float newframe; + self.steerto = steerlib_arrive(self.enemy.origin,self.target_range_optimal); //self.steerto = steerlib_standoff(self.enemy.origin,self.target_range_optimal); @@ -132,75 +81,77 @@ void ewheel_move_enemy() { if ( self.tur_head.spawnshieldtime < 1 ) { - self.frame = ewheel_amin_fwd_fast; - movelib_move_simple(v_forward, ewheel_speed_fast, 0.4); + newframe = ewheel_amin_fwd_fast; + movelib_move_simple(v_forward, autocvar_g_turrets_unit_ewheel_speed_fast, 0.4); } else if (self.tur_head.spawnshieldtime < 2) { - self.frame = ewheel_amin_fwd_slow; - movelib_move_simple(v_forward, ewheel_speed_slow, 0.4); + newframe = ewheel_amin_fwd_slow; + movelib_move_simple(v_forward, autocvar_g_turrets_unit_ewheel_speed_slow, 0.4); } else { - self.frame = ewheel_amin_fwd_slow; - movelib_move_simple(v_forward, ewheel_speed_slower, 0.4); + newframe = ewheel_amin_fwd_slow; + movelib_move_simple(v_forward, autocvar_g_turrets_unit_ewheel_speed_slower, 0.4); } } else if (self.tur_dist_enemy < self.target_range_optimal * 0.5) { - self.frame = ewheel_amin_bck_slow; - movelib_move_simple(v_forward * -1, ewheel_speed_slow, 0.4); + newframe = ewheel_amin_bck_slow; + movelib_move_simple(v_forward * -1, autocvar_g_turrets_unit_ewheel_speed_slow, 0.4); } else { - self.frame = ewheel_amin_stop; - movelib_beak_simple(ewheel_speed_stop); + newframe = ewheel_amin_stop; + movelib_beak_simple(autocvar_g_turrets_unit_ewheel_speed_stop); } + + turrets_setframe(newframe , FALSE); + + /*if(self.frame != newframe) + { + self.frame = newframe; + self.SendFlags |= TNSF_ANIM; + self.anim_start_time = time; + }*/ } void ewheel_move_idle() { + if(self.frame != 0) + { + self.SendFlags |= TNSF_ANIM; + self.anim_start_time = time; + } + self.frame = 0; if (vlen(self.velocity)) - movelib_beak_simple(ewheel_speed_stop); + movelib_beak_simple(autocvar_g_turrets_unit_ewheel_speed_stop); } void ewheel_postthink() { float vz; - vector wish_angle,real_angle; - - /* - if(self.enemy) - dprint("enemy!\n"); - else - dprint("nothign =(!\n"); - */ + vector wish_angle, real_angle; vz = self.velocity_z; self.angles_x = anglemods(self.angles_x); self.angles_y = anglemods(self.angles_y); - //self.angles_x *= -1; fixedmakevectors(self.angles); - //self.angles_x *= -1; wish_angle = normalize(self.steerto); wish_angle = vectoangles(wish_angle); real_angle = wish_angle - self.angles; - real_angle = shortangle_vxy(real_angle,self.tur_head.angles); + real_angle = shortangle_vxy(real_angle, self.tur_head.angles); self.tur_head.spawnshieldtime = fabs(real_angle_y); - real_angle_y = bound(-self.tur_head.aim_speed,real_angle_y,self.tur_head.aim_speed); + real_angle_y = bound(-self.tur_head.aim_speed, real_angle_y, self.tur_head.aim_speed); self.angles_y = (self.angles_y + real_angle_y); - // Simulate banking - self.angles_z -= self.angles_z * frametime * 2; - self.angles_z = bound(-45,self.angles_z + ((real_angle_y * -25) * frametime),45); - if(self.enemy) ewheel_move_enemy(); else if(self.pathcurrent) @@ -210,6 +161,9 @@ void ewheel_postthink() self.velocity_z = vz; + + if(vlen(self.velocity)) + self.SendFlags |= TNSF_MOVE; } void ewheel_respawnhook() @@ -217,7 +171,7 @@ void ewheel_respawnhook() entity e; // Respawn is called & first spawn to, to set team. need to make sure we do not move the initial spawn. - if(self.movetype != MOVETYPE_WALK) + if(self.movetype != MOVETYPE_WALK) return; self.velocity = '0 0 0'; @@ -238,8 +192,13 @@ void ewheel_respawnhook() dprint("Warning: not a turrret path\n"); else { + +#ifdef EWHEEL_FANCYPATH self.pathcurrent = WALKER_PATH(self.origin,e.origin); self.pathgoal = e; +#else + self.pathcurrent = e; +#endif } } } @@ -248,11 +207,10 @@ void ewheel_diehook() { self.velocity = '0 0 0'; - turret_trowgib2(self.origin, self.velocity + '0 0 400', '-0.6 -0.2 -02', self, 3 + time + random() * 2); - +#ifdef EWHEEL_FANCYPATH if (self.pathcurrent) pathlib_deletepath(self.pathcurrent.owner); - +#endif self.pathcurrent = world; } @@ -260,7 +218,8 @@ void turret_ewheel_dinit() { entity e; - if (self.netname == "") self.netname = "eWheel Turret"; + if (self.netname == "") + self.netname = "eWheel Turret"; if (self.target != "") { @@ -283,27 +242,24 @@ void turret_ewheel_dinit() self.turret_diehook = ewheel_diehook; - if (turret_stdproc_init("ewheel_std",0,"models/turrets/ewheel-base2.md3","models/turrets/ewheel-gun1.md3") == 0) + if (turret_stdproc_init("ewheel_std", "models/turrets/ewheel-base2.md3", "models/turrets/ewheel-gun1.md3", TID_EWHEEL) == 0) { remove(self); return; } - + + self.frame = 1; self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS; - self.target_select_flags = TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS; - self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;// | TFL_TARGETSELECT_LOS; - self.target_validate_flags = TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;// | TFL_TARGETSELECT_LOS; - self.damage_flags |= TFL_DMG_DEATH_NOGIBS; - + self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS; self.iscreature = TRUE; + self.damagedbycontents = TRUE; self.movetype = MOVETYPE_WALK; self.solid = SOLID_SLIDEBOX; self.takedamage = DAMAGE_AIM; + self.idle_aim = '0 0 0'; + self.pos1 = self.origin; setsize(self, '-32 -32 0', '32 32 48'); - self.idle_aim = '0 0 0'; - - self.pos1 = self.origin; // Our fire routine self.turret_firefunc = ewheel_attack; @@ -314,9 +270,6 @@ void turret_ewheel_dinit() self.tur_head.aim_speed = autocvar_g_turrets_unit_ewheel_turnrate; self.tur_head.aim_speed = self.tur_head.aim_speed / (1 / self.ticrate); - if (!turret_tag_fire_update()) - dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n"); - //setorigin(self,self.origin + '0 0 128'); if (self.target != "") { @@ -331,8 +284,12 @@ void turret_ewheel_dinit() dprint("Warning: not a turrret path\n"); else { +#ifdef EWHEEL_FANCYPATH self.pathcurrent = WALKER_PATH(self.origin, e.origin); self.pathgoal = e; +#else + self.pathcurrent = e; +#endif } } } @@ -344,12 +301,6 @@ void spawnfunc_turret_ewheel() precache_model ("models/turrets/ewheel-base2.md3"); precache_model ("models/turrets/ewheel-gun1.md3"); - precache_model ("models/pathlib/goodsquare.md3"); - precache_model ("models/pathlib/badsquare.md3"); - precache_model ("models/pathlib/square.md3"); - - turret_ewheel_loadcvars(); - self.think = turret_ewheel_dinit; self.nextthink = time + 0.5; } diff --git a/qcsrc/server/tturrets/units/unit_flac.qc b/qcsrc/server/tturrets/units/unit_flac.qc index 0c874fb504..975abbd4c9 100644 --- a/qcsrc/server/tturrets/units/unit_flac.qc +++ b/qcsrc/server/tturrets/units/unit_flac.qc @@ -1,95 +1,51 @@ void spawnfunc_turret_flac(); void turret_flac_dinit(); void turret_flac_attack(); -void turret_flac_projectile_explode(); -void turret_flac_attack() +void turret_flac_projectile_think_explode() { - local entity proj; - - turret_tag_fire_update(); - - sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", VOL_BASE, ATTN_NORM); - proj = spawn (); - setorigin(proj, self.tur_shotorg); - setsize(proj, '0 0 0', '0 0 0'); - proj.classname = "flac_projectile"; - proj.owner = self; - proj.bot_dodge = TRUE; - proj.bot_dodgerating = self.shot_dmg; - proj.solid = SOLID_BBOX; - proj.movetype = MOVETYPE_FLYMISSILE; - proj.flags = FL_PROJECTILE; - proj.takedamage = DAMAGE_NO; - proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed; - proj.angles = vectoangles(proj.velocity); - proj.touch = turret_flac_projectile_explode; - proj.think = turret_flac_projectile_explode; - proj.nextthink = time + max(self.tur_impacttime,(self.shot_radius * 3) / self.shot_speed); - proj.enemy = self.enemy; - proj.cnt = time + 5; - - CSQCProjectile(proj, TRUE, PROJECTILE_HAGAR, TRUE); - - self.tur_head.frame = self.tur_head.frame + 1; - if (self.tur_head.frame >= 4) self.tur_head.frame = 0; - -} - -void turret_flac_projectile_explode() -{ - float ftmp; - - // FIXME: tur_impacttime is not accurate enougth, this is a dirty hakk to make flac work. - - //w_deathtypestring = "got caught in the flack."; - - - - if( (self.enemy != world) && - (vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 3) ) - { - // OMG HAXX! + if(self.enemy != world) + if(vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 3) setorigin(self,self.enemy.origin + randomvec() * self.owner.shot_radius); - } - - - - te_explosion (self.origin); - - ftmp = crandom(); - if (ftmp<-0.7) - sound (self, CHAN_PROJECTILE, "weapons/hagexp1.wav", VOL_BASE, ATTN_NORM); - else if (ftmp<0.4) - sound (self, CHAN_PROJECTILE, "weapons/hagexp2.wav", VOL_BASE, ATTN_NORM); - else if (ftmp<1) - sound (self, CHAN_PROJECTILE, "weapons/hagexp3.wav", VOL_BASE, ATTN_NORM); - - - self.event_damage = SUB_Null; - - + #ifdef TURRET_DEBUG - ftmp = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world); - self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + ftmp; //self.owner.shot_dmg; + float d; + d = RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world); + self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg; #else - RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg * 0.5, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world); + RadiusDamage (self, self.realowner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world); #endif - - remove (self); + remove(self); } +void turret_flac_attack() +{ + entity proj; + + turret_tag_fire_update(); + + proj = turret_projectile("weapons/hagar_fire.wav", 5, 0, DEATH_TURRET_FLAC, PROJECTILE_HAGAR, TRUE, TRUE); + pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1); + proj.think = turret_flac_projectile_think_explode; + proj.nextthink = time + self.tur_impacttime + (random() * 0.01 - random() * 0.01); + + self.tur_head.frame = self.tur_head.frame + 1; + if (self.tur_head.frame >= 4) + self.tur_head.frame = 0; + +} void turret_flac_dinit() { - if (self.netname == "") self.netname = "FLAC Cannon"; + if (self.netname == "") + self.netname = "FLAC Cannon"; self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_FASTPROJ | TFL_TURRCAPS_MISSILEKILL; self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE; self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE; - - if (turret_stdproc_init("flac_std",0,"models/turrets/base.md3","models/turrets/flac.md3") == 0) + + if (turret_stdproc_init("flac_std", "models/turrets/base.md3", "models/turrets/flac.md3", TID_FLAC) == 0) { remove(self); return; @@ -98,10 +54,7 @@ void turret_flac_dinit() self.damage_flags |= TFL_DMG_HEADSHAKE; self.target_select_flags |= TFL_TARGETSELECT_NOTURRETS | TFL_TARGETSELECT_MISSILESONLY; - - if (!turret_tag_fire_update()) - dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n"); - + // Our fire routine self.turret_firefunc = turret_flac_attack; diff --git a/qcsrc/server/tturrets/units/unit_fusionreactor.qc b/qcsrc/server/tturrets/units/unit_fusionreactor.qc index 601a934c5b..8118b8f234 100644 --- a/qcsrc/server/tturrets/units/unit_fusionreactor.qc +++ b/qcsrc/server/tturrets/units/unit_fusionreactor.qc @@ -2,19 +2,6 @@ void spawnfunc_turret_fusionreactor(); void turret_fusionreactor_dinit(); void turret_fusionreactor_fire(); -float turret_fusionreactor_firecheck() -{ - if (self.enemy == world) return 0; - if not (self.enemy.ammo_flags & TFL_AMMO_RECIVE) return 0; - if not (self.enemy.ammo_flags & TFL_AMMO_ENERGY) return 0; - if (self.ammo < self.shot_dmg) return 0; - if (self.enemy.ammo >= self.enemy.ammo_max) return 0; - if (self.tur_dist_aimpos > self.target_range) return 0; - if (self.tur_dist_aimpos < self.target_range_min) return 0; - - return 1; -} - void turret_fusionreactor_fire() { vector fl_org; @@ -22,20 +9,51 @@ void turret_fusionreactor_fire() self.enemy.ammo = min(self.enemy.ammo + self.shot_dmg,self.enemy.ammo_max); fl_org = 0.5 * (self.enemy.absmin + self.enemy.absmax); te_smallflash(fl_org); - //te_lightning1(world,self.origin,self.enemy.origin); } void turret_fusionreactor_postthink() { - float f; - f = self.ammo / self.ammo_max; - self.tur_head.avelocity = '0 250 0' * f; + self.tur_head.avelocity = '0 250 0' * (self.ammo / self.ammo_max); } +/* void turret_fusionreactor_respawnhook() { self.tur_head.avelocity = '0 50 0'; } +*/ + +/** +** Preforms pre-fire checks for fusionreactor +**/ +float turret_fusionreactor_firecheck() +{ + if (self.attack_finished_single > time) + return 0; + + if (self.enemy.deadflag != DEAD_NO) + return 0; + + if (self.enemy == world) + return 0; + + if (self.ammo < self.shot_dmg) + return 0; + + if (self.enemy.ammo >= self.enemy.ammo_max) + return 0; + + if (vlen(self.enemy.origin - self.origin) > self.target_range) + return 0; + + if(self.team != self.enemy.team) + return 0; + + if not (self.enemy.ammo_flags & TFL_AMMO_ENERGY) + return 0; + + return 1; +} void turret_fusionreactor_dinit() { @@ -44,13 +62,13 @@ void turret_fusionreactor_dinit() self.turrcaps_flags = TFL_TURRCAPS_SUPPORT | TFL_TURRCAPS_AMMOSOURCE; self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE; self.target_select_flags = TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_OWNTEAM | TFL_TARGETSELECT_RANGELIMTS; - self.firecheck_flags = TFL_FIRECHECK_OWM_AMMO | TFL_FIRECHECK_OTHER_AMMO | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_DEAD | TFL_FIRECHECK_WORLD; + self.firecheck_flags = TFL_FIRECHECK_OWM_AMMO | TFL_FIRECHECK_OTHER_AMMO | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_DEAD; self.shoot_flags = TFL_SHOOT_HITALLVALID; self.aim_flags = TFL_AIM_NO; self.track_flags = TFL_TRACK_NO; - self.turret_respawnhook = turret_fusionreactor_respawnhook; + // self.turret_respawnhook = turret_fusionreactor_respawnhook; - if (turret_stdproc_init("fusreac_std",0,"models/turrets/base.md3","models/turrets/reactor.md3") == 0) + if (turret_stdproc_init("fusreac_std", "models/turrets/base.md3", "models/turrets/reactor.md3", TID_FUSION) == 0) { remove(self); return; diff --git a/qcsrc/server/tturrets/units/unit_hellion.qc b/qcsrc/server/tturrets/units/unit_hellion.qc index 1e2890f6ea..08bfad2a61 100644 --- a/qcsrc/server/tturrets/units/unit_hellion.qc +++ b/qcsrc/server/tturrets/units/unit_hellion.qc @@ -1,75 +1,6 @@ -.float shot_speed_max; -.float shot_speed_gain; - void spawnfunc_turret_hellion(); void turret_hellion_dinit(); void turret_hellion_attack(); -void turret_hellion_missile_explode(); -void turret_hellion_missile_think(); -void turret_hellion_missile_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce) - -void turret_hellion_postthink() -{ - if (autocvar_g_turrets_reloadcvars) - { - if (!self.shot_speed_max) self.shot_speed_max = autocvar_g_turrets_unit_hellion_std_shot_speed_max; - if (!self.shot_speed_gain) self.shot_speed_gain = autocvar_g_turrets_unit_hellion_std_shot_speed_gain; - } - - if (self.tur_head.frame != 0) - self.tur_head.frame += 1; - - if (self.tur_head.frame >= 7) - self.tur_head.frame = 0; -} - -void turret_hellion_attack() -{ - entity missile; - - if(self.tur_head.frame != 0) - self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire")); - else - self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire2")); - - sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", VOL_BASE, ATTN_NORM); - - missile = spawn (); - setorigin(missile, self.tur_shotorg); - setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot - - missile.classname = "hellion_missile"; - missile.owner = self; - missile.bot_dodge = TRUE; - missile.bot_dodgerating = self.shot_dmg; - missile.takedamage = DAMAGE_YES; - missile.event_damage = turret_hellion_missile_damage; - missile.damageforcescale = 2; - missile.health = 10; - missile.enemy = self.enemy; - missile.think = turret_hellion_missile_think; - missile.nextthink = time;// + 0.2; - missile.solid = SOLID_BBOX; - missile.movetype = MOVETYPE_FLY; - missile.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed; - missile.angles = vectoangles(missile.velocity); - missile.touch = turret_hellion_missile_explode; - missile.flags = FL_PROJECTILE; - missile.solid = SOLID_BBOX; - missile.tur_health = time + 9; - missile.tur_aimpos = randomvec() * 128; - te_explosion (missile.origin); - CSQCProjectile(missile, FALSE, PROJECTILE_ROCKET, FALSE); // no culling, has fly sound - - self.tur_head.frame += 1; -} - -void turret_hellion_missile_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce) -{ - self.health = self.health - damage; - self.velocity = self.velocity + vforce; - if (self.health <= 0) turret_hellion_missile_explode(); -} void turret_hellion_missile_think() { @@ -82,7 +13,7 @@ void turret_hellion_missile_think() olddir = normalize(self.velocity); if(self.tur_health < time) - turret_hellion_missile_explode(); + turret_projectile_explode(); // Enemy dead? just keep on the current heading then. if ((self.enemy == world) || (self.enemy.deadflag != DEAD_NO)) @@ -95,10 +26,10 @@ void turret_hellion_missile_think() self.angles = vectoangles(self.velocity); if ( (vlen(self.origin - self.owner.origin)) > (self.owner.shot_radius * 5) ) - turret_hellion_missile_explode(); + turret_projectile_explode(); // Accelerate - self.velocity = olddir * min(vlen(self.velocity) * self.owner.shot_speed_gain,self.owner.shot_speed_max); + self.velocity = olddir * min(vlen(self.velocity) * autocvar_g_turrets_unit_hellion_std_shot_speed_gain, autocvar_g_turrets_unit_hellion_std_shot_speed_max); UpdateCSQCProjectile(self); @@ -107,7 +38,7 @@ void turret_hellion_missile_think() // Enemy in range? if (vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 0.2) - turret_hellion_missile_explode(); + turret_projectile_explode(); // Predict enemy position itime = vlen(self.enemy.origin - self.origin) / vlen(self.velocity); @@ -125,78 +56,57 @@ void turret_hellion_missile_think() self.angles = vectoangles(self.velocity); // Accelerate - self.velocity = newdir * min(vlen(self.velocity) * self.owner.shot_speed_gain,self.owner.shot_speed_max); + self.velocity = newdir * min(vlen(self.velocity) * autocvar_g_turrets_unit_hellion_std_shot_speed_gain, autocvar_g_turrets_unit_hellion_std_shot_speed_max); if (itime < 0.05) - self.think = turret_hellion_missile_explode; + self.think = turret_projectile_explode; UpdateCSQCProjectile(self); } - -void turret_hellion_missile_explode() +void turret_hellion_attack() { - vector org2; - float d; - - if(self.event_damage != SUB_Null) - { - self.event_damage = SUB_Null; - self.think = turret_hellion_missile_explode; - self.nextthink = time; - return; - } - - sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); - org2 = findbetterlocation (self.origin, 16); - - // LordHavoc: TE_TEI_BIGEXPLOSION - WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); - WriteByte (MSG_BROADCAST, 78); - WriteCoord (MSG_BROADCAST, org2_x); - WriteCoord (MSG_BROADCAST, org2_y); - WriteCoord (MSG_BROADCAST, org2_z); - - //w_deathtypestring = "could not dodge the twin missiles."; - self.event_damage = SUB_Null; - d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world); - -#ifdef TURRET_DEBUG - self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; //self.owner.shot_dmg; - self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg; -#endif + entity missile; + + if(self.tur_head.frame != 0) + self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire")); + else + self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire2")); + + missile = turret_projectile("weapons/rocket_fire.wav", 6, 10, DEATH_TURRET_HELLION, PROJECTILE_ROCKET, FALSE, FALSE); + te_explosion (missile.origin); + missile.think = turret_hellion_missile_think; + missile.nextthink = time; + missile.flags = FL_PROJECTILE; + missile.tur_health = time + 9; + missile.tur_aimpos = randomvec() * 128; + self.tur_head.frame += 1; +} - // Target dead, get another is still targeting the same. - if ((self.enemy.deadflag != DEAD_NO) && (self.enemy == self.owner.enemy)) - self.owner.enemy = world; +void turret_hellion_postthink() +{ + if (self.tur_head.frame != 0) + self.tur_head.frame += 1; - remove (self); + if (self.tur_head.frame >= 7) + self.tur_head.frame = 0; } void turret_hellion_dinit() { if (self.netname == "") self.netname = "Hellion Missile Turret"; - if not (self.shot_speed_max) - self.shot_speed_max = autocvar_g_turrets_unit_hellion_std_shot_speed_max; - - if not (self.shot_speed_gain) - self.shot_speed_gain = autocvar_g_turrets_unit_hellion_std_shot_speed_gain; - self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_FASTPROJ | TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MISSILEKILL; self.aim_flags = TFL_AIM_SIMPLE; self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK ; - self.firecheck_flags = TFL_FIRECHECK_WORLD | TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_TEAMCECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF | TFL_FIRECHECK_OWM_AMMO; + self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_TEAMCECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF | TFL_FIRECHECK_OWM_AMMO; self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE; - if (turret_stdproc_init("hellion_std",0,"models/turrets/base.md3","models/turrets/hellion.md3") == 0) + if (turret_stdproc_init("hellion_std", "models/turrets/base.md3", "models/turrets/hellion.md3", TID_HELLION) == 0) { remove(self); return; } - if (!turret_tag_fire_update()) - dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n"); - self.turret_firefunc = turret_hellion_attack; self.turret_postthink = turret_hellion_postthink; } diff --git a/qcsrc/server/tturrets/units/unit_hk.qc b/qcsrc/server/tturrets/units/unit_hk.qc index 2b8e0f6a38..d61289dcbe 100644 --- a/qcsrc/server/tturrets/units/unit_hk.qc +++ b/qcsrc/server/tturrets/units/unit_hk.qc @@ -7,31 +7,7 @@ void spawnfunc_turret_hk(); void turret_hk_dinit(); void turret_hk_attack(); -void turret_hk_missile_explode(); -void turret_hk_missile_think(); -void turret_hk_missile_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force); -float turret_hk_addtarget(entity e_target,entity e_sender); -//void turret_hk_missile_touch(); - -float hk_maxspeed; -float hk_minspeed; -float hk_accel; -float hk_accel2; -float hk_decel; -float turret_hk_addtarget(entity e_target,entity e_sender) -{ - if (e_target) - { - if (turret_validate_target(self,e_target,self.target_validate_flags) > 0) - { - self.enemy = e_target; - return 1; - } - } - - return 0; -} float hk_is_valid_target(entity e_target) { @@ -66,62 +42,6 @@ float hk_is_valid_target(entity e_target) return 1; } - -void turret_hk_missile_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) -{ - if (attacker.team == self.team) - damage *= 0.5; - - self.velocity += force; - - self.health -= damage; - - if (self.health <= 0) - turret_hk_missile_explode(); -} - -void turret_hk_attack() -{ - local entity missile; - //local entity flash2; - - sound (self, CHAN_WEAPON, "weapons/rocket_fire.wav", VOL_BASE, ATTN_NORM); - - missile = spawn (); - missile.solid = SOLID_BBOX; - setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot - setorigin(missile, self.tur_shotorg); - - missile.scale = 1; - missile.classname = "hk_missile"; - missile.owner = self; - missile.bot_dodge = TRUE; - missile.bot_dodgerating = self.shot_dmg; - missile.takedamage = DAMAGE_YES; - missile.damageforcescale = 4; - missile.health = 10; - missile.think = turret_hk_missile_think; - missile.event_damage = turret_hk_missile_damage; - missile.nextthink = time + 0.25; - missile.movetype = MOVETYPE_BOUNCEMISSILE; - missile.velocity = self.tur_shotdir_updated * (self.shot_speed * 0.75); - missile.angles = vectoangles(missile.velocity); - missile.touch = turret_hk_missile_explode; //turret_hk_missile_touch; - missile.flags = FL_PROJECTILE; - missile.enemy = self.enemy; - missile.team = self.team; - missile.cnt = time + 30; - missile.ticrate = max(autocvar_sys_ticrate,0.05); - - CSQCProjectile(missile, FALSE, PROJECTILE_ROCKET, FALSE); // no culling, fly sound - - te_explosion (missile.origin); - - if (self.tur_head.frame == 0) - self.tur_head.frame = self.tur_head.frame + 1; - -} - void turret_hk_missile_think() { vector vu, vd, vf, vl, vr, ve; // Vector (direction) @@ -172,7 +92,7 @@ void turret_hk_missile_think() // Close enougth to do decent damage? if ( edist <= (self.owner.shot_radius * 0.25) ) { - turret_hk_missile_explode(); + turret_projectile_explode(); return; } @@ -207,12 +127,12 @@ void turret_hk_missile_think() ad = vlen(vectoangles(normalize(self.enemy.origin - self.origin)) - self.angles); // To close to something, Slow down! - if ( ((ff < 0.7) || (ad > 4)) && (myspeed > hk_minspeed) ) - myspeed = max(myspeed * hk_decel,hk_minspeed); + if ( ((ff < 0.7) || (ad > 4)) && (myspeed > autocvar_g_turrets_unit_hk_std_shot_speed) ) + myspeed = max(myspeed * autocvar_g_turrets_unit_hk_std_shot_speed_decel, autocvar_g_turrets_unit_hk_std_shot_speed); // Failry clear, accelerate. - if ( (ff > 0.7) && (myspeed < hk_maxspeed) ) - myspeed = min(myspeed * hk_accel,hk_maxspeed); + if ( (ff > 0.7) && (myspeed < autocvar_g_turrets_unit_hk_std_shot_speed_max) ) + myspeed = min(myspeed * autocvar_g_turrets_unit_hk_std_shot_speed_accel, autocvar_g_turrets_unit_hk_std_shot_speed_max); // Setup trace pitch pt_seek = 1 - ff; @@ -268,14 +188,14 @@ void turret_hk_missile_think() { // Got a clear path to target, speed up fast (if not at full speed) and go straight for it. myspeed = vlen(self.velocity); - if (myspeed < hk_maxspeed) - myspeed = min(myspeed * hk_accel2,hk_maxspeed); + if (myspeed < autocvar_g_turrets_unit_hk_std_shot_speed_max) + myspeed = min(myspeed * autocvar_g_turrets_unit_hk_std_shot_speed_accel2,autocvar_g_turrets_unit_hk_std_shot_speed_max); wishdir = ve; } - if ((myspeed > hk_minspeed) && (self.cnt > time)) - myspeed = min(myspeed * hk_accel2,hk_maxspeed); + if ((myspeed > autocvar_g_turrets_unit_hk_std_shot_speed) && (self.cnt > time)) + myspeed = min(myspeed * autocvar_g_turrets_unit_hk_std_shot_speed_accel2,autocvar_g_turrets_unit_hk_std_shot_speed_max); // Ranoutagazfish? if (self.cnt < time) @@ -283,7 +203,6 @@ void turret_hk_missile_think() self.cnt = time + 0.25; self.nextthink = 0; self.movetype = MOVETYPE_BOUNCE; - sound (self, CHAN_VOICE, "", 0.4 * VOL_BASE, ATTN_NORM); return; } @@ -322,93 +241,62 @@ void turret_hk_missile_think() UpdateCSQCProjectile(self); } -void turret_hk_missile_explode() +void turret_hk_attack() { - vector org2; - float d; - - if(self.event_damage != SUB_Null) - { - self.event_damage = SUB_Null; - self.think = turret_hk_missile_explode; - self.nextthink = time; - return; - } - - if ((other == self.owner)||(other == self.owner.tur_head)) - return; + entity missile; - //w_deathtypestring = "got hunted to extinction"; - //vector org2; - sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); - org2 = findbetterlocation (self.origin, 16); - - // LordHavoc: TE_TEI_BIGEXPLOSION - WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); - WriteByte (MSG_BROADCAST, 78); - WriteCoord (MSG_BROADCAST, org2_x); - WriteCoord (MSG_BROADCAST, org2_y); - WriteCoord (MSG_BROADCAST, org2_z); - - self.event_damage = SUB_Null; - d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world); + missile = turret_projectile("weapons/rocket_fire.wav", 6, 10, DEATH_TURRET_HK, PROJECTILE_ROCKET, FALSE, FALSE); + te_explosion (missile.origin); -#ifdef TURRET_DEBUG - self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; //self.owner.shot_dmg; - self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg; -#endif + missile.think = turret_hk_missile_think; + missile.nextthink = time + 0.25; + missile.movetype = MOVETYPE_BOUNCEMISSILE; + missile.velocity = self.tur_shotdir_updated * (self.shot_speed * 0.75); + missile.angles = vectoangles(missile.velocity); + missile.cnt = time + 30; + missile.ticrate = max(autocvar_sys_ticrate, 0.05); - // Target dead, get another is still targeting the same. - if ((self.enemy.deadflag != DEAD_NO) && (self.enemy == self.owner.enemy)) - self.owner.enemy = world; + if (self.tur_head.frame == 0) + self.tur_head.frame = self.tur_head.frame + 1; - remove (self); } void turret_hk_postthink() { - if (autocvar_g_turrets_reloadcvars) - { - hk_maxspeed = autocvar_g_turrets_unit_hk_std_shot_speed_max; - hk_minspeed = autocvar_g_turrets_unit_hk_std_shot_speed; - hk_accel = autocvar_g_turrets_unit_hk_std_shot_speed_accel; - hk_accel2 = autocvar_g_turrets_unit_hk_std_shot_speed_accel2; - hk_decel = autocvar_g_turrets_unit_hk_std_shot_speed_decel; - } - if (self.tur_head.frame != 0) self.tur_head.frame = self.tur_head.frame + 1; if (self.tur_head.frame > 5) self.tur_head.frame = 0; +} +float turret_hk_addtarget(entity e_target,entity e_sender) +{ + if (e_target) + { + if (turret_validate_target(self,e_target,self.target_validate_flags) > 0) + { + self.enemy = e_target; + return 1; + } + } + + return 0; } void turret_hk_dinit() { - if (self.netname == "") self.netname = "Hunter-killer turret"; - - hk_maxspeed = autocvar_g_turrets_unit_hk_std_shot_speed_max; - hk_minspeed = autocvar_g_turrets_unit_hk_std_shot_speed; - hk_accel = autocvar_g_turrets_unit_hk_std_shot_speed_accel; - hk_accel2 = autocvar_g_turrets_unit_hk_std_shot_speed_accel2; - hk_decel = autocvar_g_turrets_unit_hk_std_shot_speed_decel; + if (self.netname == "") + self.netname = "Hunter-killer turret"; self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_RECIVETARGETS; - self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE; - self.aim_flags = TFL_AIM_SIMPLE; - - self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TRIGGERTARGET | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK; - - self.firecheck_flags = TFL_FIRECHECK_WORLD | TFL_FIRECHECK_DEAD | TFL_FIRECHECK_TEAMCECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF; - self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TRIGGERTARGET | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK; - + self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_TEAMCECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF; self.shoot_flags = TFL_SHOOT_CLEARTARGET; - if (turret_stdproc_init("hk_std",0,"models/turrets/base.md3","models/turrets/hk.md3") == 0) + if (turret_stdproc_init("hk_std", "models/turrets/base.md3", "models/turrets/hk.md3", TID_HK) == 0) { remove(self); return; @@ -416,10 +304,6 @@ void turret_hk_dinit() self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TEAMCHECK; - - if (!turret_tag_fire_update()) - dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n"); - // Our fire routine self.turret_firefunc = turret_hk_attack; diff --git a/qcsrc/server/tturrets/units/unit_machinegun.qc b/qcsrc/server/tturrets/units/unit_machinegun.qc index f6426fce25..f96d3b93cc 100644 --- a/qcsrc/server/tturrets/units/unit_machinegun.qc +++ b/qcsrc/server/tturrets/units/unit_machinegun.qc @@ -5,13 +5,9 @@ void turret_machinegun_attack(); //.float bulletcounter; void turret_machinegun_attack() { - sound (self, CHAN_WEAPON, "weapons/uzi_fire.wav", VOL_BASE, ATTN_NORM); - fireBallisticBullet (self.tur_shotorg, self.tur_shotdir_updated,self.shot_spread, self.shot_speed, 5, self.shot_dmg, 0, self.shot_force, DEATH_TURRET, 0, 1, autocvar_g_balance_uzi_bulletconstant); + fireBallisticBullet (self.tur_shotorg, self.tur_shotdir_updated,self.shot_spread, self.shot_speed, 5, self.shot_dmg, 0, self.shot_force, DEATH_TURRET_MACHINEGUN, 0, 1, autocvar_g_balance_uzi_bulletconstant); endFireBallisticBullet(); - //w_deathtypestring = "had an alergic reaction due to 10 kilos of led"; - te_smallflash(self.tur_shotorg); - UziFlash(); setattachment(self.muzzle_flash, self.tur_head, "tag_fire"); } @@ -28,7 +24,7 @@ void turret_machinegun_std_init() if not (autocvar_g_antilag_bullets) self.turrcaps_flags |= TFL_TURRCAPS_HITSCAN; - if (turret_stdproc_init("machinegun_std",0,"models/turrets/base.md3","models/turrets/machinegun.md3") == 0) + if (turret_stdproc_init("machinegun_std", "models/turrets/base.md3", "models/turrets/machinegun.md3", TID_MACHINEGUN) == 0) { remove(self); return; @@ -36,9 +32,6 @@ void turret_machinegun_std_init() self.damage_flags |= TFL_DMG_HEADSHAKE; - if (!turret_tag_fire_update()) - dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n"); - // Our fire routine self.turret_firefunc = turret_machinegun_attack; diff --git a/qcsrc/server/tturrets/units/unit_mlrs.qc b/qcsrc/server/tturrets/units/unit_mlrs.qc index 499d6de235..65c0ed0585 100644 --- a/qcsrc/server/tturrets/units/unit_mlrs.qc +++ b/qcsrc/server/tturrets/units/unit_mlrs.qc @@ -1,8 +1,6 @@ void spawnfunc_turret_mlrs(); void turret_mlrs_dinit(); void turret_mlrs_attack(); -void turret_mlrs_rocket_explode(); -void turret_mlrs_rocket_touch(); void turret_mlrs_postthink() { @@ -13,84 +11,16 @@ void turret_mlrs_postthink() dprint("ammo:",ftos(self.ammo),"\n"); dprint("shot_dmg:",ftos(self.shot_dmg),"\n"); } - } void turret_mlrs_attack() { entity missile; - - turret_tag_fire_update(); - - sound (self, CHAN_WEAPON, "weapons/rocket_fire.wav", VOL_BASE, ATTN_NORM); - - missile = spawn (); - setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot - setorigin(missile, self.tur_shotorg); - missile.classname = "mlrs_missile"; - missile.owner = self; - missile.bot_dodge = TRUE; - missile.bot_dodgerating = self.shot_dmg; - missile.takedamage = DAMAGE_NO; - missile.damageforcescale = 4; - missile.think = turret_mlrs_rocket_explode; - missile.nextthink = time + max(self.tur_impacttime,(self.shot_radius * 2) / self.shot_speed); - missile.solid = SOLID_BBOX; - missile.movetype = MOVETYPE_FLYMISSILE; - missile.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed; - missile.angles = vectoangles(missile.velocity); - missile.touch = turret_mlrs_rocket_touch; - missile.flags = FL_PROJECTILE; - missile.solid = SOLID_BBOX; - missile.enemy = self.enemy; - - CSQCProjectile(missile, TRUE, PROJECTILE_ROCKET, FALSE); // no cull, fly sound - - te_explosion (missile.origin); -} - -void turret_mlrs_rocket_touch() -{ - if( (other == self.owner) || (other == self.owner.tur_head) ) - return; - - PROJECTILE_TOUCH; - - turret_mlrs_rocket_explode(); -} - -void turret_mlrs_rocket_explode() -{ - vector org2; - - if(self.event_damage != SUB_Null) - { - self.event_damage = SUB_Null; - self.think = turret_mlrs_rocket_explode; - self.nextthink = time; - return; - } - - - sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); - org2 = findbetterlocation (self.origin, 16); - pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1); - //w_deathtypestring = "dident escape the rocket barrage"; -#ifdef TURRET_DEBUG - float d; - - d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world); - self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; //self.owner.shot_dmg; - self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg; -#else - RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg * 0.5, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world); -#endif - - // Target dead, Tell turret. - if ((self.enemy.deadflag != DEAD_NO) && (self.enemy == self.owner.enemy)) - self.owner.enemy = world; - - remove (self); + + turret_tag_fire_update(); + missile = turret_projectile("weapons/rocket_fire.wav", 6, 10, DEATH_TURRET_MLRS, PROJECTILE_ROCKET, TRUE, TRUE); + missile.nextthink = time + max(self.tur_impacttime,(self.shot_radius * 2) / self.shot_speed); + te_explosion (missile.origin); } void turret_mlrs_dinit() @@ -99,9 +29,9 @@ void turret_mlrs_dinit() self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL; self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE; - self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;// | TFL_AIM_GROUND2; + self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE; - if (turret_stdproc_init("mlrs_std",0,"models/turrets/base.md3","models/turrets/mlrs.md3") == 0) + if (turret_stdproc_init("mlrs_std", "models/turrets/base.md3", "models/turrets/mlrs.md3", TID_MLRS) == 0) { remove(self); return; @@ -111,9 +41,6 @@ void turret_mlrs_dinit() self.shoot_flags |= TFL_SHOOT_VOLLYALWAYS; self.volly_counter = self.shot_volly; - if (!turret_tag_fire_update()) - dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n"); - // Our fire routine self.turret_firefunc = turret_mlrs_attack; self.turret_postthink = turret_mlrs_postthink; diff --git a/qcsrc/server/tturrets/units/unit_phaser.qc b/qcsrc/server/tturrets/units/unit_phaser.qc index 9c5ca071d8..91794929b6 100644 --- a/qcsrc/server/tturrets/units/unit_phaser.qc +++ b/qcsrc/server/tturrets/units/unit_phaser.qc @@ -40,7 +40,7 @@ void beam_think() self.owner.attack_finished_single = time + self.owner.shot_refire; self.owner.fireflag = 2; self.owner.tur_head.frame = 10; - sound (self, CHAN_PROJECTILE, "", VOL_BASE, ATTN_NORM); + sound (self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTN_NORM); remove(self); return; } @@ -50,7 +50,7 @@ void beam_think() if (time - self.shot_spread > 0) { self.shot_spread = time + 2; - sound (self, CHAN_VOICE, "turrets/phaser.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_SHOTS_SINGLE, "turrets/phaser.wav", VOL_BASE, ATTN_NORM); } @@ -68,7 +68,7 @@ void beam_think() self.shot_force, oldself.shot_dmg, 0.75, - DEATH_TURRET); + DEATH_TURRET_PHASER); self = oldself; self.scale = vlen(self.owner.tur_shotorg - trace_endpos) / 256; @@ -94,7 +94,7 @@ void turret_phaser_attack() beam.enemy = self.enemy; beam.bot_dodge = TRUE; beam.bot_dodgerating = beam.shot_dmg; - sound (beam, CHAN_PROJECTILE, "turrets/phaser.wav", VOL_BASE, ATTN_NORM); + sound (beam, CH_SHOTS_SINGLE, "turrets/phaser.wav", VOL_BASE, ATTN_NORM); self.fireflag = 1; beam.attack_finished_single = self.attack_finished_single; @@ -102,7 +102,7 @@ void turret_phaser_attack() setattachment(beam,self.tur_head,"tag_fire"); - soundat (self, trace_endpos, CHAN_PROJECTILE, "weapons/neximpact.wav", VOL_BASE, ATTN_NORM); + soundat (self, trace_endpos, CH_SHOTS, "weapons/neximpact.wav", VOL_BASE, ATTN_NORM); if (self.tur_head.frame == 0) self.tur_head.frame = 1; @@ -116,15 +116,12 @@ void turret_phaser_dinit() self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE; self.aim_flags = TFL_AIM_LEAD; - if (turret_stdproc_init("phaser_std",0,"models/turrets/base.md3","models/turrets/phaser.md3") == 0) + if (turret_stdproc_init("phaser_std", "models/turrets/base.md3","models/turrets/phaser.md3", TID_PHASER) == 0) { remove(self); return; } - if (!turret_tag_fire_update()) - dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n"); - self.turret_firecheckfunc = turret_phaser_firecheck; self.turret_firefunc = turret_phaser_attack; self.turret_postthink = turret_phaser_postthink; diff --git a/qcsrc/server/tturrets/units/unit_plasma.qc b/qcsrc/server/tturrets/units/unit_plasma.qc index 63466084a5..d5abf654be 100644 --- a/qcsrc/server/tturrets/units/unit_plasma.qc +++ b/qcsrc/server/tturrets/units/unit_plasma.qc @@ -5,7 +5,7 @@ void turret_plasma_std_init(); void turret_plasma_dual_init(); void turret_plasma_attack(); -void turret_plasma_projectile_explode(); + void turret_plasma_postthink() { @@ -26,91 +26,18 @@ void turret_plasma_dual_postthink() } void turret_plasma_attack() -{ - entity proj; - - sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", VOL_BASE, ATTN_NORM); +{ + turret_projectile("weapons/hagar_fire.wav", 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, TRUE, TRUE); pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1); - - proj = spawn (); - setorigin(proj, self.tur_shotorg); - setsize(proj, '-1 -1 -1', '1 1 1'); - proj.classname = "plasmabomb"; - proj.owner = self; - proj.bot_dodge = TRUE; - proj.bot_dodgerating = self.shot_dmg; - proj.think = turret_plasma_projectile_explode; - proj.nextthink = time + 9; - proj.solid = SOLID_BBOX; - proj.movetype = MOVETYPE_FLYMISSILE; - proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed; - proj.touch = turret_plasma_projectile_explode; - proj.flags = FL_PROJECTILE; - proj.enemy = self.enemy; - proj.flags = FL_PROJECTILE | FL_NOTARGET; - - CSQCProjectile(proj, TRUE, PROJECTILE_ELECTRO_BEAM, TRUE); - if (self.tur_head.frame == 0) self.tur_head.frame = 1; } void turret_plasma_dual_attack() { - entity proj; - - sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", VOL_BASE, ATTN_NORM); - proj = spawn (); - setorigin(proj, self.tur_shotorg); - setsize(proj, '0 0 0', '0 0 0'); - proj.classname = "plasmabomb"; - proj.owner = self; - proj.bot_dodge = TRUE; - proj.bot_dodgerating = self.shot_dmg; - proj.think = turret_plasma_projectile_explode; - proj.nextthink = time + 9; - proj.solid = SOLID_BBOX; - proj.movetype = MOVETYPE_FLYMISSILE; - proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed; - proj.touch = turret_plasma_projectile_explode; - proj.flags = FL_PROJECTILE; - proj.enemy = self.enemy; - proj.flags = FL_PROJECTILE | FL_NOTARGET; - + turret_projectile("weapons/hagar_fire.wav", 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, TRUE, TRUE); + pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1); self.tur_head.frame += 1; - - CSQCProjectile(proj, TRUE, PROJECTILE_ELECTRO_BEAM, TRUE); -} - -void turret_plasma_projectile_explode() -{ - vector org2; - - org2 = findbetterlocation (self.origin, 8); - WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); - WriteByte (MSG_BROADCAST, 79); - WriteCoord (MSG_BROADCAST, org2_x); - WriteCoord (MSG_BROADCAST, org2_y); - WriteCoord (MSG_BROADCAST, org2_z); - WriteCoord (MSG_BROADCAST, 0); // SeienAbunae: groan... Useless clutter - WriteCoord (MSG_BROADCAST, 0); - WriteCoord (MSG_BROADCAST, 0); - WriteByte (MSG_BROADCAST, 155); - - self.event_damage = SUB_Null; - //w_deathtypestring = "ate to much plasma"; -#ifdef TURRET_DEBUG - float d; - - d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world); - self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; //self.owner.shot_dmg; - self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg; -#else - RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world); -#endif - sound (self, CHAN_PROJECTILE, "weapons/electro_impact.wav", VOL_BASE, ATTN_NORM); - - remove (self); } void turret_plasma_std_init() @@ -121,10 +48,10 @@ void turret_plasma_std_init() self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE; // How to aim - self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_GROUND2; - self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MISSILEKILL; + self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_GROUNDGROUND; + self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL; - if (turret_stdproc_init("plasma_std",FALSE,"models/turrets/base.md3","models/turrets/plasma.md3") == 0) + if (turret_stdproc_init("plasma_std", "models/turrets/base.md3", "models/turrets/plasma.md3", TID_PLASMA) == 0) { remove(self); return; @@ -133,9 +60,6 @@ void turret_plasma_std_init() self.damage_flags |= TFL_DMG_HEADSHAKE; self.firecheck_flags |= TFL_FIRECHECK_AFF; - if (!turret_tag_fire_update()) - dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n"); - // Our fireing routine self.turret_firefunc = turret_plasma_attack; @@ -153,10 +77,10 @@ void turret_plasma_dual_init() self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE; // How to aim at targets - self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_GROUND2 ; + self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_GROUNDGROUND ; self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL; - if (turret_stdproc_init("plasma_dual",0,"models/turrets/base.md3","models/turrets/plasmad.md3") == 0) + if (turret_stdproc_init("plasma_dual", "models/turrets/base.md3", "models/turrets/plasmad.md3", TID_PLASMA_DUAL) == 0) { remove(self); return; @@ -165,9 +89,6 @@ void turret_plasma_dual_init() self.damage_flags |= TFL_DMG_HEADSHAKE; self.firecheck_flags |= TFL_FIRECHECK_AFF; - if (!turret_tag_fire_update()) - dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n"); - // Our fireing routine self.turret_firefunc = turret_plasma_dual_attack; diff --git a/qcsrc/server/tturrets/units/unit_tessla.qc b/qcsrc/server/tturrets/units/unit_tessla.qc index 443cd8b562..6c2cce6a73 100644 --- a/qcsrc/server/tturrets/units/unit_tessla.qc +++ b/qcsrc/server/tturrets/units/unit_tessla.qc @@ -35,11 +35,9 @@ entity toast(entity from, float range, float damage) } if (etarget) - { - te_smallflash(etarget.origin); + { te_csqc_lightningarc(from.origin,etarget.origin); - dprint("DMG:",ftos(damage),"\n"); - Damage(etarget, self, self, damage, DEATH_TURRET, etarget.origin, '0 0 0'); + Damage(etarget, self, self, damage, DEATH_TURRET_TESLA, etarget.origin, '0 0 0'); etarget.railgunhit = 1; } @@ -48,24 +46,45 @@ entity toast(entity from, float range, float damage) float turret_tesla_firecheck() { - if not (turret_stdproc_firecheck()) - return 0; + // g_turrets_targetscan_maxdelay forces a target re-scan at least this often + float do_target_scan; + + if((self.target_select_time + autocvar_g_turrets_targetscan_maxdelay) < time) + do_target_scan = 1; + + // Old target (if any) invalid? + if(self.target_validate_time < time) + if (turret_validate_target(self, self.enemy, self.target_validate_flags) <= 0) + { + self.enemy = world; + self.target_validate_time = time + 0.5; + do_target_scan = 1; + } - self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK; + // But never more often then g_turrets_targetscan_mindelay! + if (self.target_select_time + autocvar_g_turrets_targetscan_mindelay > time) + do_target_scan = 0; - self.enemy = turret_select_target(); + if(do_target_scan) + { + self.enemy = turret_select_target(); + self.target_select_time = time; + } + + if not (turret_stdproc_firecheck()) + return 0; if(self.enemy) return 1; return 0; - } + void turret_tesla_fire() { - entity e,t; - float d,r,i; + entity e, t; + float d, r, i; //w_deathtypestring = "discoverd how a tesla coil works"; @@ -103,7 +122,7 @@ void turret_tesla_fire() void turret_tesla_postthink() { - if not (self.tur_active) + if not (self.active) { self.tur_head.avelocity = '0 0 0'; return; @@ -145,7 +164,7 @@ void turret_tesla_dinit() self.aim_flags = TFL_AIM_NO; self.track_flags = TFL_TRACK_NO; - if (turret_stdproc_init("tesla_std",0,"models/turrets/tesla_base.md3","models/turrets/tesla_head.md3") == 0) + if (turret_stdproc_init("tesla_std", "models/turrets/tesla_base.md3", "models/turrets/tesla_head.md3", TID_TESLA) == 0) { remove(self); return; @@ -155,9 +174,6 @@ void turret_tesla_dinit() self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK; - if (!turret_tag_fire_update()) - dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n"); - self.turret_firefunc = turret_tesla_fire; self.turret_postthink = turret_tesla_postthink; self.turret_firecheckfunc = turret_tesla_firecheck; diff --git a/qcsrc/server/tturrets/units/unit_walker.qc b/qcsrc/server/tturrets/units/unit_walker.qc index 5d37db4929..646fccccb2 100644 --- a/qcsrc/server/tturrets/units/unit_walker.qc +++ b/qcsrc/server/tturrets/units/unit_walker.qc @@ -10,53 +10,13 @@ #define ANIM_MEELE 9 #define ANIM_SWIM 10 #define ANIM_ROAM 11 - .float animflag; -.entity wkr_spawn; #define WALKER_MIN '-70 -70 0' #define WALKER_MAX '70 70 95' #define WALKER_PATH(s,e) pathlib_astar(s,e) -float walker_meele_dmg; -float walker_meele_force; - -float walker_speed_stop; -float walker_speed_walk; -float walker_speed_run; -float walker_speed_jump; -float walker_speed_roam; -float walker_speed_swim; - -float walker_std_rocket_dmg; -float walker_std_rocket_radius; -float walker_std_rocket_force; -float walker_std_rocket_speed; -float walker_std_rocket_turnrate; - -void walker_loadcvars() -{ - walker_meele_dmg = autocvar_g_turrets_unit_walker_std_meele_dmg; - walker_meele_force = autocvar_g_turrets_unit_walker_std_meele_force; - - walker_speed_stop = autocvar_g_turrets_unit_walker_speed_stop; - walker_speed_walk = autocvar_g_turrets_unit_walker_speed_walk; - walker_speed_run = autocvar_g_turrets_unit_walker_speed_run; - walker_speed_jump = autocvar_g_turrets_unit_walker_speed_jump; - walker_speed_roam = autocvar_g_turrets_unit_walker_speed_roam; - walker_speed_swim = autocvar_g_turrets_unit_walker_speed_swim; - - walker_std_rocket_dmg = autocvar_g_turrets_unit_walker_std_rocket_dmg; - walker_std_rocket_radius = autocvar_g_turrets_unit_walker_std_rocket_radius; - walker_std_rocket_force = autocvar_g_turrets_unit_walker_std_rocket_force; - walker_std_rocket_speed = autocvar_g_turrets_unit_walker_std_rocket_speed; - walker_std_rocket_turnrate = autocvar_g_turrets_unit_walker_std_rocket_turnrate; - -} - - - float walker_firecheck() { if (self.animflag == ANIM_MEELE) @@ -69,171 +29,29 @@ void walker_meele_do_dmg() { vector where; entity e; + makevectors(self.angles); where = self.origin + v_forward * 128; - //w_deathtypestring = "tried to hug the cute spider thingy."; e = findradius(where,32); - while (e) + while (e) { - if (turret_validate_target(self,e,self.target_validate_flags)) + if (turret_validate_target(self, e, self.target_validate_flags)) if (e != self && e.owner != self) - Damage(e, self, self, walker_meele_dmg ,DEATH_TURRET,'0 0 0', v_forward * walker_meele_force); + Damage(e, self, self, autocvar_g_turrets_unit_walker_std_meele_dmg, DEATH_TURRET_WALKER_MEELE, '0 0 0', v_forward * autocvar_g_turrets_unit_walker_std_meele_force); e = e.chain; } } + void walker_setnoanim() { - self.frame = ANIM_NO; - self.animflag = self.owner.frame; - dprint("walker_setnoanim\n"); - + turrets_setframe(ANIM_NO, FALSE); + self.animflag = self.frame; } - -void walker_dly_meele_do_dmg() -{ - walker_meele_do_dmg(); - dprint("walker_dly_meele_do_dmg\n"); - -} - -void walker_animate() -{ - vector real_angle; - float vz; - - real_angle = vectoangles(self.steerto) - self.angles; - vz = self.velocity_z; - - if (self.tur_head.frame != 0) - self.tur_head.frame = self.tur_head.frame +1; - - if (self.tur_head.frame > 12) - self.tur_head.frame = 0; - - switch (self.animflag) - { - - case ANIM_NO: - self.frame = 0; - movelib_beak_simple(walker_speed_stop); - break; - - /* - case ANIM_REVERSE: - if ((self.frame < 5) || (self.frame > 25)) - self.frame = 25; - - self.frame = self.frame -1; - movelib_move_simple(v_forward * -1, walker_speed_walk, 0.6); - - if (self.frame < 5) - self.frame = 25; - - break; - */ - - case ANIM_TURN: - self.frame = ANIM_TURN; - self.angles_y += bound(-15, shortangle_f(real_angle_y, self.angles_y), 15); - movelib_beak_simple(walker_speed_stop); - break; - - case ANIM_WALK: - self.frame = ANIM_WALK; - self.angles_y += bound(-10, shortangle_f(real_angle_y, self.angles_y), 10); - movelib_move_simple(v_forward, walker_speed_walk, 0.6); - break; - - case ANIM_RUN: - self.frame = ANIM_RUN; - self.angles_y += bound(-5, shortangle_f(real_angle_y, self.angles_y), 5); - movelib_move_simple(v_forward, walker_speed_run, 0.6); - break; - - case ANIM_STRAFE_L: - self.frame = ANIM_STRAFE_L; - self.angles_y += bound(-2.5, shortangle_f(real_angle_y, self.angles_y), 2.5); - movelib_move_simple(v_right * -1, walker_speed_walk, 0.8); - break; - - case ANIM_STRAFE_R: - self.frame = ANIM_STRAFE_R; - self.angles_y += bound(-2.5, shortangle_f(real_angle_y, self.angles_y), 2.5); - movelib_move_simple(v_right, walker_speed_walk, 0.8); - break; - - case ANIM_JUMP: - self.frame = ANIM_JUMP; - self.velocity += '0 0 1' * walker_speed_jump; - break; - - case ANIM_LAND: - self.frame = ANIM_LAND; - break; - - case ANIM_PAIN: - if(self.frame != ANIM_PAIN) - defer(0.25,walker_setnoanim); - - self.frame = ANIM_PAIN; - - break; - - case ANIM_MEELE: - if(self.frame != ANIM_MEELE) - { - defer(0.41, walker_setnoanim); - defer(0.21, walker_dly_meele_do_dmg); - } - - self.frame = ANIM_MEELE; - movelib_beak_simple(walker_speed_stop); - break; - - case ANIM_SWIM: - self.frame = ANIM_SWIM; - self.angles_y += bound(-10, shortangle_f(real_angle_y, self.angles_y), 10); - self.angles_x += bound(-10, shortangle_f(real_angle_x, self.angles_x), 10); - movelib_move_simple(v_forward, walker_speed_swim, 0.3); - vz = self.velocity_z + sin(time * 4) * 8; - break; - - case ANIM_ROAM: - self.frame = ANIM_ROAM; - self.angles_y += bound(-5, shortangle_f(real_angle_y, self.angles_y), 5); - movelib_move_simple(v_forward ,walker_speed_roam, 0.5); - break; - - } - - self.velocity_z = vz; - - if (self.flags & FL_ONGROUND) - movelib_groundalign4point(300, 100, 0.25); - -} - - void walker_rocket_explode() { - vector org2; - - if (self.event_damage != SUB_Null) - { - self.event_damage = SUB_Null; - self.think = walker_rocket_explode; - self.nextthink = time; - return; - } - - sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); - org2 = findbetterlocation (self.origin, 16); - - pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1); - RadiusDamage (self, self.owner, walker_std_rocket_dmg, 0, walker_std_rocket_radius, world,walker_std_rocket_force, DEATH_TURRET, world); - + RadiusDamage (self, self.owner, autocvar_g_turrets_unit_walker_std_rocket_dmg, 0, autocvar_g_turrets_unit_walker_std_rocket_radius, self, autocvar_g_turrets_unit_walker_std_rocket_force, DEATH_TURRET_WALKER_ROCKET, world); remove (self); } @@ -241,11 +59,12 @@ void walker_rocket_damage (entity inflictor, entity attacker, float damage, floa { self.health = self.health - damage; self.velocity = self.velocity + vforce; + if (self.health <= 0) - walker_rocket_explode(); + W_PrepareExplosionByDamage(self.owner, walker_rocket_explode); } -#define WALKER_ROCKET_MOVE movelib_move_simple(newdir, walker_std_rocket_speed, walker_std_rocket_turnrate); UpdateCSQCProjectile(self) +#define WALKER_ROCKET_MOVE movelib_move_simple(newdir, autocvar_g_turrets_unit_walker_std_rocket_speed, autocvar_g_turrets_unit_walker_std_rocket_turnrate); UpdateCSQCProjectile(self) void walker_rocket_loop(); void walker_rocket_think() { @@ -262,49 +81,42 @@ void walker_rocket_think() if (self.cnt < time) { if (edist < 1000) - self.tur_shotorg = randomvec() * min(edist,64); + self.tur_shotorg = randomvec() * min(edist, 64); else - self.tur_shotorg = randomvec() * min(edist,256); + self.tur_shotorg = randomvec() * min(edist, 256); self.cnt = time + 0.5; } - if (edist < 256) + if (edist < 128) self.tur_shotorg = '0 0 0'; - if (self.tur_health < time) { - self.think = walker_rocket_explode; - self.nextthink = time; + self.think = walker_rocket_explode; + self.nextthink = time; return; } - if (self.shot_dmg != 1337) - if (random() < 0.01) - { - walker_rocket_loop(); - return; - } + if (self.shot_dmg != 1337 && random() < 0.01) + { + walker_rocket_loop(); + return; + } m_speed = vlen(self.velocity); // Enemy dead? just keep on the current heading then. - if ((self.enemy == world) || (self.enemy.deadflag != DEAD_NO)) - { - // Make sure we dont return to tracking a respawned entity + if (self.enemy == world || self.enemy.deadflag != DEAD_NO) self.enemy = world; - } if (self.enemy) { - itime = max(edist / m_speed,1); + itime = max(edist / m_speed, 1); newdir = steerlib_pull(self.enemy.origin + self.tur_shotorg); } else - { newdir = normalize(self.velocity); - } WALKER_ROCKET_MOVE; } @@ -320,7 +132,7 @@ void walker_rocket_loop3() return; } - if (vlen(self.origin - self.tur_shotorg) < 128 ) + if (vlen(self.origin - self.tur_shotorg) < 100 ) { self.think = walker_rocket_think; return; @@ -344,7 +156,7 @@ void walker_rocket_loop2() return; } - if (vlen(self.origin - self.tur_shotorg) < 128 ) + if (vlen(self.origin - self.tur_shotorg) < 100 ) { self.tur_shotorg = self.origin - '0 0 200'; self.think = walker_rocket_loop3; @@ -358,37 +170,30 @@ void walker_rocket_loop2() void walker_rocket_loop() { self.nextthink = time; - self.tur_shotorg = self.origin + '0 0 400'; + self.tur_shotorg = self.origin + '0 0 300'; self.think = walker_rocket_loop2; self.shot_dmg = 1337; } void walker_fire_rocket(vector org) { - entity rocket; - - - //self.angles_x *= -1; + fixedmakevectors(self.angles); - //self.angles_x *= -1; te_explosion (org); rocket = spawn (); setorigin(rocket, org); - sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_WEAPON_A, "weapons/hagar_fire.wav", VOL_BASE, ATTN_NORM); setsize (rocket, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot rocket.classname = "walker_rocket"; rocket.owner = self; - rocket.bot_dodge = TRUE; rocket.bot_dodgerating = 50; - rocket.takedamage = DAMAGE_YES; - rocket.damageforcescale = 2; rocket.health = 25; rocket.tur_shotorg = randomvec() * 512; @@ -402,9 +207,9 @@ void walker_fire_rocket(vector org) rocket.event_damage = walker_rocket_damage; - rocket.nextthink = time;// + 0.25; + rocket.nextthink = time; rocket.movetype = MOVETYPE_FLY; - rocket.velocity = normalize((v_forward + v_up * 0.5) + (randomvec() * 0.2)) * walker_std_rocket_speed; + rocket.velocity = normalize((v_forward + v_up * 0.5) + (randomvec() * 0.2)) * autocvar_g_turrets_unit_walker_std_rocket_speed; rocket.angles = vectoangles(rocket.velocity); rocket.touch = walker_rocket_explode; rocket.flags = FL_PROJECTILE; @@ -414,42 +219,43 @@ void walker_fire_rocket(vector org) CSQCProjectile(rocket, FALSE, PROJECTILE_ROCKET, FALSE); // no culling, has fly sound } -void rv_think() +.vector enemy_last_loc; +.float enemy_last_time; +void walker_move_to(vector _target, float _dist) { - float f; - vector org; - entity oldself; - - if (self.owner.deadflag != DEAD_NO) + switch (self.waterlevel) { - remove(self); - return; + case WATERLEVEL_NONE: + if (_dist > 500) + self.animflag = ANIM_RUN; + else + self.animflag = ANIM_WALK; + case WATERLEVEL_WETFEET: + case WATERLEVEL_SWIMMING: + if (self.animflag != ANIM_SWIM) + self.animflag = ANIM_WALK; + else + self.animflag = ANIM_SWIM; + break; + case WATERLEVEL_SUBMERGED: + self.animflag = ANIM_SWIM; } - self.cnt = self.cnt -1; + self.moveto = _target; + self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95); - if (self.cnt < 0) + if(self.enemy) { - remove(self); - return; + self.enemy_last_loc = _target; + self.enemy_last_time = time; } - - if (self.cnt > 1) - f = gettagindex(self.owner,"tag_rocket01"); - else - f = gettagindex(self.owner,"tag_rocket02"); - - org = gettaginfo(self.owner,f); - - self.nextthink = time + 0.2; - oldself = self; - self = self.owner; - walker_fire_rocket(org); - self = oldself; } +//#define WALKER_FANCYPATHING + void walker_move_path() { +#ifdef WALKER_FANCYPATHING // Are we close enougth to a path node to switch to the next? if (vlen(self.origin - self.pathcurrent.origin) < 64) if (self.pathcurrent.path_next == world) @@ -475,182 +281,259 @@ void walker_move_path() else self.pathcurrent = self.pathcurrent.path_next; - switch (self.waterlevel) - { - case 0: - self.animflag = ANIM_WALK; - case 1: - case 2: - if (self.animflag == ANIM_WALK) - self.animflag = ANIM_WALK; - else - self.animflag = ANIM_SWIM; - break; - case 3: - self.animflag = ANIM_SWIM; - } - self.moveto = self.pathcurrent.origin; self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95); + walker_move_to(self.moveto, 0); +#else + if (vlen(self.origin - self.pathcurrent.origin) < 64) + self.pathcurrent = self.pathcurrent.enemy; + + if(!self.pathcurrent) + return; + + self.moveto = self.pathcurrent.origin; + self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95); + walker_move_to(self.moveto, 0); +#endif } -void walker_move_enemy() -{ - switch (self.waterlevel) - { - case 0: - if (self.tur_dist_enemy > 500) - self.animflag = ANIM_RUN; - else - self.animflag = ANIM_WALK; - case 1: - case 2: - if (self.animflag != ANIM_SWIM) - self.animflag = ANIM_WALK; - else - self.animflag = ANIM_SWIM; - break; - case 3: - self.animflag = ANIM_SWIM; - } - - self.moveto = self.enemy.origin; - self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95); - -} - -void walker_move_idle_pause() -{ - self.moveto = self.origin; - self.steerto = v_forward; - self.animflag = ANIM_NO; -} - -void walker_move_idle_roam() -{ -} - -void walker_move_idle() -{ -} - -float walker_attack_meele() -{ - - vector wish_angle; - - - if (self.animflag == ANIM_SWIM || self.animflag == ANIM_MEELE) - return 0; - - wish_angle = angleofs(self,self.enemy); - - if (self.tur_dist_enemy > autocvar_g_turrets_unit_walker_std_meele_range) - return 0; - else - if (fabs(wish_angle_y) > 15) - return 0; - - self.moveto = self.enemy.origin; - self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95); - self.animflag = ANIM_MEELE; - - return 1; -} - -float walker_attack_rockets() -{ - if (self.tur_head.attack_finished_single > time) - return 0; - - if (self.tur_dist_enemy < autocvar_g_turrets_unit_walker_std_rockets_range_min) - return 0; - - if (self.tur_dist_enemy > autocvar_g_turrets_unit_walker_std_rockets_range) - return 0; - - entity rv; - - rv = spawn(); - rv.think = rv_think; - rv.nextthink = time; - rv.cnt = 4; - rv.owner = self; - - self.tur_head.attack_finished_single = time + autocvar_g_turrets_unit_walker_std_rocket_refire; - - return 1; -} - +.float idletime; void walker_postthink() { - - //self.angles_x *= -1; fixedmakevectors(self.angles); - //self.angles_x *= -1; - if ((self.spawnflags & TSF_NO_PATHBREAK) && self.pathcurrent) + if (self.spawnflags & TSF_NO_PATHBREAK && self.pathcurrent) walker_move_path(); else if (self.enemy == world) { if(self.pathcurrent) walker_move_path(); else - walker_move_idle_pause(); + { + if(self.enemy_last_time != 0) + { + if(vlen(self.origin - self.enemy_last_loc) < 128 || time - self.enemy_last_time > 10) + self.enemy_last_time = 0; + else + walker_move_to(self.enemy_last_loc, 0); + } + else + { + if(self.animflag != ANIM_NO) + { + traceline(self.origin + '0 0 64', self.origin + '0 0 64' + v_forward * 128, MOVE_NORMAL, self); + + if(trace_fraction != 1.0) + self.tur_head.idletime = -1337; + else + { + traceline(trace_endpos, trace_endpos - '0 0 256', MOVE_NORMAL, self); + if(trace_fraction == 1.0) + self.tur_head.idletime = -1337; + } + + if(self.tur_head.idletime == -1337) + { + self.moveto = self.origin + randomvec() * 256; + self.tur_head.idletime = 0; + } + + self.moveto = self.moveto * 0.9 + ((self.origin + v_forward * 500) + randomvec() * 400) * 0.1; + self.moveto_z = self.origin_z + 64; + walker_move_to(self.moveto, 0); + } + + if(self.idletime < time) + { + if(random() < 0.5 || !(self.spawnflags & TSL_ROAM)) + { + self.idletime = time + 1 + random() * 5; + self.moveto = self.origin; + self.animflag = ANIM_NO; + } + else + { + self.animflag = ANIM_WALK; + self.idletime = time + 4 + random() * 2; + self.moveto = self.origin + randomvec() * 256; + self.tur_head.moveto = self.moveto; + self.tur_head.idletime = 0; + } + } + } + } } else { - if not (self.animflag == ANIM_MEELE) - if not (walker_attack_rockets()) - walker_attack_meele(); - - if not (self.animflag == ANIM_MEELE) - walker_move_enemy(); + if (self.tur_dist_enemy < autocvar_g_turrets_unit_walker_std_meele_range && self.animflag != ANIM_MEELE) + { + vector wish_angle; + + wish_angle = angleofs(self, self.enemy); + if (self.animflag != ANIM_SWIM) + if (fabs(wish_angle_y) < 15) + { + self.moveto = self.enemy.origin; + self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95); + self.animflag = ANIM_MEELE; + } + } + else if (self.tur_head.attack_finished_single < time) + { + if(self.tur_head.shot_volly) + { + self.animflag = ANIM_NO; + + self.tur_head.shot_volly = self.tur_head.shot_volly -1; + if(self.tur_head.shot_volly == 0) + self.tur_head.attack_finished_single = time + autocvar_g_turrets_unit_walker_std_rocket_refire; + else + self.tur_head.attack_finished_single = time + 0.2; + + if(self.tur_head.shot_volly > 1) + walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket01"))); + else + walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket02"))); + } + else + { + if (self.tur_dist_enemy > autocvar_g_turrets_unit_walker_std_rockets_range_min) + if (self.tur_dist_enemy < autocvar_g_turrets_unit_walker_std_rockets_range) + self.tur_head.shot_volly = 4; + } + } + else + { + if (self.animflag != ANIM_MEELE) + walker_move_to(self.enemy.origin, self.tur_dist_enemy); + } } + //if(self.animflag != ANIM_NO) + { + vector real_angle; + float turny, turnx; + float vz; + + real_angle = vectoangles(self.steerto) - self.angles; + vz = self.velocity_z; + + switch (self.animflag) + { + case ANIM_NO: + movelib_beak_simple(autocvar_g_turrets_unit_walker_speed_stop); + break; + + case ANIM_TURN: + turny = autocvar_g_turrets_unit_walker_turn; + movelib_beak_simple(autocvar_g_turrets_unit_walker_speed_stop); + break; + + case ANIM_WALK: + turny = autocvar_g_turrets_unit_walker_turn_walk; + movelib_move_simple(v_forward, autocvar_g_turrets_unit_walker_speed_walk, 0.6); + break; + + case ANIM_RUN: + turny = autocvar_g_turrets_unit_walker_turn_run; + movelib_move_simple(v_forward, autocvar_g_turrets_unit_walker_speed_run, 0.6); + break; + + case ANIM_STRAFE_L: + turny = autocvar_g_turrets_unit_walker_turn_strafe; + movelib_move_simple(v_right * -1, autocvar_g_turrets_unit_walker_speed_walk, 0.8); + break; + + case ANIM_STRAFE_R: + turny = autocvar_g_turrets_unit_walker_turn_strafe; + movelib_move_simple(v_right, autocvar_g_turrets_unit_walker_speed_walk, 0.8); + break; + + case ANIM_JUMP: + self.velocity += '0 0 1' * autocvar_g_turrets_unit_walker_speed_jump; + break; + + case ANIM_LAND: + break; + + case ANIM_PAIN: + if(self.frame != ANIM_PAIN) + defer(0.25, walker_setnoanim); + + break; + + case ANIM_MEELE: + if(self.frame != ANIM_MEELE) + { + defer(0.41, walker_setnoanim); + defer(0.21, walker_meele_do_dmg); + } + + movelib_beak_simple(autocvar_g_turrets_unit_walker_speed_stop); + break; + + case ANIM_SWIM: + turny = autocvar_g_turrets_unit_walker_turn_swim; + turnx = autocvar_g_turrets_unit_walker_turn_swim; + + self.angles_x += bound(-10, shortangle_f(real_angle_x, self.angles_x), 10); + movelib_move_simple(v_forward, autocvar_g_turrets_unit_walker_speed_swim, 0.3); + vz = self.velocity_z + sin(time * 4) * 8; + break; + + case ANIM_ROAM: + turny = autocvar_g_turrets_unit_walker_turn_walk; + movelib_move_simple(v_forward ,autocvar_g_turrets_unit_walker_speed_roam, 0.5); + break; + } + + if(turny) + { + turny = bound( turny * -1, shortangle_f(real_angle_y, self.angles_y), turny ); + self.angles_y += turny; + } - walker_animate(); + if(turnx) + { + turnx = bound( turnx * -1, shortangle_f(real_angle_x, self.angles_x), turnx ); + self.angles_x += turnx; + } + + self.velocity_z = vz; + } + + + if(self.origin != self.oldorigin) + self.SendFlags |= TNSF_MOVE; + + self.oldorigin = self.origin; + turrets_setframe(self.animflag, FALSE); } void walker_attack() { - sound (self, CHAN_WEAPON, "weapons/uzi_fire.wav", VOL_BASE, ATTN_NORM); - fireBallisticBullet (self.tur_shotorg, self.tur_shotdir_updated,self.shot_spread, self.shot_speed, 5, self.shot_dmg, 0, self.shot_force, DEATH_TURRET, 0, 1, autocvar_g_balance_uzi_bulletconstant); + sound (self, CH_WEAPON_A, "weapons/uzi_fire.wav", VOL_BASE, ATTN_NORM); + fireBallisticBullet (self.tur_shotorg, self.tur_shotdir_updated, self.shot_spread, self.shot_speed, 5, self.shot_dmg, 0, self.shot_force, DEATH_TURRET_WALKER_GUN, 0, 1, autocvar_g_balance_uzi_bulletconstant); endFireBallisticBullet(); - if (self.uzi_bulletcounter == 2) - { - - UziFlash(); - setattachment(self.muzzle_flash, self.tur_head, "tag_fire"); - - self.uzi_bulletcounter = 0; - } - - self.uzi_bulletcounter = self.uzi_bulletcounter + 1; - self.tur_head.frame = self.tur_head.frame + 1; + pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1); } void walker_respawnhook() { - vector vtmp; entity e; // Respawn is called & first spawn to, to set team. need to make sure we do not move the initial spawn. - if(self.movetype != MOVETYPE_WALK) + if(self.movetype != MOVETYPE_WALK) return; - setorigin(self, self.wkr_spawn.origin); - - self.angles = self.wkr_spawn.angles; - vtmp = self.wkr_spawn.origin; - vtmp_z += self.wkr_spawn.maxs_z; - setorigin(self,vtmp); - + setorigin(self, self.pos1); + self.angles = self.pos2; + if (self.target != "") { - e = find(world,targetname,self.target); + e = find(world, targetname, self.target); if (!e) { dprint("Warning! initital waypoint for Walker does NOT exsist!\n"); @@ -661,34 +544,30 @@ void walker_respawnhook() dprint("Warning: not a turrret path\n"); else { - self.pathcurrent = WALKER_PATH(self.origin,e.origin); + #ifdef WALKER_FANCYPATHING + self.pathcurrent = WALKER_PATH(self.origin, e.origin); self.pathgoal = e; +#else + self.pathcurrent = e; +#endif } } } void walker_diehook() { - turret_trowgib2(self.origin, self.velocity + v_up * 200, '-0.6 -0.2 -02', self,time + random() * 1); - turret_trowgib2(self.origin + '0 0 64', self.velocity + v_forward * 150 + v_up * 150, '-0.2 -0.2 -02', self.tur_head, 3 + time + random() * 2); - +#ifdef WALKER_FANCYPATHING if (self.pathcurrent) pathlib_deletepath(self.pathcurrent.owner); - +#endif self.pathcurrent = world; - - if (self.damage_flags & TFL_DMG_DEATH_NORESPAWN) - remove(self.wkr_spawn); - } void turret_walker_dinit() { - entity e; if (self.netname == "") self.netname = "Walker Turret"; - self.wkr_spawn = spawn(); self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE; self.turrcaps_flags = TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MOVE ; @@ -704,38 +583,24 @@ void turret_walker_dinit() self.turret_diehook = walker_diehook; self.ticrate = 0.05; - if (turret_stdproc_init("walker_std",FALSE,"models/turrets/walker_body.md3","models/turrets/walker_head_minigun.md3") == 0) + if (turret_stdproc_init("walker_std", "models/turrets/walker_body.md3", "models/turrets/walker_head_minigun.md3", TID_WALKER) == 0) { remove(self); return; } - - if (!turret_tag_fire_update()) - dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n"); - - self.damage_flags |= TFL_DMG_DEATH_NOGIBS; + setsize(self, WALKER_MIN, WALKER_MAX); self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS; self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS; - self.iscreature = TRUE; + self.damagedbycontents = TRUE; self.movetype = MOVETYPE_WALK; self.solid = SOLID_SLIDEBOX; - self.takedamage = DAMAGE_AIM; - - setmodel(self.wkr_spawn,"models/turrets/walker_spawn.md3"); - - self.wkr_spawn.angles = self.angles; - self.wkr_spawn.solid = SOLID_NOT; - - setsize(self, WALKER_MIN, WALKER_MAX); - - setorigin(self,self.origin); - //traceline(self.origin + '0 0 128', self.origin - '0 0 10000', MOVE_NORMAL, self); - tracebox(self.origin + '0 0 128', self.mins,self.maxs,self.origin - '0 0 10000', MOVE_NORMAL, self); - - setorigin(self.wkr_spawn, trace_endpos + '0 0 4'); - setorigin(self, self.wkr_spawn.origin); - + self.takedamage = DAMAGE_AIM; + setorigin(self, self.origin); + tracebox(self.origin + '0 0 128', self.mins, self.maxs, self.origin - '0 0 10000', MOVE_NORMAL, self); + setorigin(self, trace_endpos + '0 0 4'); + self.pos1 = self.origin; + self.pos2 = self.angles; self.idle_aim = '0 0 0'; self.turret_firecheckfunc = walker_firecheck; self.turret_firefunc = walker_attack; @@ -743,7 +608,7 @@ void turret_walker_dinit() if (self.target != "") { - e = find(world,targetname,self.target); + e = find(world, targetname, self.target); if (!e) { dprint("Initital waypoint for walker does NOT exsist, fix your map!\n"); @@ -754,8 +619,12 @@ void turret_walker_dinit() dprint("Warning: not a turrret path\n"); else { - self.pathcurrent = WALKER_PATH(self.origin,e.origin); +#ifdef WALKER_FANCYPATHING + self.pathcurrent = WALKER_PATH(self.origin, e.origin); self.pathgoal = e; +#else + self.pathcurrent = e; +#endif } } } @@ -763,14 +632,10 @@ void turret_walker_dinit() void spawnfunc_turret_walker() { - walker_loadcvars(); - g_turrets_common_precash(); precache_model ("models/turrets/walker_head_minigun.md3"); precache_model ("models/turrets/walker_body.md3"); - precache_model ("models/turrets/walker_props.md3"); - precache_model ("models/turrets/walker_spawn.md3"); precache_model ( "models/turrets/rocket.md3"); precache_sound ( "weapons/rocket_impact.wav" ); diff --git a/qcsrc/server/vehicles/racer.qc b/qcsrc/server/vehicles/racer.qc index 09efab4bfc..fa188bbb1d 100644 --- a/qcsrc/server/vehicles/racer.qc +++ b/qcsrc/server/vehicles/racer.qc @@ -1,122 +1,109 @@ -#define RACER_MIN '-80 -80 -40' -#define RACER_MAX '80 80 40' -#define RACER_TICRATE 0.05 +#define RACER_MIN '-120 -120 -40' +#define RACER_MAX '120 120 40' +#ifdef SVQC void racer_exit(float eject); void racer_enter(); -//void racer_think(); -float racer_power_air; -float racer_power_solid; -float racer_power_min; -float racer_anglestabilizer; -float racer_springlength; - -float racer_healthmax; -float racer_shieldmax; -float racer_energymax; - -float racer_pitchspeed; -float racer_turnspeed; -float racer_turnroll; -float racer_speed_forward; -float racer_speed_strafe; - -float racer_afterburn_cost; - -float jetfromtag_power; -float jetfromtag_normpower; -vector jetfromtag_origin; -float jetfromtag_groundcontact; - -void racer_loadsettings() -{ - racer_power_min = autocvar_g_vehicle_racer_power_min * 0.25; - racer_power_air = autocvar_g_vehicle_racer_power_air * 0.25; - racer_power_solid = autocvar_g_vehicle_racer_power_solid * 0.25; - - racer_springlength = autocvar_g_vehicle_racer_springlength; - racer_anglestabilizer = autocvar_g_vehicle_racer_anglestabilizer; - racer_pitchspeed = autocvar_g_vehicle_racer_pitchspeed; - racer_turnspeed = autocvar_g_vehicle_racer_turnspeed; - racer_turnroll = autocvar_g_vehicle_racer_turnroll; - racer_speed_forward = autocvar_g_vehicle_racer_speed_forward; - racer_speed_strafe = autocvar_g_vehicle_racer_speed_strafe; - - racer_afterburn_cost = autocvar_g_vehicle_racer_afterburn_cost; - - racer_healthmax = autocvar_g_vehicle_racer_health; - racer_shieldmax = autocvar_g_vehicle_racer_shield; - racer_energymax = autocvar_g_vehicle_racer_energy; - -} - -vector racer_jetfromtag(string tagname) -{ - vector force_dir; - float air_frac, solid_frac, air_pwr, solid_pwr; - - jetfromtag_origin = gettaginfo(self,gettagindex(self,tagname)); - v_forward = normalize(v_forward) * -1; - - force_dir = jetfromtag_origin - (v_forward * racer_springlength); - traceline(jetfromtag_origin, force_dir, MOVE_NORMAL, self); - //te_lightning1(world,jetfromtag_origin, force_dir); - - //trace_fraction *= trace_fraction; - - solid_frac = 1 - trace_fraction; - air_frac = trace_fraction; - - if (trace_fraction != 1.0) - jetfromtag_groundcontact = 1; - - solid_pwr = solid_frac * racer_power_solid; - air_pwr = air_frac * racer_power_air; - - jetfromtag_power = solid_pwr + air_pwr; - jetfromtag_normpower = jetfromtag_power / (racer_power_air + racer_power_solid); - - //te_lightning1(world,jetfromtag_origin,jetfromtag_origin + normalize(self.origin - force_dir) * max(jetfromtag_power, racer_power_min)); - //return normalize(self.origin - force_dir) * max(jetfromtag_power, racer_power_min); - return v_forward * max(jetfromtag_power, racer_power_min); -} +// Auto cvars +float autocvar_g_vehicle_racer_speed_afterburn; +float autocvar_g_vehicle_racer_afterburn_cost; + +float autocvar_g_vehicle_racer_anglestabilizer; +float autocvar_g_vehicle_racer_downforce; + +float autocvar_g_vehicle_racer_speed_forward; +float autocvar_g_vehicle_racer_speed_strafe; +float autocvar_g_vehicle_racer_springlength; +float autocvar_g_vehicle_racer_upforcedamper; +float autocvar_g_vehicle_racer_friction; + +float autocvar_g_vehicle_racer_hovertype; +float autocvar_g_vehicle_racer_hoverpower; + +float autocvar_g_vehicle_racer_turnroll; +float autocvar_g_vehicle_racer_turnspeed; +float autocvar_g_vehicle_racer_pitchspeed; + +float autocvar_g_vehicle_racer_energy; +float autocvar_g_vehicle_racer_energy_regen; +float autocvar_g_vehicle_racer_energy_regen_pause; + +float autocvar_g_vehicle_racer_health; +float autocvar_g_vehicle_racer_health_regen; +float autocvar_g_vehicle_racer_health_regen_pause; + +float autocvar_g_vehicle_racer_shield; +float autocvar_g_vehicle_racer_shield_regen; +float autocvar_g_vehicle_racer_shield_regen_pause; + +float autocvar_g_vehicle_racer_cannon_cost; +float autocvar_g_vehicle_racer_cannon_damage; +float autocvar_g_vehicle_racer_cannon_radius; +float autocvar_g_vehicle_racer_cannon_refire; +float autocvar_g_vehicle_racer_cannon_speed; +float autocvar_g_vehicle_racer_cannon_spread; +float autocvar_g_vehicle_racer_cannon_force; + +float autocvar_g_vehicle_racer_rocket_accel; +float autocvar_g_vehicle_racer_rocket_damage; +float autocvar_g_vehicle_racer_rocket_radius; +float autocvar_g_vehicle_racer_rocket_force; +float autocvar_g_vehicle_racer_rocket_refire; +float autocvar_g_vehicle_racer_rocket_speed; +float autocvar_g_vehicle_racer_rocket_turnrate; + +float autocvar_g_vehicle_racer_rocket_locktarget; +float autocvar_g_vehicle_racer_rocket_locking_time; +float autocvar_g_vehicle_racer_rocket_locking_releasetime; +float autocvar_g_vehicle_racer_rocket_locked_time; +float autocvar_g_vehicle_racer_rocket_locked_maxangle; + +float autocvar_g_vehicle_racer_respawntime; + +float autocvar_g_vehicle_racer_blowup_radius; +float autocvar_g_vehicle_racer_blowup_coredamage; +float autocvar_g_vehicle_racer_blowup_edgedamage; +float autocvar_g_vehicle_racer_blowup_forceintensity; + +float autocvar_g_vehicle_racer_bouncefactor; +float autocvar_g_vehicle_racer_bouncestop; +vector autocvar_g_vehicle_racer_bouncepain; + +var vector racer_force_from_tag(string tag_name, float spring_length, float max_power); void racer_align4point() { - vector push_vector; + vector push_vector, v_add; float fl_push, fr_push, bl_push, br_push; - jetfromtag_groundcontact = 0; - push_vector = racer_jetfromtag("tag_engine_fr"); - fr_push = jetfromtag_normpower; - traceline(jetfromtag_origin, jetfromtag_origin + self.velocity * frametime, MOVE_NORMAL,self); - if(trace_fraction != 1) - self.velocity += normalize(self.origin - trace_endpos) * (vlen(self.velocity) * 1.25); + push_vector = racer_force_from_tag("tag_engine_fr", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower); + fr_push = force_fromtag_normpower; + //vehicles_sweap_collision(force_fromtag_origin, self.velocity, frametime, v_add, autocvar_g_vehicle_racer_collision_multiplier); + + push_vector += racer_force_from_tag("tag_engine_fl", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower); + fl_push = force_fromtag_normpower; + //vehicles_sweap_collision(force_fromtag_origin, self.velocity, frametime, v_add, autocvar_g_vehicle_racer_collision_multiplier); - push_vector += racer_jetfromtag("tag_engine_fl"); - fl_push = jetfromtag_normpower; - traceline(jetfromtag_origin, jetfromtag_origin + self.velocity * frametime, MOVE_NORMAL,self); - if(trace_fraction != 1) - self.velocity += normalize(self.origin - trace_endpos) * (vlen(self.velocity) * 1.25); + push_vector += racer_force_from_tag("tag_engine_br", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower); + br_push = force_fromtag_normpower; + //vehicles_sweap_collision(force_fromtag_origin, self.velocity, frametime, v_add, autocvar_g_vehicle_racer_collision_multiplier); - push_vector += racer_jetfromtag("tag_engine_br"); - br_push = jetfromtag_normpower; - traceline(jetfromtag_origin, jetfromtag_origin + self.velocity * frametime, MOVE_NORMAL,self); - if(trace_fraction != 1) - self.velocity += normalize(self.origin - trace_endpos) * (vlen(self.velocity) * 1.25); + push_vector += racer_force_from_tag("tag_engine_bl", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower); + bl_push = force_fromtag_normpower; + //vehicles_sweap_collision(force_fromtag_origin, self.velocity, frametime, v_add, autocvar_g_vehicle_racer_collision_multiplier); - push_vector += racer_jetfromtag("tag_engine_bl"); - bl_push = jetfromtag_normpower; - traceline(jetfromtag_origin, jetfromtag_origin + self.velocity * frametime, MOVE_NORMAL,self); - if(trace_fraction != 1) - self.velocity += normalize(self.origin - trace_endpos) * (vlen(self.velocity) * 1.25); + self.velocity += (push_vector * frametime); - self.velocity = self.velocity + (push_vector * frametime); - self.velocity_z -= autocvar_sv_gravity * frametime; + // Anti ocilation + if(self.velocity_z > 0) + self.velocity_z *= 1 - (autocvar_g_vehicle_racer_upforcedamper * frametime); - push_vector_x = (fl_push - bl_push); + self.velocity += v_add; + //self.velocity_z -= autocvar_sv_gravity * frametime; + + push_vector_x = (fl_push - bl_push); push_vector_x += (fr_push - br_push); push_vector_x *= 360; @@ -124,105 +111,42 @@ void racer_align4point() push_vector_z += (br_push - bl_push); push_vector_z *= 360; - //if (push_vector_z != 0) - if(self.angles_z > 0) - self.angles_z = max(0, self.angles_z - (racer_anglestabilizer * frametime)); - else - self.angles_z = min(0, self.angles_z + (racer_anglestabilizer * frametime)); - //else - self.angles_z += push_vector_z * frametime; + // Apply angle diffrance + self.angles_z += push_vector_z * frametime; + self.angles_x += push_vector_x * frametime; - //if (push_vector_x != 0) - if(self.angles_x > 0) - self.angles_x = max(0, self.angles_x - (racer_anglestabilizer * frametime)); - else - self.angles_x = min(0, self.angles_x + (racer_anglestabilizer * frametime)); - //else - self.angles_x += push_vector_x * frametime; -} - -void racer_bolt_explode() -{ - vector org2; - - org2 = findbetterlocation (self.origin, 8); - pointparticles(particleeffectnum("laser_impact"), org2, trace_plane_normal * 1000, 1); - RadiusDamage (self, self.realowner, autocvar_g_vehicle_racer_laser_damage, 0, autocvar_g_vehicle_racer_laser_radius, world, 150, DEATH_WAKIGUN, world); - sound (self, CHAN_PROJECTILE, "weapons/electro_impact.wav", VOL_BASE, ATTN_NORM); - - remove (self); -} - -void racer_rocket_explode() -{ - vector org2; - - //if not(self.owner) - // self.owner = self.realowner; - - sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); - org2 = findbetterlocation (self.origin, 16); - pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1); - RadiusDamage (self, self.realowner ,autocvar_g_vehicle_racer_rocket_damage, 0, autocvar_g_vehicle_racer_rocket_radius, world, 150, DEATH_WAKIROCKET, world); - - remove (self); -} - -void racer_rocket_touch() -{ - if(other.owner == self.owner) - return; - - PROJECTILE_TOUCH; - /* - if(pointcontents(self.origin) == CONTENT_SKY) - { - self.think = SUB_Remove; - self.nextthink = time; - return; - } - */ - - racer_rocket_explode(); + // Apply stabilizer + self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * frametime); + self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * frametime); } void racer_fire_cannon(string tagname) { + vector v; entity bolt; - bolt = spawn(); - bolt.solid = SOLID_TRIGGER; - bolt.movetype = MOVETYPE_FLYMISSILE; - bolt.flags = FL_PROJECTILE | FL_NOTARGET; - bolt.owner = self; - bolt.realowner = self.owner; - bolt.touch = racer_bolt_explode; - bolt.think = racer_bolt_explode; - bolt.nextthink = time + 9; - bolt.bot_dodge = TRUE; - bolt.bot_dodgerating = autocvar_g_vehicle_racer_laser_damage; - setorigin(bolt, gettaginfo(self,gettagindex(self,tagname))); + v = gettaginfo(self, gettagindex(self, tagname)); + bolt = vehicles_projectile("wakizashi_gun_muzzleflash", "weapons/lasergun_fire.wav", + v, normalize(v_forward + randomvec() * autocvar_g_vehicle_racer_cannon_spread) * autocvar_g_vehicle_racer_cannon_speed, + autocvar_g_vehicle_racer_cannon_damage, autocvar_g_vehicle_racer_cannon_radius, autocvar_g_vehicle_racer_cannon_force, 0, + DEATH_WAKIGUN, PROJECTILE_WAKICANNON, 0, TRUE, TRUE); - vector v; - // FIXME this uses prydon cursor - v = normalize(self.owner.cursor_trace_endpos - bolt.origin); + // Fix z-aim (for chase mode) + v = normalize(trace_endpos - bolt.origin); v_forward_z = v_z * 0.5; - - bolt.velocity = v_forward * autocvar_g_vehicle_racer_laser_speed; - - CSQCProjectile(bolt, TRUE, PROJECTILE_LASER, TRUE); + bolt.velocity = v_forward * autocvar_g_vehicle_racer_cannon_speed; } void racer_rocket_groundhugger() { - vector newdir,olddir; - float oldspeed, newspeed; + vector olddir, newdir; + float oldvel, newvel; self.nextthink = time; - if ((self.owner.deadflag != DEAD_NO) || (self.cnt < time)) + if(self.owner.deadflag != DEAD_NO || self.cnt < time) { - racer_rocket_explode(); + self.use(); return; } @@ -232,35 +156,45 @@ void racer_rocket_groundhugger() return; } - olddir = normalize(self.velocity); - oldspeed = vlen(self.velocity); + olddir = normalize(self.velocity); + oldvel = vlen(self.velocity); + newvel = oldvel + self.lip; - tracebox(self.origin, self.mins, self.maxs, self.origin + olddir * 512, MOVE_WORLDONLY,self); - if(trace_fraction >= 0.35) + tracebox(self.origin, self.mins, self.maxs, self.origin + olddir * 64, MOVE_WORLDONLY,self); + if(trace_fraction <= 0.5) { - traceline(trace_endpos, trace_endpos - '0 0 512', MOVE_NORMAL, self); - if(trace_fraction != 1.0) - newdir = trace_endpos + '0 0 32'; - - newdir = normalize(newdir - self.origin); + // Hitting somethign soon, just speed ahead + self.velocity = olddir * newvel; + UpdateCSQCProjectile(self); + return; } - newspeed = oldspeed + self.lip; - self.velocity = normalize(olddir + newdir * self.wait) * newspeed; + traceline(trace_endpos, trace_endpos - '0 0 64', MOVE_NORMAL, self); + if(trace_fraction != 1.0) + { + newdir = normalize(trace_endpos + '0 0 64' - self.origin) * autocvar_g_vehicle_racer_rocket_turnrate; + self.velocity = normalize(olddir + newdir) * newvel; + } + else + { + self.velocity = olddir * newvel; + self.velocity_z -= 1600 * sys_frametime; // 2x grav looks better for this one + } UpdateCSQCProjectile(self); + return; } -void racer_rocket_think() +void racer_rocket_tracker() { - vector newdir,olddir, eorg, edir; - float oldspeed, newspeed, dist; + vector olddir, newdir; + float oldvel, newvel; self.nextthink = time; - if ((self.owner.deadflag != DEAD_NO) || (self.cnt < time)) + if (self.owner.deadflag != DEAD_NO || self.cnt < time) { - racer_rocket_explode(); + self.use(); return; } @@ -271,115 +205,71 @@ void racer_rocket_think() } olddir = normalize(self.velocity); - oldspeed = vlen(self.velocity); - fixedmakevectors(olddir); - eorg = 0.5 * (self.enemy.absmin + self.enemy.absmax); - edir = normalize(eorg - self.origin); - dist = vlen(self.origin - self.enemy.origin); + oldvel = vlen(self.velocity); + newvel = oldvel + self.lip; + makevectors(vectoangles(olddir)); + + traceline(self.origin, self.origin + v_forward * 64 - '0 0 32', MOVE_NORMAL, self); + newdir = normalize(self.enemy.origin - self.origin); - if(dist > 512) + if(vlen(newdir - v_forward) > autocvar_g_vehicle_racer_rocket_locked_maxangle) { - vector ddir; - float p; - p = dist / self.delay; - p = max(0.05, p * 0.25); - ddir = steerlib_traceavoid(p, oldspeed * 0.25); - edir += ddir * 0.95; + //bprint("Target lost!\n"); + //dprint("OF:", ftos(vlen(newdir - v_forward)), "\n"); + self.think = racer_rocket_groundhugger; + return; } - newdir = normalize(olddir + edir * self.wait); - newspeed = oldspeed + self.lip; - self.velocity = normalize(olddir + newdir * self.wait) * newspeed; + if(trace_fraction != 1.0) + newdir_z += 16 * sys_frametime; + + self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_racer_rocket_turnrate) * newvel; + self.velocity_z -= 800 * sys_frametime; UpdateCSQCProjectile(self); + return; } -void racer_fire_rocket(string tagname) +void racer_fire_rocket(string tagname, entity trg) { + vector v; entity rocket; - rocket = spawn(); - setsize (rocket, '-1 -1 -1', '1 1 1'); - rocket.lip = autocvar_g_vehicle_racer_rocket_accel * sys_frametime; - rocket.wait = autocvar_g_vehicle_racer_rocket_turnrate; - rocket.solid = SOLID_BBOX; - rocket.movetype = MOVETYPE_FLYMISSILE; - rocket.flags = FL_PROJECTILE; - rocket.owner = self; - rocket.realowner = self.owner; - rocket.touch = racer_rocket_touch; - rocket.bot_dodge = TRUE; - rocket.bot_dodgerating = autocvar_g_vehicle_racer_rocket_damage; - setorigin(rocket, gettaginfo(self,gettagindex(self,tagname))); + v = gettaginfo(self, gettagindex(self, tagname)); + rocket = vehicles_projectile("wakizashi_rocket_launch", "weapons/rocket_fire.wav", + v, v_forward * autocvar_g_vehicle_racer_rocket_speed, + autocvar_g_vehicle_racer_rocket_damage, autocvar_g_vehicle_racer_rocket_radius, autocvar_g_vehicle_racer_rocket_force, 3, + DEATH_WAKIROCKET, PROJECTILE_WAKIROCKET, 20, FALSE, FALSE); - /* - if( (self.tur_head.gun1) && (self.tur_head.cnt > time)) - rocket.enemy = self.tur_head.gun1; + rocket.lip = autocvar_g_vehicle_racer_rocket_accel * sys_frametime; + rocket.wait = autocvar_g_vehicle_racer_rocket_turnrate; + rocket.nextthink = time; + rocket.enemy = trg; + rocket.cnt = time + 15; - if(rocket.enemy) - { - rocket.delay = vlen(rocket.enemy.origin - rocket.origin); - rocket.cnt = time + 9; - rocket.velocity = v_forward * autocvar_g_vehicle_racer_rocket_speed; - rocket.think = racer_rocket_think; - rocket.nextthink = time; - CSQCProjectile(rocket, FALSE, PROJECTILE_ROCKET, FALSE); // no culling, has fly sound - } + if(trg) + rocket.think = racer_rocket_tracker; else - { - */ - rocket.cnt = time + 9; - rocket.velocity = v_forward * autocvar_g_vehicle_racer_rocket_speed; - rocket.think = racer_rocket_groundhugger; - rocket.nextthink = time; - CSQCProjectile(rocket, TRUE, PROJECTILE_ROCKET, TRUE); - //} + rocket.think = racer_rocket_groundhugger; } -float racer_customizeentityforclient() -{ - - if(self.deadflag == DEAD_DEAD) - return FALSE; - - /* - if(other == self.owner) - self.alpha = -1; - else - self.alpha = 1; - */ - - return TRUE; -} - -float racer_pplug() +float racer_frame() { entity player, racer; - float ftmp, ftmp2; vector df; - - if(autocvar_g_vehicle_racer_reload) - { - racer_loadsettings(); - cvar_set("g_vehicle_racer_reload","0"); - } - - player = self; - racer = self.vehicle; - - player.BUTTON_ZOOM = 0; - player.BUTTON_CROUCH = 0; - - self = racer; - - if(player.BUTTON_USE) - { - self = racer; - racer_exit(0); - self = player; - return 0; - } - + float ftmp; + + if(intermission_running) + return 1; + + player = self; + racer = self.vehicle; + self = racer; + + player.BUTTON_ZOOM = player.BUTTON_CROUCH = 0; + + vehicles_painframe(); + if(racer.deadflag != DEAD_NO) { self = player; @@ -387,66 +277,100 @@ float racer_pplug() return 1; } - racer_align4point(); - racer.angles_x *= -1; - makevectors(racer.angles); + crosshair_trace(player); - // Rotate Body - ftmp = racer_turnspeed * sys_frametime; - ftmp2 = ftmp * -1; + racer.angles_x *= -1; - ftmp = bound(ftmp2, shortangle_f(player.v_angle_y - racer.angles_y, racer.angles_y), ftmp); - ftmp2 = anglemods(racer.angles_y + ftmp); + // Yaw + ftmp = autocvar_g_vehicle_racer_turnspeed * frametime; + ftmp = bound(-ftmp, shortangle_f(player.v_angle_y - racer.angles_y, racer.angles_y), ftmp); + racer.angles_y = anglemods(racer.angles_y + ftmp); // Roll - ftmp = bound(-45, shortangle_f(player.v_angle_z + ((racer.angles_y - ftmp2) * racer_turnroll), racer.angles_z), 45); - ftmp = anglemods(racer.angles_z + ftmp); - racer.angles_z = bound(-85, ftmp, 85); + racer.angles_z += -ftmp * autocvar_g_vehicle_racer_turnroll * frametime; - // Turn - racer.angles_y = ftmp2; + // Pitch + ftmp = autocvar_g_vehicle_racer_pitchspeed * frametime; + ftmp = bound(-ftmp, shortangle_f(player.v_angle_x - racer.angles_x, racer.angles_x), ftmp); + racer.angles_x = bound(-30, anglemods(racer.angles_x + ftmp), 30); - // Pitch Body - ftmp = racer_pitchspeed * sys_frametime; - ftmp2 = ftmp * -1; - - ftmp = bound(ftmp2,shortangle_f(player.v_angle_x - racer.angles_x,racer.angles_x),ftmp); - racer.angles_x = anglemods(racer.angles_x + ftmp); + makevectors(racer.angles); racer.angles_x *= -1; - df = racer.velocity * -0.5; + + ftmp = racer.velocity_z; + df = racer.velocity * -autocvar_g_vehicle_racer_friction; + racer.velocity_z = ftmp; if(player.movement_x != 0) { if(player.movement_x > 0) - df += v_forward * racer_speed_forward; + df += v_forward * autocvar_g_vehicle_racer_speed_forward; else if(player.movement_x < 0) - df -= v_forward * racer_speed_forward; + df -= v_forward * autocvar_g_vehicle_racer_speed_forward; } if(player.movement_y != 0) { if(player.movement_y < 0) - df -= v_right * racer_speed_strafe; + df -= v_right * autocvar_g_vehicle_racer_speed_strafe; else if(player.movement_y > 0) - df += v_right * racer_speed_strafe; + df += v_right * autocvar_g_vehicle_racer_speed_strafe; } - - // limit _z to avoid flying on normal thrust - if(df_z > 0) - df_z = min(df_z,700); - - + + if(vlen(player.movement) != 0) + { + if(self.sound_nexttime < time || self.sounds != 1) + { + self.sounds = 1; + self.sound_nexttime = time + 10.922667; //soundlength("vehicles/racer_move.wav"); + sound (self, CH_TRIGGER_SINGLE, "vehicles/racer_move.wav", VOL_VEHICLEENGINE, ATTN_NORM); + } + } + else + { + if(self.sound_nexttime < time || self.sounds != 0) + { + self.sounds = 0; + self.sound_nexttime = time + 11.888604; //soundlength("vehicles/racer_idle.wav"); + sound (self, CH_TRIGGER_SINGLE, "vehicles/racer_idle.wav", VOL_VEHICLEENGINE, ATTN_NORM); + } + } + // Afterburn - if (player.BUTTON_JUMP) - if(racer.vehicle_energy >= (racer_afterburn_cost * frametime)) + if (player.BUTTON_JUMP && racer.vehicle_energy >= (autocvar_g_vehicle_racer_afterburn_cost * frametime)) { - racer.wait = time + autocvar_g_vehicle_racer_energy_usepause; - racer.vehicle_energy -= racer_afterburn_cost * frametime; + if(time - racer.wait > 0.2) + pointparticles(particleeffectnum("wakizashi_booster_smoke"), self.origin, '0 0 0', 1); + + racer.wait = time; + racer.vehicle_energy -= autocvar_g_vehicle_racer_afterburn_cost * frametime; df += (v_forward * autocvar_g_vehicle_racer_speed_afterburn); + + if(self.invincible_finished < time) + { + traceline(self.origin, self.origin - '0 0 256', MOVE_NORMAL, self); + if(trace_fraction != 1.0) + pointparticles(particleeffectnum("smoke_small"), trace_endpos, '0 0 0', 1); + + self.invincible_finished = time + 0.1 + (random() * 0.1); + } + + if(self.strength_finished < time) + { + //self.sounds = 2; + self.strength_finished = time + 10.922667; //soundlength("vehicles/racer_boost.wav"); + sound (self.tur_head, CH_TRIGGER_SINGLE, "vehicles/racer_boost.wav", VOL_VEHICLEENGINE, ATTN_NORM); + } + } + else + { + self.strength_finished = 0; + sound (self.tur_head, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_VEHICLEENGINE, ATTN_NORM); } + racer.velocity += df * frametime; @@ -454,23 +378,14 @@ float racer_pplug() racer.velocity = racer.velocity - df; player.movement = racer.velocity; - /* - // for homing rockets - // FIXME this uses prydon cursor - if(self.owner.cursor_trace_ent) - { - self.tur_head.gun1 = self.owner.cursor_trace_ent; - self.tur_head.cnt = time + 1; - } - */ - if(player.BUTTON_ATCK) if(time > racer.attack_finished_single) - if(racer.vehicle_energy >= autocvar_g_vehicle_racer_laser_cost) + if(racer.vehicle_energy >= autocvar_g_vehicle_racer_cannon_cost) { - racer.vehicle_energy -= autocvar_g_vehicle_racer_laser_cost; - racer.wait = time + autocvar_g_vehicle_racer_energy_usepause; + racer.vehicle_energy -= autocvar_g_vehicle_racer_cannon_cost; + racer.wait = time; + crosshair_trace(player); if(racer.cnt) { racer_fire_cannon("tag_fire1"); @@ -481,418 +396,296 @@ float racer_pplug() racer_fire_cannon("tag_fire2"); racer.cnt = 1; } - racer.attack_finished_single = time + autocvar_g_vehicle_racer_laser_refire; + racer.attack_finished_single = time + autocvar_g_vehicle_racer_cannon_refire; + //self.owner.vehicle_energy = racer.vehicle_energy / autocvar_g_vehicle_racer_energy; } - if(player.BUTTON_ATCK2) - if(time > racer.delay) + if(autocvar_g_vehicle_racer_rocket_locktarget) { - racer_fire_rocket("tag_rocket_r"); - racer_fire_rocket("tag_rocket_l"); - racer.delay = time + autocvar_g_vehicle_racer_rocket_refire; - racer.lip = time; + vehicles_locktarget((1 / autocvar_g_vehicle_racer_rocket_locking_time) * frametime, + (1 / autocvar_g_vehicle_racer_rocket_locking_releasetime) * frametime, + autocvar_g_vehicle_racer_rocket_locked_time); + if(self.lock_target) + { + if(racer.lock_strength == 1) + UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '1 0 0', 0); + else if(self.lock_strength > 0.5) + UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '0 1 0', 0); + else if(self.lock_strength < 0.5) + UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '0 0 1', 0); + } } - player.vehicle_reload1 = (time - racer.lip) / (racer.delay-racer.lip); - vehicle_stdproc_shiledregen(racer_shieldmax, frametime); - vehicle_stdproc_healthregen(racer_healthmax, frametime); - - if (racer.wait < time) - vehicle_stdproc_energyregen(racer_energymax, frametime); - else - player.vehicle_energy = (racer.vehicle_energy / racer_energymax); - - self = player; + if(time > racer.delay) + if(player.BUTTON_ATCK2) + { + self.misc_bulletcounter += 1; + racer.delay = time + 0.3; + if(self.misc_bulletcounter == 1) + racer_fire_rocket("tag_rocket_r", (self.lock_strength == 1 && self.lock_target) ? self.lock_target : world); + else if(self.misc_bulletcounter == 2) + { + racer_fire_rocket("tag_rocket_l", (self.lock_strength == 1 && self.lock_target) ? self.lock_target : world); + self.lock_strength = 0; + self.lock_target = world; + self.misc_bulletcounter = 0; - player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0; - setorigin(player,racer.origin + '0 0 32'); - player.velocity = racer.velocity; + racer.delay = time + autocvar_g_vehicle_racer_rocket_refire; + racer.lip = time; + } + } + player.vehicle_reload1 = bound(0, 100 * ((time - racer.lip) / (racer.delay - racer.lip)), 100); - return 1; -} + if(self.vehicle_flags & VHF_SHIELDREGEN) + vehicles_regen(dmg_time, vehicle_shield, autocvar_g_vehicle_racer_shield, autocvar_g_vehicle_racer_shield_regen_pause, autocvar_g_vehicle_racer_shield_regen, frametime); -void racer_exitthink() -{ - float a, b, c; + if(self.vehicle_flags & VHF_HEALTHREGEN) + vehicles_regen(dmg_time, vehicle_health, autocvar_g_vehicle_racer_health, autocvar_g_vehicle_racer_health_regen_pause, autocvar_g_vehicle_racer_health_regen, frametime); - self.nextthink = time; + if(self.vehicle_flags & VHF_ENERGYREGEN) + vehicles_regen(wait, vehicle_energy, autocvar_g_vehicle_racer_energy, autocvar_g_vehicle_racer_energy_regen_pause, autocvar_g_vehicle_racer_energy_regen, frametime); - a = racer_anglestabilizer; - b = racer_springlength; - c = racer_power_solid; - racer_anglestabilizer = 36; - racer_springlength = 96; - racer_power_solid = 300; + VEHICLE_UPDATE_PLAYER(health, racer); + VEHICLE_UPDATE_PLAYER(energy, racer); - racer_align4point(); + if(self.vehicle_flags & VHF_HASSHIELD) + VEHICLE_UPDATE_PLAYER(shield, racer); - if(self.velocity_z < 0) - self.velocity_z *= 0.95; - racer_anglestabilizer = a; - racer_springlength = b; - racer_power_solid = c; + player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0; + setorigin(player,racer.origin + '0 0 32'); + player.velocity = racer.velocity; - self.velocity_x *= 0.95; - self.velocity_y *= 0.95; + self = player; + return 1; } -void racer_spawnthink() +void racer_think() { - float a, b, c; - vector dorg; - - self.nextthink = time; - - a = racer_anglestabilizer; - b = racer_springlength; - c = racer_power_solid; - - racer_anglestabilizer = 36; - racer_springlength = 96; - racer_power_solid = 300; - - // self.velocity_z += sin(time * 128) * 4; - - racer_align4point(); + /* + float a, b, c;a = autocvar_g_vehicle_racer_anglestabilizer; + b = autocvar_g_vehicle_racer_springlength; + c = autocvar_g_vehicle_racer_hoverpower; - if(self.velocity_z < 0) - self.velocity_z *= 0.98; + autocvar_g_vehicle_racer_anglestabilizer = 36; + autocvar_g_vehicle_racer_springlength = 96; + autocvar_g_vehicle_racer_hoverpower = 300; + */ - racer_anglestabilizer = a; - racer_springlength = b; - racer_power_solid = c; + racer_align4point(); //time - self.nextthink); - self.velocity_x *= 0.95; - self.velocity_y *= 0.95; + /* + //if(self.velocity_z > 0) + // self.velocity_z *= 0.95; - dorg = self.pos1 - self.origin ; + autocvar_g_vehicle_racer_anglestabilizer = a; + autocvar_g_vehicle_racer_springlength = b; + autocvar_g_vehicle_racer_hoverpower = c; + */ - self.velocity_x = bound(-32, self.velocity_x + dorg_x, 32); - self.velocity_y = bound(-32, self.velocity_y + dorg_y, 32); + self.velocity_x *= 0.9; + self.velocity_y *= 0.9; + self.velocity_z *= 0.8; + self.velocity_z += sin(time * 2) * 16; + self.nextthink = time; // + 0.05; } void racer_enter() { - self.owner = other; - - - self.nextthink = 0; - self.flags = 0; - self.vehicle_hudmodel.viewmodelforclient = self.owner; - self.colormap = self.owner.colormap; - - self.owner.PlayerPhysplug = racer_pplug; - self.owner.takedamage = DAMAGE_NO; - self.owner.event_damage = SUB_Null; - self.owner.vehicle = self; - self.owner.angles = self.angles; - self.owner.solid = SOLID_NOT; - self.owner.movetype = MOVETYPE_NOCLIP; - self.owner.alpha = -1; - self.owner.hud = HUD_WAKIZASHI; - self.owner.effects |= EF_NODRAW; - self.owner.view_ofs = '0 0 0'; - - self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_racer_health); - self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_racer_shield); - - setorigin(other,self.origin + '0 0 32'); - other.velocity = self.velocity; - - other.flags &~= FL_ONGROUND; - msg_entity = other; - WriteByte (MSG_ONE, SVC_SETVIEWPORT); - WriteEntity( MSG_ONE, self.vehicle_viewport); - - WriteByte (MSG_ONE, SVC_SETVIEWANGLES); // 10 = SVC_SETVIEWANGLES - WriteAngle(MSG_ONE, self.angles_x * -1); // tilt - WriteAngle(MSG_ONE, self.angles_y); // yaw - WriteAngle(MSG_ONE, 0); // roll -} - -void racer_spawn(); -void racer_return() -{ - pointparticles(particleeffectnum("teleport"), self.enemy.origin + '0 0 64', '0 0 0', 1); - self.enemy.think = racer_spawn; - self.enemy.nextthink = time; - remove(self); + self.movetype = MOVETYPE_BOUNCE; + self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_racer_health) * 100; + self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_racer_shield) * 100; + + if(self.owner.flagcarried) + setorigin(self.owner.flagcarried, '-190 0 96'); } void racer_exit(float eject) { - self.colormap = 1024; - self.flags = FL_NOTARGET; - + vector spot; + + self.think = racer_think; + self.nextthink = time; + self.movetype = MOVETYPE_TOSS; + sound (self.tur_head, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_VEHICLEENGINE, ATTN_NORM); + if not (self.owner) return; - msg_entity = self.owner; - WriteByte (MSG_ONE, SVC_SETVIEWPORT); - WriteEntity( MSG_ONE, self.owner); - - WriteByte (MSG_ONE, SVC_SETVIEWANGLES); // 10 = SVC_SETVIEWANGLES - WriteAngle(MSG_ONE, 0); // tilt - WriteAngle(MSG_ONE, self.angles_y); // yaw - WriteAngle(MSG_ONE, 0); // roll - - if (self.deadflag == DEAD_NO) - { - self.think = racer_exitthink; - self.nextthink = time; - } - - self.owner.takedamage = DAMAGE_AIM; - self.owner.solid = SOLID_SLIDEBOX; - self.owner.movetype = MOVETYPE_WALK; - - setsize(self.owner,PL_MIN,PL_MAX); - - self.owner.effects &~= EF_NODRAW; - self.owner.alpha = 1; - self.owner.PlayerPhysplug = SUB_Null; - self.owner.vehicle = world; - self.owner.view_ofs = PL_VIEW_OFS; - self.owner.event_damage = PlayerDamage; - self.owner.hud = HUD_NORMAL; - - self.vehicle_hudmodel.viewmodelforclient = self; - + makevectors(self.angles); if(eject) { - makevectors(self.angles); - setorigin(self.owner,self.origin + v_forward * 100); + spot = self.origin + v_forward * 100 + '0 0 64'; + spot = vehicles_findgoodexit(spot); + setorigin(self.owner , spot); self.owner.velocity = (v_up + v_forward * 0.25) * 750; } else { - self.owner.velocity = (v_forward) * -150; - setorigin(self.owner,self.origin - v_forward * 128); + spot = self.origin - v_forward * 200 + '0 0 64'; + spot = vehicles_findgoodexit(spot); + setorigin(self.owner , spot); } - + self.owner = world; - - if (self.deadflag != DEAD_NO) - { - entity ret; - ret = spawn(); - ret.enemy = self; - ret.think = racer_return; - ret.nextthink = time + autocvar_g_vehicle_racer_respawntime; - } } - -void racer_touch() +void racer_impact() { - if(self.owner) - { - if(vlen(self.velocity) == 0) - return; - - if(other.classname != "player") - return; - - vector a; - a = normalize(other.origin - self.origin); - a = a - normalize(self.velocity); - - return; - } - - if(other.classname != "player") - return; - - if(other.deadflag != DEAD_NO) - return; - - if(other.vehicle != world) - return; - - racer_enter(); + if(autocvar_g_vehicle_racer_bouncepain_x) + vehilces_impact(autocvar_g_vehicle_racer_bouncepain_x, autocvar_g_vehicle_racer_bouncepain_y, autocvar_g_vehicle_racer_bouncepain_z); } void racer_spawn() { - self.think = racer_spawnthink; - self.nextthink = time; - - self.flags = FL_NOTARGET; - self.effects = 0; - - self.vehicle_health = racer_healthmax; - self.vehicle_shield = racer_shieldmax; - - self.event_damage = vehicle_stdproc_damage; - self.touch = racer_touch; - - self.iscreature = TRUE; - self.scale = 0.5; - self.movetype = MOVETYPE_FLY; - self.solid = SOLID_SLIDEBOX; - self.takedamage = DAMAGE_AIM; - - self.alpha = 1; - self.colormap = 1024; - self.deadflag = DEAD_NO; - self.bot_attack = TRUE; - - self.vehicle_energy = 1; - self.vehicle_hudmodel.viewmodelforclient = self; - - setorigin(self, self.pos1); - self.angles = self.pos2; - - setsize(self,RACER_MIN * 0.5,RACER_MAX * 0.5); - pointparticles(particleeffectnum("teleport"), self.origin + '0 0 64', '0 0 0', 1); - self.delay = time; + self.think = racer_think; + self.nextthink = time; + self.vehicle_health = autocvar_g_vehicle_racer_health; + self.vehicle_shield = autocvar_g_vehicle_racer_shield; + + self.movetype = MOVETYPE_TOSS; + self.solid = SOLID_SLIDEBOX; + self.delay = time; + self.scale = 0.5; + + setsize(self, RACER_MIN * 0.5, RACER_MAX * 0.5); + self.bouncefactor = autocvar_g_vehicle_racer_bouncefactor; + self.bouncestop = autocvar_g_vehicle_racer_bouncestop; + self.vehicle_impact = racer_impact; + //self.destvec = autocvar_g_vehicle_racer_bouncepain; } void racer_blowup() { - - sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); - pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1); - self.deadflag = DEAD_DEAD; self.vehicle_exit(VHEF_NORMAL); - RadiusDamage (self, self, 250, 15, 250, world, 250, DEATH_WAKIBLOWUP, world); - self.alpha = -1; + RadiusDamage (self, self, autocvar_g_vehicle_racer_blowup_coredamage, + autocvar_g_vehicle_racer_blowup_edgedamage, + autocvar_g_vehicle_racer_blowup_radius, world, + autocvar_g_vehicle_racer_blowup_forceintensity, + DEATH_WAKIBLOWUP, world); + self.nextthink = time + autocvar_g_vehicle_racer_respawntime; self.think = racer_spawn; self.movetype = MOVETYPE_NONE; self.effects = EF_NODRAW; - self.avelocity_z = 0; - self.colormod = '0 0 0'; + self.colormod = '0 0 0'; + self.avelocity = '0 0 0'; + self.velocity = '0 0 0'; - setorigin(self,self.pos1); + setorigin(self, self.pos1); + self.think = racer_spawn; + self.nextthink = time + autocvar_g_vehicle_racer_respawntime; } -void racer_dietouch() +void racer_deadtouch() { - if(self.wait > time) - return; - - self.wait = time + 0.75; - - pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1); + self.avelocity_x *= 0.7; + self.cnt -= 1; + if(self.cnt <= 0) + racer_blowup(); } void racer_die() { self.health = 0; self.event_damage = SUB_Null; - self.iscreature = FALSE; - self.solid = SOLID_NOT; + self.solid = SOLID_CORPSE; self.takedamage = DAMAGE_NO; - self.touch = racer_dietouch; self.deadflag = DEAD_DYING; self.movetype = MOVETYPE_BOUNCE; - self.wait = time; - - pointparticles(particleeffectnum("rocket_explode"), findbetterlocation (self.origin, 16), '0 0 0', 1); - - self.velocity += '0 0 128'; + self.wait = time; + self.cnt = 1 + random() * 2; + self.touch = racer_deadtouch; + + pointparticles(particleeffectnum("explosion_medium"), self.origin, '0 0 0', 1); if(random() < 0.5) - self.avelocity_z = 16; + self.avelocity_z = 32; else - self.avelocity_z = -16; + self.avelocity_z = -32; - self.colormod = '-0.5 -0.5 -0.5'; + self.avelocity_x = -vlen(self.velocity) * 0.2; + self.velocity += '0 0 700'; + self.colormod = '-0.5 -0.5 -0.5'; self.think = racer_blowup; - self.nextthink = time + 3; + self.nextthink = 2 + time + random() * 3; } void racer_dinit() { + if not (vehicle_initialize( + "Wakizashi", + "models/vehicles/wakizashi.dpm", + "null", // we need this so tur_head is networked and usable for sounds + "models/vehicles/wakizashi_cockpit.dpm", + "", "", "tag_viewport", + HUD_WAKIZASHI, + 0.5 * RACER_MIN, 0.5 * RACER_MAX, + FALSE, + racer_spawn, autocvar_g_vehicle_racer_respawntime, + racer_frame, + racer_enter, racer_exit, + racer_die, racer_think, + TRUE)) + { + remove(self); + return; + } - tracebox(self.origin + '0 0 100', RACER_MIN * 0.5, RACER_MAX * 0.5, self.origin - '0 0 10000', MOVE_WORLDONLY, self); - setorigin(self,trace_endpos); - - if (self.netname == "") - self.netname = "Race PoD"; - - self.cvar_basename = "g_vehicle_racer"; - - self.vehicle_viewport = spawn(); - self.vehicle_hudmodel = spawn(); - //self.ccamera = spawn(); - - setorigin(self, self.origin); - - setmodel(self,"models/vehicles/wakizashi.dpm"); - setmodel(self.vehicle_hudmodel, "models/vehicles/wakizashi_cockpit.dpm"); - setmodel (self.vehicle_viewport, "null"); + if(autocvar_g_vehicle_racer_hovertype != 0) + racer_force_from_tag = vehicles_force_fromtag_maglev; + else + racer_force_from_tag = vehicles_force_fromtag_hover; + // FIXME: this be hakkz, fix the models insted (scale body, add tag_viewport to the hudmodel). + self.scale = 0.5; setattachment(self.vehicle_hudmodel, self, ""); setattachment(self.vehicle_viewport, self, "tag_viewport"); - self.vehicle_hudmodel.viewmodelforclient = self; - self.customizeentityforclient = racer_customizeentityforclient; - - self.tur_head = spawn(); - - self.pos1 = self.origin; - self.pos2 = self.angles; - self.angles = '0 0 0'; - self.angles = self.pos1; - - self.vehicle_die = racer_die; - self.vehicle_exit = racer_exit; - - addstat(STAT_HUD, AS_INT, hud); - addstat(STAT_VEHICLESTAT_HEALTH, AS_FLOAT, vehicle_health); - addstat(STAT_VEHICLESTAT_SHIELD, AS_FLOAT, vehicle_shield); - addstat(STAT_VEHICLESTAT_ENERGY, AS_FLOAT, vehicle_energy); - - addstat(STAT_VEHICLESTAT_AMMO1, AS_INT, vehicle_ammo1); - addstat(STAT_VEHICLESTAT_RELOAD1, AS_FLOAT, vehicle_reload1); - - addstat(STAT_VEHICLESTAT_AMMO2, AS_INT, vehicle_ammo2); - addstat(STAT_VEHICLESTAT_RELOAD2, AS_FLOAT, vehicle_reload2); - - racer_spawn(); + self.mass = 900; } void spawnfunc_vehicle_racer() { - g_turrets_common_precash(); - racer_loadsettings(); + self.vehicle_flags |= VHF_DMGSHAKE; + self.vehicle_flags |= VHF_DMGROLL; - self.vehicle_flags = VHF_HASSHIELD | VHF_SHIELDREGEN; - - /* - traceline(self.origin,self.origin - '0 0 2048',MOVE_WORLDONLY,self); - if(trace_startsolid) - { - dprint("WARNING: vehicle_racer placed in solid\n"); - traceline(self.origin + '0 0 512' ,self.origin - '0 0 2048',MOVE_WORLDONLY,self); - if(trace_startsolid || trace_fraction == 1.0) - { - dprint("ERROR: vehicle_racer placed in more then 512 units into solid\n"); - remove(self); - return; - } - } - */ - - if(trace_fraction != 1.0) - setorigin(self,trace_endpos + '0 0 128'); - else - dprint("WARNING: vehicle_racer placed more then 2048 units above ground.\n"); + precache_sound ("weapons/lasergun_fire.wav"); + precache_sound ("weapons/rocket_fire.wav"); + + precache_sound ("vehicles/racer_idle.wav"); + precache_sound ("vehicles/racer_move.wav"); + precache_sound ("vehicles/racer_boost.wav"); + precache_model ("models/vhshield.md3"); precache_model ("models/vehicles/wakizashi.dpm"); precache_model ("models/vehicles/wakizashi_cockpit.dpm"); - precache_model ("maps/bspmodel.bsp"); + vehicles_configcheck("vehicle_racer.cfg", autocvar_g_vehicle_racer_health); + if(autocvar_g_vehicle_racer_energy) + if(autocvar_g_vehicle_racer_energy_regen) + self.vehicle_flags |= VHF_ENERGYREGEN; + + if(autocvar_g_vehicle_racer_shield) + self.vehicle_flags |= VHF_HASSHIELD; + + if(autocvar_g_vehicle_racer_shield_regen) + self.vehicle_flags |= VHF_SHIELDREGEN; + + if(autocvar_g_vehicle_racer_health_regen) + self.vehicle_flags |= VHF_HEALTHREGEN; self.think = racer_dinit; - self.nextthink = time + 1; + + if(g_assault) + self.nextthink = time + 0.5; + else + self.nextthink = time + (autocvar_g_vehicles_delayspawn ? autocvar_g_vehicle_racer_respawntime + (random() * autocvar_g_vehicles_delayspawn_jitter) : 0.5); } +#endif // SVQC diff --git a/qcsrc/server/vehicles/raptor.qc b/qcsrc/server/vehicles/raptor.qc index 38ebad0427..9e80f1869d 100644 --- a/qcsrc/server/vehicles/raptor.qc +++ b/qcsrc/server/vehicles/raptor.qc @@ -1,815 +1,708 @@ -#define RAPTOR_MIN '-40 -40 0' -#define RAPTOR_MAX '40 40 40' - -float raptor_movestyle; -float raptor_turnspeed; -float raptor_turnroll; -float raptor_pitchspeed; -float raptor_speed_forward; -float raptor_speed_strafe; -float raptor_speed_up; -float raptor_speed_down; - -float raptor_bomblet_waves; -float raptor_bomblet_wavefirst; -float raptor_bomblet_wavenext; -float raptor_bomblet_wawespread; -float raptor_bomblets; -float raptor_bomblet_damage; -float raptor_bomblet_edgedamage; -float raptor_bomblet_radius; -float raptor_bomblet_force; -float raptor_bombs_refire; - -float raptor_beam_dps; -float raptor_beam_fops; -float raptor_beam_aps; -float raptor_beam_size; -float raptor_beam_leangth; -float raptor_beam_refire; - -float raptor_shield_max; -float raptor_shield_regen; - -float raptor_health_max; -float raptor_health_regen; - -float raptor_energy_max; -float raptor_energy_regen; +#ifdef SVQC +#define RAPTOR_MIN '-80 -80 0' +#define RAPTOR_MAX '80 80 70' + +float autocvar_g_vehicle_raptor_respawntime; + +float autocvar_g_vehicle_raptor_movestyle; +float autocvar_g_vehicle_raptor_turnspeed; +float autocvar_g_vehicle_raptor_pitchspeed; +float autocvar_g_vehicle_raptor_pitchlimit; + +float autocvar_g_vehicle_raptor_speed_forward; +float autocvar_g_vehicle_raptor_speed_strafe; +float autocvar_g_vehicle_raptor_speed_up; +float autocvar_g_vehicle_raptor_speed_down; +float autocvar_g_vehicle_raptor_friction; + +float autocvar_g_vehicle_raptor_bomblets; +float autocvar_g_vehicle_raptor_bomblet_alt; +float autocvar_g_vehicle_raptor_bomblet_time; +float autocvar_g_vehicle_raptor_bomblet_damage; +float autocvar_g_vehicle_raptor_bomblet_spread; +float autocvar_g_vehicle_raptor_bomblet_edgedamage; +float autocvar_g_vehicle_raptor_bomblet_radius; +float autocvar_g_vehicle_raptor_bomblet_force; +float autocvar_g_vehicle_raptor_bomblet_explode_delay; +float autocvar_g_vehicle_raptor_bombs_refire; + +float autocvar_g_vehicle_raptor_cannon_turnspeed; +float autocvar_g_vehicle_raptor_cannon_turnlimit; +float autocvar_g_vehicle_raptor_cannon_pitchlimit_up; +float autocvar_g_vehicle_raptor_cannon_pitchlimit_down; + +float autocvar_g_vehicle_raptor_cannon_locktarget; +float autocvar_g_vehicle_raptor_cannon_locking_time; +float autocvar_g_vehicle_raptor_cannon_locking_releasetime; +float autocvar_g_vehicle_raptor_cannon_locked_time; +float autocvar_g_vehicle_raptor_cannon_predicttarget; + +float autocvar_g_vehicle_raptor_cannon_cost; +float autocvar_g_vehicle_raptor_cannon_damage; +float autocvar_g_vehicle_raptor_cannon_radius; +float autocvar_g_vehicle_raptor_cannon_refire; +float autocvar_g_vehicle_raptor_cannon_speed; +float autocvar_g_vehicle_raptor_cannon_spread; +float autocvar_g_vehicle_raptor_cannon_force; + +float autocvar_g_vehicle_raptor_energy; +float autocvar_g_vehicle_raptor_energy_regen; +float autocvar_g_vehicle_raptor_energy_regen_pause; + +float autocvar_g_vehicle_raptor_health; +float autocvar_g_vehicle_raptor_health_regen; +float autocvar_g_vehicle_raptor_health_regen_pause; + +float autocvar_g_vehicle_raptor_shield; +float autocvar_g_vehicle_raptor_shield_regen; +float autocvar_g_vehicle_raptor_shield_regen_pause; + +float autocvar_g_vehicle_raptor_bouncefactor; +float autocvar_g_vehicle_raptor_bouncestop; +vector autocvar_g_vehicle_raptor_bouncepain; void raptor_spawn(); -void raptor_return(); -float raptor_pplug(); +float raptor_frame(); float raptor_takeoff(); -float raptor_land(); .entity bomb1; .entity bomb2; float raptor_altitude(float amax) { - tracebox(self.origin, self.mins, self.maxs, '0 0 -1' * amax, TRUE, self); - if(trace_fraction == 1) - return amax+1; - else - return vlen(self.origin - trace_endpos); + tracebox(self.origin, self.mins, self.maxs, self.origin - ('0 0 1' * amax), MOVE_WORLDONLY, self); + return vlen(self.origin - trace_endpos); } -void raptor_loadsettings() -{ - raptor_movestyle = CCVAR("_movestyle"); - raptor_turnspeed = CCVAR("_turnspeed"); - raptor_turnroll = CCVAR("_turnroll"); - raptor_pitchspeed = CCVAR("_pitchspeed"); - raptor_speed_forward = CCVAR("_speed_forward"); - raptor_speed_strafe = CCVAR("_speed_strafe"); - raptor_speed_up = CCVAR("_speed_up"); - raptor_speed_down = CCVAR("_speed_down"); - - raptor_bomblet_waves = CCVAR("_bomblet_waves "); - raptor_bomblet_wavefirst = CCVAR("_bomblet_wavefirst"); - raptor_bomblet_wavenext = CCVAR("_bomblet_wavenext"); - raptor_bomblet_wawespread = CCVAR("_bomblet_wawespread"); - raptor_bomblets = CCVAR("_bomblets"); - raptor_bomblet_damage = CCVAR("_bomblet_damage"); - raptor_bomblet_edgedamage = CCVAR("_bomblet_edgedamage"); - raptor_bomblet_radius = CCVAR("_bomblet_radius"); - raptor_bomblet_force = CCVAR("_bomblet_force "); - raptor_bombs_refire = CCVAR("_bombs_refire"); - - raptor_beam_dps = CCVAR("_beam_dps"); - raptor_beam_fops = CCVAR("_beam_fops"); - raptor_beam_aps = CCVAR("_beam_aps"); - raptor_beam_size = CCVAR("_beam_size"); - raptor_beam_leangth = CCVAR("_beam_length"); - raptor_beam_refire = CCVAR("_beam_refire"); - - raptor_shield_max = CCVAR("_shield"); - raptor_shield_regen = CCVAR("_shield_regen"); - - raptor_health_max = CCVAR("_health"); - raptor_health_regen = CCVAR("_health_regen"); - - raptor_energy_max = CCVAR("_energy"); - raptor_energy_regen = CCVAR("_energy_regen"); -} -void raptor_bombs_return() +void raptor_bomblet_boom() { - self.owner.bomb1.alpha = 1; - self.owner.bomb2.alpha = 1; + RadiusDamage (self, self.realowner, autocvar_g_vehicle_raptor_bomblet_damage, + autocvar_g_vehicle_raptor_bomblet_edgedamage, + autocvar_g_vehicle_raptor_bomblet_radius, world, + autocvar_g_vehicle_raptor_bomblet_force, DEATH_RAPTOR_BOMB, world); remove(self); } -void raptor_bomblet_boom() +void raptor_bomblet_touch() { - if(other.enemy == self.enemy) + if(other == self.owner) return; - pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1); - RadiusDamage (self, self.enemy, raptor_bomblet_damage, raptor_bomblet_edgedamage, raptor_bomblet_radius, world, raptor_bomblet_force, DEATH_SBROCKET, world); - remove(self); + PROJECTILE_TOUCH; + self.think = raptor_bomblet_boom; + self.nextthink = time + random() * autocvar_g_vehicle_raptor_bomblet_explode_delay; } void raptor_bomb_burst() { - self.angles = vectoangles(self.velocity); - - if(self.cnt < time) + if(self.cnt > time) + if(autocvar_g_vehicle_raptor_bomblet_alt) { - entity bomblet; - float i,v; - vector d; - - makevectors(self.angles); - v = vlen(self.velocity) + random(); - d = normalize(self.velocity); - pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1); - - for(i = 0; i < raptor_bomblets; ++i) - { - - bomblet = spawn(); - setorigin(bomblet,self.origin); - - setmodel(bomblet,"models/vehicles/raptor_bomb.dpm"); - bomblet.scale = 0.5; - - bomblet.owner = self.owner; - bomblet.enemy = self.enemy; - - bomblet.solid = SOLID_TRIGGER; - bomblet.movetype = MOVETYPE_BOUNCE; - bomblet.touch = raptor_bomblet_boom; - - bomblet.think = raptor_bomblet_boom; - bomblet.nextthink = time + 5; - - //bomblet.modelflags = MF_ROCKET; - bomblet.modelflags = MF_GRENADE; - - bomblet.velocity = normalize(d + randomvec() * raptor_bomblet_wawespread) * v; - - bomblet.angles = vectoangles(bomblet.velocity); - } - - self.wait -= 1; - if(self.wait <= 0) + self.nextthink = time; + traceline(self.origin, self.origin + (normalize(self.velocity) * autocvar_g_vehicle_raptor_bomblet_alt), MOVE_NORMAL, self); + if((trace_fraction == 1.0) || (vlen(self.origin - self.owner.origin) < autocvar_g_vehicle_raptor_bomblet_radius)) { - remove(self); + UpdateCSQCProjectile(self); return; } - - self.cnt = time + raptor_bomblet_wavenext; } - self.nextthink = time; -} + entity bomblet; + float i; -void raptor_bomb_touch() -{ - raptor_bomb_burst(); + Damage_DamageInfo(self.origin, 0, 0, 0, '0 0 0', DEATH_RAPTOR_BOMB_SPLIT, self); + + for(i = 0; i < autocvar_g_vehicle_raptor_bomblets; ++i) + { + bomblet = spawn(); + setorigin(bomblet, self.origin); + + bomblet.movetype = MOVETYPE_TOSS; + bomblet.touch = raptor_bomblet_touch; + bomblet.think = raptor_bomblet_boom; + bomblet.nextthink = time + 5; + bomblet.owner = self.owner; + bomblet.realowner = self.realowner; + bomblet.velocity = normalize(normalize(self.velocity) + (randomvec() * autocvar_g_vehicle_raptor_bomblet_spread)) * vlen(self.velocity); + + PROJECTILE_MAKETRIGGER(bomblet); + CSQCProjectile(bomblet, TRUE, PROJECTILE_RAPTORBOMBLET, TRUE); + } + + remove(self); } void raptor_bombdrop() { entity bomb_1, bomb_2; - self.bomb1.alpha = 0.25; - self.bomb2.alpha = 0.25; - bomb_1 = spawn(); bomb_2 = spawn(); - setmodel(bomb_1,"models/vehicles/raptor_bomb.dpm"); - setmodel(bomb_2,"models/vehicles/raptor_bomb.dpm"); - setorigin(bomb_1, gettaginfo(self, gettagindex(self, "bombmount_left"))); setorigin(bomb_2, gettaginfo(self, gettagindex(self, "bombmount_right"))); - bomb_1.movetype = bomb_2.movetype = MOVETYPE_TOSS; - bomb_1.velocity = bomb_2.velocity = self.velocity; - bomb_1.touch = bomb_2.touch = raptor_bomb_touch; - bomb_1.think = bomb_2.think = raptor_bomb_burst; - bomb_1.nextthink = bomb_2.nextthink = time; - bomb_1.cnt = bomb_2.cnt = time + raptor_bomblet_wavefirst; - bomb_1.wait = bomb_2.wait = raptor_bomblet_waves; - - bomb_1.avelocity = bomb_2.avelocity = '0 0 180'; - bomb_1.owner = bomb_2.owner = self; - bomb_1.enemy = bomb_2.enemy = self.owner; - bomb_1.angles = bomb_2.angles = self.angles; + bomb_1.movetype = bomb_2.movetype = MOVETYPE_BOUNCE; + bomb_1.velocity = bomb_2.velocity = self.velocity; + bomb_1.touch = bomb_2.touch = raptor_bomb_burst; + bomb_1.think = bomb_2.think = raptor_bomb_burst; + bomb_1.cnt = bomb_2.cnt = time + 10; + + if(autocvar_g_vehicle_raptor_bomblet_alt) + bomb_1.nextthink = bomb_2.nextthink = time; + else + bomb_1.nextthink = bomb_2.nextthink = time + autocvar_g_vehicle_raptor_bomblet_time; + + bomb_1.owner = bomb_2.owner = self; + bomb_1.realowner = bomb_2.realowner = self.owner; bomb_1.solid = bomb_2.solid = SOLID_BBOX; + bomb_1.gravity = bomb_2.gravity = 1; - bomb_1 = spawn(); - bomb_1.owner = self; - bomb_1.think = raptor_bombs_return; - bomb_1.nextthink = time + raptor_bombs_refire; + PROJECTILE_MAKETRIGGER(bomb_1); + PROJECTILE_MAKETRIGGER(bomb_2); + + CSQCProjectile(bomb_1, TRUE, PROJECTILE_RAPTORBOMB, TRUE); + CSQCProjectile(bomb_2, TRUE, PROJECTILE_RAPTORBOMB, TRUE); } -void raptor_animator_think() + +void raptor_fire_cannon(entity gun, string tagname) { - self.owner.frame += 1; - if(self.owner.frame == self.cnt) - remove(self); - else - self.nextthink = time + self.wait; + vehicles_projectile("raptor_cannon_muzzleflash", "weapons/lasergun_fire.wav", + gettaginfo(gun, gettagindex(gun, tagname)), normalize(v_forward + randomvec() * autocvar_g_vehicle_raptor_cannon_spread) * autocvar_g_vehicle_raptor_cannon_speed, + autocvar_g_vehicle_raptor_cannon_damage, autocvar_g_vehicle_raptor_cannon_radius, autocvar_g_vehicle_raptor_cannon_force, 0, + DEATH_RAPTOR_CANNON, PROJECTILE_RAPTORCANNON, 0, TRUE, TRUE); } -void raptor_setanim(float start, float end, float length) +void raptor_think() { - entity ani; - if(self.tur_head.enemy) - ani = self.tur_head.enemy; - else - ani = spawn(); - - self.tur_head.enemy = ani; - ani.owner = self; - self.frame = start; - ani.cnt = end; - ani.wait = sys_frametime / length; - ani.think = raptor_animator_think; - ani.nextthink = time + ani.wait; } -void raptor_beam (vector start, vector end, vector smin, vector smax, float bforce, float f_dmg, float deathtype) +void raptor_enter() { - vector hitloc, force, endpoint, dir; - entity ent; + self.owner.PlayerPhysplug = raptor_takeoff; + self.movetype = MOVETYPE_BOUNCEMISSILE; + self.solid = SOLID_SLIDEBOX; + self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_raptor_health) * 100; + self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_raptor_shield) * 100; + self.velocity_z = 1; // Nudge upwards to takeoff sequense can work. + self.tur_head.exteriormodeltoclient = self.owner; - dir = normalize(end - start); - force = dir * bforce; + self.delay = time + autocvar_g_vehicle_raptor_bombs_refire; + self.lip = time; - // go a little bit into the wall because we need to hit this wall later - end = end + dir; + if(self.owner.flagcarried) + setorigin(self.owner.flagcarried, '-20 0 96'); - // trace multiple times until we hit a wall, each obstacle will be made unsolid. - // note down which entities were hit so we can damage them later - while (1) - { - tracebox(start, smin, smax, end, FALSE, world); - - // if it is world we can't hurt it so stop now - if (trace_ent == world || trace_fraction == 1) - break; - - if (trace_ent.solid == SOLID_BSP) - break; +} - // make the entity non-solid so we can hit the next one - trace_ent.railgunhit = TRUE; - trace_ent.railgunhitloc = end; - trace_ent.railgunhitsolidbackup = trace_ent.solid; +void raptor_land() +{ + float hgt; + + hgt = raptor_altitude(512); + self.velocity = (self.velocity * 0.9) + ('0 0 -1800' * (hgt / 256) * sys_frametime); + self.angles_x *= 0.95; + self.angles_z *= 0.95; - // make the entity non-solid - trace_ent.solid = SOLID_NOT; - } + if(hgt < 128) + if(hgt > 0) + self.frame = (hgt / 128) * 25; - endpoint = trace_endpos; + self.bomb1.gun1.avelocity_y = 90 + ((self.frame / 25) * 2000); + self.bomb1.gun2.avelocity_y = -self.bomb1.gun1.avelocity_y; - // find all the entities the railgun hit and hurt them - ent = findchainfloat(railgunhit, TRUE); - while (ent) + if(hgt < 16) { - // get the details we need to call the damage function - ent.solid = ent.railgunhitsolidbackup; - hitloc = ent.railgunhitloc; - ent.railgunhitloc = '0 0 0'; - ent.railgunhitsolidbackup = SOLID_NOT; - ent.railgunhit = FALSE; - - // apply the damage - if (ent.takedamage) - Damage (ent, self, self, f_dmg, deathtype, hitloc, force); - - ent = ent.chain; + self.movetype = MOVETYPE_TOSS; + self.think = raptor_think; + self.frame = 0; } - trace_endpos = endpoint; -} - - -void raptor_enter() -{ - // Remove this when bots know how to use vehicles - if (clienttype(other) != CLIENTTYPE_REAL) - return; - - if(teams_matter) - if(self.team) - if(self.team != other.team) - return; - - self.owner = other; - self.switchweapon = other.switchweapon; - - self.event_damage = vehicle_stdproc_damage; - self.colormap = self.owner.colormap; - self.vehicle_hudmodel.viewmodelforclient = self.owner; - self.nextthink = 0; - self.owner.angles = self.angles; - self.owner.takedamage = DAMAGE_NO; - self.owner.solid = SOLID_NOT; - self.owner.movetype = MOVETYPE_NOCLIP; - self.owner.alpha = -1; - self.owner.PlayerPhysplug = raptor_takeoff; - self.owner.vehicle = self; - self.owner.event_damage = SUB_Null; - self.owner.hud = HUD_RAPTOR; - self.owner.vehicle_health = self.vehicle_health / raptor_health_max; - self.owner.vehicle_shield = self.vehicle_shield / raptor_shield_max; - self.owner.view_ofs = '0 0 1'; - self.owner.vehicle_ammo1 = self.vehicle_ammo1; - self.owner.vehicle_ammo2 = self.vehicle_ammo2; - self.owner.vehicle_reload1 = self.vehicle_reload1; - self.owner.vehicle_reload2 = self.vehicle_reload2; - - other.flags &~= FL_ONGROUND; - self.flags &~= FL_ONGROUND; - - self.frame = 0; - raptor_setanim(0, 25, 1); - - self.team = self.owner.team; - self.flags -= FL_NOTARGET; - self.velocity = '0 0 1'; - - setorigin(other,self.origin + '0 0 32'); - other.velocity = self.velocity; - - other.flags &~= FL_ONGROUND; - msg_entity = other; - WriteByte (MSG_ONE, SVC_SETVIEWPORT); - WriteEntity( MSG_ONE, self.vehicle_viewport); - - WriteByte (MSG_ONE, SVC_SETVIEWANGLES); // 10 = SVC_SETVIEWANGLES - WriteAngle(MSG_ONE, self.angles_x * -1); // tilt - WriteAngle(MSG_ONE, self.angles_y); // yaw - WriteAngle(MSG_ONE, 0); // roll + self.nextthink = time; } void raptor_exit(float eject) { - self.colormap = 1024; - self.flags = FL_NOTARGET; - - if not (self.owner) - return; - - msg_entity = self.owner; - WriteByte (MSG_ONE, SVC_SETVIEWPORT); - WriteEntity( MSG_ONE, self.owner); - - WriteByte (MSG_ONE, SVC_SETVIEWANGLES); // 10 = SVC_SETVIEWANGLES - WriteAngle(MSG_ONE, 0); // tilt - WriteAngle(MSG_ONE, self.angles_y); // yaw - WriteAngle(MSG_ONE, 0); // roll + vector spot; + self.tur_head.exteriormodeltoclient = world; - if (self.deadflag == DEAD_NO) + if(self.deadflag == DEAD_NO) { - //self.think = racer_exitthink; - self.nextthink = time; + self.think = raptor_land; + self.nextthink = time; } - self.owner.takedamage = DAMAGE_AIM; - self.owner.solid = SOLID_SLIDEBOX; - self.owner.movetype = MOVETYPE_WALK; - - setsize(self.owner,PL_MIN,PL_MAX); - - self.owner.effects &~= EF_NODRAW; - self.owner.alpha = 1; - self.owner.PlayerPhysplug = SUB_Null; - self.owner.vehicle = world; - self.owner.view_ofs = PL_VIEW_OFS; - self.owner.event_damage = PlayerDamage; - self.owner.hud = HUD_NORMAL; - //self.exteriormodeltoclient = self; - - self.vehicle_hudmodel.viewmodelforclient = self; + if not (self.owner) + return; + makevectors(self.angles); if(eject) { - makevectors(self.angles); - setorigin(self.owner,self.origin + v_forward * 100); + spot = self.origin + v_forward * 100 + '0 0 64'; + spot = vehicles_findgoodexit(spot); + setorigin(self.owner , spot); self.owner.velocity = (v_up + v_forward * 0.25) * 750; } else { - self.owner.velocity = (v_forward) * -150; - setorigin(self.owner,self.origin - v_forward * 128); + spot = self.origin - v_forward * 200 + '0 0 64'; + spot = vehicles_findgoodexit(spot); + setorigin(self.owner , spot); } - + self.owner = world; - - if (self.deadflag != DEAD_NO) - { - entity ret; - ret = spawn(); - ret.enemy = self; - ret.think = raptor_return; - ret.nextthink = time + autocvar_g_vehicle_racer_respawntime; - } } - -float raptor_pplug() +float raptor_takeoff() { - entity player, vhic; - float ftmp, ftmp2, energy_used; - vector df; - - - if(autocvar_g_vehicle_raptor_reload) - { - raptor_loadsettings(); - cvar_set("g_vehicle_raptor_reload","0"); - } - + entity player, raptor; + player = self; - vhic = self.vehicle; - self = vhic; - - if(player.BUTTON_USE) + raptor = self.vehicle; + self = raptor; + if(self.sound_nexttime < time) + { + self.sound_nexttime = time + 7.955812; //soundlength("vehicles/raptor_fly.wav"); + sound (self, CH_TRIGGER_SINGLE, "vehicles/raptor_speed.wav", VOL_VEHICLEENGINE, ATTN_NORM); + } + + // Takeoff sequense + if(raptor.frame < 25) { - self = vhic; - raptor_exit(0); - self = player; - return 0; - } + raptor.frame += 0.25; + raptor.velocity_z = min(raptor.velocity_z * 1.5, 256); + self.bomb1.gun1.avelocity_y = 90 + ((raptor.frame / 25) * 25000); + self.bomb1.gun2.avelocity_y = -self.bomb1.gun1.avelocity_y; + player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0; - if(vhic.deadflag != DEAD_NO) - { - self = player; - player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0; - return 1; + setorigin(player, raptor.origin + '0 0 32'); } + else + player.PlayerPhysplug = raptor_frame; + + if(self.vehicle_flags & VHF_SHIELDREGEN) + vehicles_regen(dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, frametime); - vhic.angles_x *= -1; - // Rotate Body - ftmp = raptor_turnspeed * sys_frametime; + if(self.vehicle_flags & VHF_HEALTHREGEN) + vehicles_regen(dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, frametime); - ftmp = bound(-ftmp, shortangle_f(player.v_angle_y - vhic.angles_y, vhic.angles_y), ftmp); + if(self.vehicle_flags & VHF_ENERGYREGEN) + vehicles_regen(cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, frametime); - // Roll - //ftmp = bound(-90,shortangle_f(player.v_angle_z + ((vhic.angles_y - ftmp2) * raptor_turnroll), vhic.angles_z),90); - //ftmp = safeangle(vhic.angles_z + ftmp); - //vhic.angles_z = ftmp; - // Turn - vhic.angles_y = anglemods(vhic.angles_y + ftmp); + raptor.bomb1.alpha = raptor.bomb2.alpha = (time - raptor.lip) / (raptor.delay - raptor.lip); + player.vehicle_reload2 = bound(0, raptor.bomb1.alpha * 100, 100); - // Pitch Body - ftmp = raptor_pitchspeed * sys_frametime; + VEHICLE_UPDATE_PLAYER(health, raptor); + VEHICLE_UPDATE_PLAYER(energy, raptor); + if(self.vehicle_flags & VHF_HASSHIELD) + VEHICLE_UPDATE_PLAYER(shield, raptor); - ftmp = bound(-ftmp, shortangle_f(player.v_angle_x - vhic.angles_x,vhic.angles_x), ftmp); + player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0; + self = player; + return 1; +} - vhic.angles_x = bound(-60,anglemods(vhic.angles_x + ftmp),60); - vhic.angles_x *= -1; +float raptor_frame() +{ + entity player, raptor; + float ftmp, ftmp2; + vector df; + + if(intermission_running) + return 1; - if(raptor_movestyle == 1) + player = self; + raptor = self.vehicle; + self = raptor; + vehicles_painframe(); + /* + ftmp = vlen(self.velocity); + if(ftmp > autocvar_g_vehicle_raptor_speed_forward) + ftmp = 1; + else + ftmp = ftmp / autocvar_g_vehicle_raptor_speed_forward; + */ + + if(self.sound_nexttime < time) + { + self.sound_nexttime = time + 7.955812; + //sound (self.tur_head, CH_TRIGGER_SINGLE, "vehicles/raptor_fly.wav", 1 - ftmp, ATTN_NORM ); + sound (self, CH_TRIGGER_SINGLE, "vehicles/raptor_speed.wav", 1, ATTN_NORM); + self.wait = ftmp; + } + /* + else if(fabs(ftmp - self.wait) > 0.2) { - ftmp = vhic.angles_z; - vhic.angles_z = 0; - ftmp2 = vhic.angles_x; - vhic.angles_x = 0; - fixedmakevectors(vhic.angles); - vhic.angles_z = ftmp; - vhic.angles_x = ftmp2; + sound (self.tur_head, CH_TRIGGER_SINGLE, "", 1 - ftmp, ATTN_NORM ); + sound (self, CH_TRIGGER_SINGLE, "", ftmp, ATTN_NORM); + self.wait = ftmp; + } + */ + + if(raptor.deadflag != DEAD_NO) + { + self = player; + player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0; + return 1; } + crosshair_trace(player); + + vector vang; + vang = raptor.angles; + df = vectoangles(normalize(trace_endpos - self.origin + '0 0 32')); + vang_x *= -1; + df_x *= -1; + if(df_x > 180) df_x -= 360; + if(df_x < -180) df_x += 360; + if(df_y > 180) df_y -= 360; + if(df_y < -180) df_y += 360; + + ftmp = shortangle_f(player.v_angle_y - vang_y, vang_y); + if(ftmp > 180) ftmp -= 360; if(ftmp < -180) ftmp += 360; + raptor.avelocity_y = bound(-autocvar_g_vehicle_raptor_turnspeed, ftmp + raptor.avelocity_y * 0.9, autocvar_g_vehicle_raptor_turnspeed); + + // Pitch + ftmp = 0; + if(player.movement_x > 0 && vang_x < autocvar_g_vehicle_raptor_pitchlimit) ftmp = 5; + else if(player.movement_x < 0 && vang_x > -autocvar_g_vehicle_raptor_pitchlimit) ftmp = -20; + + df_x = bound(-autocvar_g_vehicle_raptor_pitchlimit, df_x , autocvar_g_vehicle_raptor_pitchlimit); + ftmp = vang_x - bound(-autocvar_g_vehicle_raptor_pitchlimit, df_x + ftmp, autocvar_g_vehicle_raptor_pitchlimit); + raptor.avelocity_x = bound(-autocvar_g_vehicle_raptor_pitchspeed, ftmp + raptor.avelocity_x * 0.9, autocvar_g_vehicle_raptor_pitchspeed); + + raptor.angles_x = anglemods(raptor.angles_x); + raptor.angles_y = anglemods(raptor.angles_y); + raptor.angles_z = anglemods(raptor.angles_z); + + if(autocvar_g_vehicle_raptor_movestyle == 1) + makevectors('0 1 0' * raptor.angles_y); else - fixedmakevectors(vhic.angles); + makevectors(player.v_angle); - df = vhic.velocity * -1; + df = raptor.velocity * -autocvar_g_vehicle_raptor_friction; if(player.movement_x != 0) { if(player.movement_x > 0) - df += v_forward * raptor_speed_forward; + df += v_forward * autocvar_g_vehicle_raptor_speed_forward; else if(player.movement_x < 0) - df -= v_forward * raptor_speed_forward; + df -= v_forward * autocvar_g_vehicle_raptor_speed_forward; } if(player.movement_y != 0) { if(player.movement_y < 0) - df -= v_right * raptor_speed_strafe; + df -= v_right * autocvar_g_vehicle_raptor_speed_strafe; else if(player.movement_y > 0) - df += v_right * raptor_speed_strafe; + df += v_right * autocvar_g_vehicle_raptor_speed_strafe; - vhic.angles_z = bound(-30,vhic.angles_z + (player.movement_y / raptor_speed_strafe),30); + raptor.angles_z = bound(-30,raptor.angles_z + (player.movement_y / autocvar_g_vehicle_raptor_speed_strafe),30); } else { - vhic.angles_z *= 0.95; - if(vhic.angles_z >= -1 && vhic.angles_z <= -1) - vhic.angles_z = 0; + raptor.angles_z *= 0.95; + if(raptor.angles_z >= -1 && raptor.angles_z <= -1) + raptor.angles_z = 0; } if(player.BUTTON_CROUCH) - df -= v_up * raptor_speed_down; + df -= v_up * autocvar_g_vehicle_raptor_speed_down; else if (player.BUTTON_JUMP) - df += v_up * raptor_speed_up; - //else - //df_z = vhic.velocity_z * -1; - - vhic.velocity += df * frametime; - player.velocity = player.movement = vhic.velocity; - setorigin(player,vhic.origin + '0 0 32'); + df += v_up * autocvar_g_vehicle_raptor_speed_up; - // Aim the gunz - /* - vector target_angle, move_angle, org1, org2, targ; + raptor.velocity += df * frametime; + player.velocity = player.movement = raptor.velocity; + setorigin(player, raptor.origin + '0 0 32'); - makevectors(player.v_angle); - - //targ = (vhic.origin + player.view_ofs) + v_forward * MAX_SHOT_DISTANCE; - targ = player.cursor_trace_endpos; - - org1 = gettaginfo(vhic.gun1,gettagindex(vhic.gun1, "fire1")); - org2 = gettaginfo(vhic.gun2,gettagindex(vhic.gun2, "fire1")); + vector vf, ad; + // Target lock & predict + if(autocvar_g_vehicle_raptor_cannon_locktarget) + { - traceline(vhic.origin + player.view_ofs, targ, FALSE, vhic); - targ = trace_endpos; + vehicles_locktarget((1 / autocvar_g_vehicle_raptor_cannon_locking_time) * frametime, + (1 / autocvar_g_vehicle_raptor_cannon_locking_releasetime) * frametime, + autocvar_g_vehicle_raptor_cannon_locked_time); - // Find the direction - target_angle = vectoangles(normalize(targ - org1)); // And make a angle + if(self.lock_target != world) + if(autocvar_g_vehicle_raptor_cannon_predicttarget) + if(self.lock_strength == 1) + { + float i, distance, impact_time; + + vf = real_origin(raptor.lock_target); + ad = vf; + for(i = 0; i < 4; ++i) + { + distance = vlen(ad - raptor.origin); + impact_time = distance / autocvar_g_vehicle_raptor_cannon_speed; + ad = vf + raptor.lock_target.velocity * impact_time; + } + trace_endpos = ad; + } - // Find the diffrence between where we currently aim and where we want to aim - move_angle = target_angle - (vhic.angles + vhic.gun1.angles); - move_angle = shortangle_vxy(move_angle,(vhic.angles + vhic.gun1.angles)); - vhic.gun1.angles_x = bound(-10, move_angle_x + vhic.gun1.angles_x, 10); - vhic.gun1.angles_y = bound(-15, move_angle_y + vhic.gun1.angles_y, 15); + if(self.lock_target) + { + if(raptor.lock_strength == 1) + UpdateAuxiliaryXhair(player, real_origin(raptor.lock_target), '1 0 0', 1); + else if(self.lock_strength > 0.5) + UpdateAuxiliaryXhair(player, real_origin(raptor.lock_target), '0 1 0', 1); + else if(self.lock_strength < 0.5) + UpdateAuxiliaryXhair(player, real_origin(raptor.lock_target), '0 0 1', 1); + } + } - // Find the direction - target_angle = vectoangles(normalize(targ - org2)); // And make a angle + // Aim the gunz + ftmp2 = autocvar_g_vehicle_raptor_cannon_turnspeed * frametime; + ftmp = -ftmp2; + + // Gun1 + df = gettaginfo(raptor.gun1, gettagindex(raptor.gun1, "fire1")); + //ad = df; + //vf = v_forward; + df = vectoangles(normalize(trace_endpos - df)); // Find the direction & angle + df = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(raptor.angles), AnglesTransform_FromAngles(df))) - raptor.gun1.angles; + df = shortangle_vxy(df, raptor.gun1.angles); + + // Bind to aimspeed + df_x = bound(ftmp, df_x, ftmp2); + df_y = bound(ftmp, df_y, ftmp2); + // Bind to limts + raptor.gun1.angles_x = bound(-autocvar_g_vehicle_raptor_cannon_pitchlimit_down, df_x + raptor.gun1.angles_x, autocvar_g_vehicle_raptor_cannon_pitchlimit_up); + raptor.gun1.angles_y = bound(-autocvar_g_vehicle_raptor_cannon_turnlimit, df_y + raptor.gun1.angles_y, autocvar_g_vehicle_raptor_cannon_turnlimit); + + // Gun2 + df = gettaginfo(raptor.gun2, gettagindex(raptor.gun2, "fire1")); + //ad += df; + //vf += v_forward; + df = vectoangles(normalize(trace_endpos - df)); // Find the direction & angle + df = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(raptor.angles), AnglesTransform_FromAngles(df))) - raptor.gun2.angles; + df = shortangle_vxy(df, raptor.gun2.angles); + + // Bind to aimspeed + df_x = bound(ftmp, df_x, ftmp2); + df_y = bound(ftmp, df_y, ftmp2); + // Bind to limts + raptor.gun2.angles_x = bound(-autocvar_g_vehicle_raptor_cannon_pitchlimit_down, df_x + raptor.gun2.angles_x, autocvar_g_vehicle_raptor_cannon_pitchlimit_up); + raptor.gun2.angles_y = bound(-autocvar_g_vehicle_raptor_cannon_turnlimit, df_y + raptor.gun2.angles_y, autocvar_g_vehicle_raptor_cannon_turnlimit); - move_angle = target_angle - (vhic.angles + vhic.gun2.angles); - move_angle = shortangle_vxy(move_angle,(vhic.angles + vhic.gun2.angles)); - vhic.gun2.angles_x = bound(-15,move_angle_x + vhic.gun2.angles_x,15); - vhic.gun2.angles_y = bound(-20,move_angle_y + vhic.gun2.angles_y,20); - */ + /* + ad = ad * 0.5; + v_forward = vf * 0.5; + traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, raptor); + UpdateAuxiliaryXhair(player, trace_endpos, '0 1 0', 0); + */ + if(player.BUTTON_ATCK) - if(vhic.vehicle_energy > (raptor_beam_aps * sys_frametime)) + if(raptor.attack_finished_single <= time) + if(raptor.vehicle_energy > autocvar_g_vehicle_raptor_cannon_cost) { - vector start; - self = player; - - start = gettaginfo(vhic.gun1, gettagindex(vhic.gun1, "fire1")); - traceline(start, start + v_forward * MAX_SHOT_DISTANCE, TRUE, player); - te_lightning1(vhic.gun1, start, trace_endpos); - raptor_beam(start, trace_endpos, '-1 -1 -1' * raptor_beam_size, '1 1 1' * raptor_beam_size, raptor_beam_fops * sys_frametime, raptor_beam_dps * sys_frametime, DEATH_SBROCKET); - - - start = gettaginfo(vhic.gun2, gettagindex(vhic.gun2, "fire1")); - traceline(start, start + v_forward * MAX_SHOT_DISTANCE, TRUE, player); - te_lightning1(vhic.gun2, start, trace_endpos); - raptor_beam(start, trace_endpos, '-1 -1 -1' * raptor_beam_size, '1 1 1' * raptor_beam_size, raptor_beam_fops * sys_frametime, raptor_beam_dps * sys_frametime, DEATH_SBROCKET); - - self = vhic; - - vhic.vehicle_energy -= raptor_beam_aps * sys_frametime; - vhic.cnt = time + 1; + raptor.misc_bulletcounter += 1; + raptor.attack_finished_single = time + autocvar_g_vehicle_raptor_cannon_refire; + if(raptor.misc_bulletcounter <= 2) + raptor_fire_cannon(self.gun1, "fire1"); + else if(raptor.misc_bulletcounter == 3) + raptor_fire_cannon(self.gun2, "fire1"); + else + { + raptor.attack_finished_single = time + autocvar_g_vehicle_raptor_cannon_refire * 2; + raptor_fire_cannon(self.gun2, "fire1"); + raptor.misc_bulletcounter = 0; + } + raptor.vehicle_energy -= autocvar_g_vehicle_raptor_cannon_cost; + self.cnt = time; } - if(vhic.cnt < time) - vhic.vehicle_energy = min(vhic.vehicle_energy += raptor_energy_regen * frametime, raptor_energy_max); + if(self.vehicle_flags & VHF_SHIELDREGEN) + vehicles_regen(dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, frametime); + + if(self.vehicle_flags & VHF_HEALTHREGEN) + vehicles_regen(dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, frametime); - player.vehicle_energy = vhic.vehicle_energy / raptor_energy_max; + if(self.vehicle_flags & VHF_ENERGYREGEN) + vehicles_regen(cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, frametime); + if(time > raptor.delay) if(player.BUTTON_ATCK2) - if(time > vhic.delay) { raptor_bombdrop(); - vhic.delay = time + raptor_bombs_refire; + raptor.delay = time + autocvar_g_vehicle_raptor_bombs_refire; + raptor.lip = time; } - player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0; - vehicle_stdproc_shiledregen(raptor_shield_max, frametime); - vehicle_stdproc_healthregen(raptor_health_max, frametime); - - self = player; - - return 1; -} - -float raptor_takeoff() -{ - entity player, vhic; + raptor.bomb1.alpha = raptor.bomb2.alpha = (time - raptor.lip) / (raptor.delay - raptor.lip); + player.vehicle_reload2 = bound(0, raptor.bomb1.alpha * 100, 100); - if(self.vehicle.frame < 25) - return 1; - - player = self; - vhic = self.vehicle; - self = vhic; + VEHICLE_UPDATE_PLAYER(health, raptor); + VEHICLE_UPDATE_PLAYER(energy, raptor); + if(self.vehicle_flags & VHF_HASSHIELD) + VEHICLE_UPDATE_PLAYER(shield, raptor); - if(raptor_altitude(512) <= 256) - { - vhic.velocity_z = min(vhic.velocity_z * 1.5, 256); - } - else - { - player.PlayerPhysplug = raptor_pplug; - } - - player.BUTTON_CROUCH = player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0; + player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0; + self = player; - return 1; } -float raptor_land() +void raptor_blowup() { - return 0; -} + self.deadflag = DEAD_DEAD; + self.vehicle_exit(VHEF_NORMAL); + RadiusDamage (self, self, 250, 15, 250, world, 250, DEATH_WAKIBLOWUP, world); -void raptor_return() -{ - pointparticles(particleeffectnum("teleport"), self.enemy.origin + '0 0 64', '0 0 0', 1); - self.enemy.think = raptor_spawn; - self.enemy.nextthink = time; - remove(self); -} + self.alpha = -1; + self.movetype = MOVETYPE_NONE; + self.effects = EF_NODRAW; + self.colormod = '0 0 0'; + self.avelocity = '0 0 0'; + self.velocity = '0 0 0'; -void raptor_think() -{ + setorigin(self, self.pos1); + self.touch = SUB_Null; + self.nextthink = 0; } -void raptor_touch() +void raptor_diethink() { - if(self.owner) + if(random() < 0.1) { - if(vlen(self.velocity) == 0) - return; - - if(other.classname != "player") - return; - - return; + sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("explosion_small"), randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1); } - - if(other.classname != "player") - return; - - if(other.deadflag != DEAD_NO) - return; - - if(other.vehicle != world) - return; - - raptor_enter(); + self.nextthink = time + 0.1; } void raptor_die() { self.health = 0; self.event_damage = SUB_Null; - self.iscreature = FALSE; - self.solid = SOLID_NOT; + self.solid = SOLID_CORPSE; self.takedamage = DAMAGE_NO; - //self.touch = racer_dietouch; self.deadflag = DEAD_DYING; self.movetype = MOVETYPE_BOUNCE; - self.wait = time; - - pointparticles(particleeffectnum("rocket_explode"), findbetterlocation (self.origin, 16), '0 0 0', 1); + self.think = raptor_diethink; + self.nextthink = time; + + pointparticles(particleeffectnum("explosion_medium"), findbetterlocation (self.origin, 16), '0 0 0', 1); - self.velocity += '0 0 128'; + self.velocity_z += 600; - if(random() < 0.5) - self.avelocity_z = 45; - else - self.avelocity_z = -45; + self.avelocity = '0 0.5 1' * (random() * 400); + self.avelocity -= '0 0.5 1' * (random() * 400); self.colormod = '-0.5 -0.5 -0.5'; + self.touch = raptor_blowup; +} - self.think = raptor_spawn; - self.nextthink = time + 5; +void raptor_impact() +{ + if(autocvar_g_vehicle_raptor_bouncepain_x) + vehilces_impact(autocvar_g_vehicle_raptor_bouncepain_x, autocvar_g_vehicle_raptor_bouncepain_y, autocvar_g_vehicle_raptor_bouncepain_z); } void raptor_spawn() { - self.flags = FL_NOTARGET; - self.effects = 0; - - self.vehicle_health = raptor_health_max; - self.vehicle_shield = raptor_shield_max; - - self.event_damage = vehicle_stdproc_damage; - self.touch = raptor_touch; - - self.iscreature = TRUE; - self.movetype = MOVETYPE_FLY; - self.solid = SOLID_SLIDEBOX; - self.takedamage = DAMAGE_AIM; - - self.alpha = 1; - self.colormap = 1024; - self.deadflag = DEAD_NO; - self.bot_attack = TRUE; - - self.colormod = '1 1 1'; - self.avelocity = '0 0 0'; - self.velocity = '0 0 0'; - + self.frame = 0; + self.vehicle_health = autocvar_g_vehicle_raptor_health; + self.vehicle_shield = autocvar_g_vehicle_raptor_shield; + self.movetype = MOVETYPE_TOSS; + self.solid = SOLID_SLIDEBOX; self.vehicle_energy = 1; - self.vehicle_hudmodel.viewmodelforclient = self; - setorigin(self, self.pos1); - self.angles = self.pos2; + self.bomb1.gun1.avelocity_y = 90; + self.bomb1.gun2.avelocity_y = -90; - setsize(self,RAPTOR_MIN ,RAPTOR_MAX ); - pointparticles(particleeffectnum("teleport"), self.origin + '0 0 64', '0 0 0', 1); + setsize(self, RAPTOR_MIN, RAPTOR_MAX ); self.delay = time; + + self.bouncefactor = autocvar_g_vehicle_raptor_bouncefactor; + self.bouncestop = autocvar_g_vehicle_raptor_bouncestop; + self.vehicle_impact = raptor_impact; } -float raptor_customizeentityforclient() +// If we dont do this ever now and then, the raptors rotors +// stop working, presumably due to angle overflow. cute. +void raptor_rotor_anglefix() { - if(self.deadflag == DEAD_DEAD) - return FALSE; - - /* - if(other == self.owner) - self.alpha = -1; - else - self.alpha = 1; - */ - - return TRUE; + self.gun1.angles_y = anglemods(self.gun1.angles_y); + self.gun2.angles_y = anglemods(self.gun2.angles_y); + self.nextthink = time + 15; } void raptor_dinit() { + entity spinner; + vector ofs; + + if not (vehicle_initialize( + "Raptor", + "models/vehicles/raptor.dpm", + "", + "models/vehicles/raptor_cockpit.dpm", + "", "tag_hud", "tag_camera", + HUD_RAPTOR, + RAPTOR_MIN, RAPTOR_MAX, + FALSE, + raptor_spawn, autocvar_g_vehicle_raptor_respawntime, + raptor_frame, + raptor_enter, raptor_exit, + raptor_die, raptor_think, + FALSE)) + { + remove(self); + return; + } - if (self.netname == "") - self.netname = "Raptor"; - - setorigin(self, self.origin); + //FIXME: Camera is in a bad place in HUD model. + //setorigin(self.vehicle_viewport, '25 0 5'); self.frame = 0; - setmodel(self,"models/vehicles/raptor.dpm"); - self.bomb1 = spawn(); self.bomb2 = spawn(); + self.gun1 = spawn(); + self.gun2 = spawn(); - setmodel(self.bomb1,"models/vehicles/raptor_bomb.dpm"); - setmodel(self.bomb2,"models/vehicles/raptor_bomb.dpm"); + setmodel(self.bomb1,"models/vehicles/clusterbomb_folded.md3"); + setmodel(self.bomb2,"models/vehicles/clusterbomb_folded.md3"); + setmodel(self.gun1, "models/vehicles/raptor_gun.dpm"); + setmodel(self.gun2, "models/vehicles/raptor_gun.dpm"); + setmodel(self.tur_head, "models/vehicles/raptor_body.dpm"); setattachment(self.bomb1, self,"bombmount_left"); setattachment(self.bomb2, self,"bombmount_right"); + setattachment(self.tur_head, self,"root"); - if not (self.vehicle_hudmodel) - { - self.vehicle_hudmodel = spawn(); - setmodel(self.vehicle_hudmodel, "models/vehicles/raptor_cockpit.dpm"); - //setattachment(self.vehicle_hudmodel, self, "tag_viewport"); - setattachment(self.vehicle_hudmodel, self, "tag_hud"); - } + // FIXME Guns mounts to angled bones + self.bomb1.angles = self.angles; + self.angles = '0 0 0'; + // This messes up gun-aim, so work arround it. + //setattachment(self.gun1, self, "gunmount_left"); + ofs = gettaginfo(self, gettagindex(self, "gunmount_left")); + ofs -= self.origin; + setattachment(self.gun1, self, ""); + setorigin(self.gun1, ofs); - if not (self.vehicle_viewport) - { - self.vehicle_viewport = spawn(); - setmodel (self.vehicle_viewport, "null"); - setattachment(self.vehicle_viewport, self.vehicle_hudmodel, "tag_camera"); - } + //setattachment(self.gun2, self, "gunmount_right"); + ofs = gettaginfo(self, gettagindex(self, "gunmount_right")); + ofs -= self.origin; + setattachment(self.gun2, self, ""); + setorigin(self.gun2, ofs); - if not (self.gun1) - { - self.gun1 = spawn(); - setmodel(self.gun1, "models/vehicles/raptor_gun.dpm"); - setattachment(self.gun1, self, "gunmount_left"); - } + self.angles = self.bomb1.angles; + self.bomb1.angles = '0 0 0'; - if not (self.gun2) - { - self.gun2 = spawn(); - setmodel(self.gun2, "models/vehicles/raptor_gun.dpm"); - setattachment(self.gun2, self, "gunmount_right"); - } - - self.tur_head = spawn(); - self.pos1 = self.origin; - self.pos2 = self.angles; - - self.vehicle_hudmodel.viewmodelforclient = self; - self.customizeentityforclient = raptor_customizeentityforclient; - - self.vehicle_die = raptor_die; - self.vehicle_exit = raptor_exit; - - - entity spinner; spinner = spawn(); spinner.owner = self; setmodel(spinner,"models/vehicles/spinner.dpm"); setattachment(spinner, self, "engine_left"); spinner.movetype = MOVETYPE_NOCLIP; spinner.avelocity = '0 90 0'; + self.bomb1.gun1 = spinner; spinner = spawn(); spinner.owner = self; @@ -817,76 +710,50 @@ void raptor_dinit() setattachment(spinner, self, "engine_right"); spinner.movetype = MOVETYPE_NOCLIP; spinner.avelocity = '0 -90 0'; + self.bomb1.gun2 = spinner; - addstat(STAT_HUD, AS_INT, hud); - addstat(STAT_VEHICLESTAT_HEALTH, AS_FLOAT, vehicle_health); - addstat(STAT_VEHICLESTAT_SHIELD, AS_FLOAT, vehicle_shield); - addstat(STAT_VEHICLESTAT_ENERGY, AS_FLOAT, vehicle_energy); - - addstat(STAT_VEHICLESTAT_AMMO1, AS_INT, vehicle_ammo1); - addstat(STAT_VEHICLESTAT_RELOAD1, AS_FLOAT, vehicle_reload1); + // Sigh. + self.bomb1.think = raptor_rotor_anglefix; + self.bomb1.nextthink = time; - addstat(STAT_VEHICLESTAT_AMMO2, AS_INT, vehicle_ammo2); - addstat(STAT_VEHICLESTAT_RELOAD2, AS_FLOAT, vehicle_reload2); - - raptor_spawn(); + self.mass = 1 ; } void spawnfunc_vehicle_raptor() { - self.cvar_basename = "g_vehicle_raptor"; - raptor_loadsettings(); + vehicles_configcheck("vehicle_raptor.cfg", autocvar_g_vehicle_raptor_health); - self.vehicle_flags = VHF_HASSHIELD | VHF_SHIELDREGEN; + self.vehicle_flags |= VHF_DMGSHAKE; + self.vehicle_flags |= VHF_DMGROLL; + + if(autocvar_g_vehicle_raptor_shield) + self.vehicle_flags |= VHF_HASSHIELD; - traceline(self.origin, self.origin - '0 0 2048', MOVE_WORLDONLY, self); - if(trace_startsolid) - { - dprint("WARNING: vehicle_raptor placed in solid\n"); - traceline(self.origin + '0 0 512' ,self.origin - '0 0 2048',MOVE_WORLDONLY,self); - if(trace_startsolid || trace_fraction == 1.0) - { - dprint("ERROR: vehicle_raptor placed in more then 512 units into solid\n"); - remove(self); - return; - } - } + if(autocvar_g_vehicle_raptor_shield_regen) + self.vehicle_flags |= VHF_SHIELDREGEN; - if(trace_fraction != 1.0) - setorigin(self,trace_endpos + '0 0 8'); - else - dprint("WARNING: vehicle_racer placed more then 2048 units above ground.\n"); + if(autocvar_g_vehicle_raptor_health_regen) + self.vehicle_flags |= VHF_HEALTHREGEN; + + if(autocvar_g_vehicle_raptor_energy_regen) + self.vehicle_flags |= VHF_ENERGYREGEN; precache_model ("models/vehicles/raptor.dpm"); precache_model ("models/vehicles/raptor_gun.dpm"); precache_model ("models/vehicles/spinner.dpm"); precache_model ("models/vehicles/raptor_cockpit.dpm"); - precache_model ("models/vehicles/raptor_bomb.dpm"); - - + //precache_model ("models/vehicles/clusterbomb.md3"); + precache_model ("models/vehicles/clusterbomb_folded.md3"); + precache_model ("models/vehicles/raptor_body.dpm"); + + precache_sound ("vehicles/raptor_fly.wav"); + precache_sound ("vehicles/raptor_speed.wav"); + self.think = raptor_dinit; - self.nextthink = time + 1; -} - - -void spawnfunc_vehicle_raptor2() -{ - entity iqm,dpm,md3; - - precache_model ("models/vehicles/test.iqm"); - precache_model ("models/vehicles/test.dpm"); - precache_model ("models/vehicles/test.md3"); - - iqm = spawn(); - dpm = spawn(); - md3 = spawn(); - iqm.scale = md3.scale = dpm.scale = 10; - - //setmodel(iqm,"models/vehicles/test.iqm"); - //setmodel(dpm,"models/vehicles/test.dpm"); - setmodel(md3,"models/vehicles/test.md3"); - - setorigin(iqm, self.origin + '0 0 16'); - setorigin(dpm, self.origin + '0 20 32'); - setorigin(iqm, self.origin + '0 40 48'); + + if(g_assault) + self.nextthink = time + 0.5; + else + self.nextthink = time + (autocvar_g_vehicles_delayspawn ? autocvar_g_vehicle_raptor_respawntime + (random() * autocvar_g_vehicles_delayspawn_jitter) : 0.5); } +#endif // SVQC diff --git a/qcsrc/server/vehicles/spiderbot.qc b/qcsrc/server/vehicles/spiderbot.qc index fa0781fa78..f1cb575519 100644 --- a/qcsrc/server/vehicles/spiderbot.qc +++ b/qcsrc/server/vehicles/spiderbot.qc @@ -1,71 +1,77 @@ -const vector spiderbot_MIN = '-75 -75 0'; -const vector spiderbot_MAX = '75 75 100'; +const vector SPIDERBOT_MIN = '-75 -75 10'; +const vector SPIDERBOT_MAX = '75 75 125'; + +#ifdef SVQC +float autocvar_g_vehicle_spiderbot_respawntime; + +float autocvar_g_vehicle_spiderbot_speed_stop; +float autocvar_g_vehicle_spiderbot_speed_strafe; +float autocvar_g_vehicle_spiderbot_speed_walk; +float autocvar_g_vehicle_spiderbot_turnspeed; +float autocvar_g_vehicle_spiderbot_movement_inertia; + +float autocvar_g_vehicle_spiderbot_springlength; +float autocvar_g_vehicle_spiderbot_springup; +float autocvar_g_vehicle_spiderbot_springblend; + +float autocvar_g_vehicle_spiderbot_head_pitchlimit_down; +float autocvar_g_vehicle_spiderbot_head_pitchlimit_up; +float autocvar_g_vehicle_spiderbot_head_pitchspeed; +float autocvar_g_vehicle_spiderbot_head_turnlimit; +float autocvar_g_vehicle_spiderbot_head_turnspeed; + +//float autocvar_g_vehicle_spiderbot_energy; +//float autocvar_g_vehicle_spiderbot_energy_regen; +//float autocvar_g_vehicle_spiderbot_energy_regen_pause; + +float autocvar_g_vehicle_spiderbot_health; +float autocvar_g_vehicle_spiderbot_health_regen; +float autocvar_g_vehicle_spiderbot_health_regen_pause; + +float autocvar_g_vehicle_spiderbot_shield; +float autocvar_g_vehicle_spiderbot_shield_regen; +float autocvar_g_vehicle_spiderbot_shield_regen_pause; + +float autocvar_g_vehicle_spiderbot_minigun_damage; +float autocvar_g_vehicle_spiderbot_minigun_refire; +float autocvar_g_vehicle_spiderbot_minigun_spread; +float autocvar_g_vehicle_spiderbot_minigun_ammo_cost; +float autocvar_g_vehicle_spiderbot_minigun_ammo_max; +float autocvar_g_vehicle_spiderbot_minigun_ammo_regen; +float autocvar_g_vehicle_spiderbot_minigun_ammo_regen_pause; + +float autocvar_g_vehicle_spiderbot_rocket_damage; +float autocvar_g_vehicle_spiderbot_rocket_force; +float autocvar_g_vehicle_spiderbot_rocket_radius; +float autocvar_g_vehicle_spiderbot_rocket_speed; +float autocvar_g_vehicle_spiderbot_rocket_refire; +float autocvar_g_vehicle_spiderbot_rocket_reload; +float autocvar_g_vehicle_spiderbot_rocket_health; +float autocvar_g_vehicle_spiderbot_rocket_noise; +float autocvar_g_vehicle_spiderbot_rocket_turnrate; +float autocvar_g_vehicle_spiderbot_rocket_lifetime; + +vector autocvar_g_vehicle_spiderbot_bouncepain; -#define spiderbot_spawnpnt wkr_spawn void spiderbot_exit(float eject); void spiderbot_enter(); - -void spiderbot_rocket_explode() -{ - vector org2; - - if(self.event_damage != SUB_Null) - { - self.event_damage = SUB_Null; - self.think = spiderbot_rocket_explode; - self.nextthink = time; - return; - } - - sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); - org2 = findbetterlocation (self.origin, 16); - pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1); - w_deathtypestring = "dident escape the rocket barrage"; - - if(!self.owner) - self.owner = self.realowner; - - RadiusDamage (self, self.owner, - autocvar_g_vehicle_spiderbot_rocket_damage, - autocvar_g_vehicle_spiderbot_rocket_edgedamage, - autocvar_g_vehicle_spiderbot_rocket_radius, world, - autocvar_g_vehicle_spiderbot_rocket_force, DEATH_SBROCKET, world); - - remove (self); -} - -void spiderbot_rocket_touch() -{ - if(self.owner) - { - if(other == self.owner.vehicle) - return; - - if(other == self.owner.vehicle.tur_head) - return; - } - - PROJECTILE_TOUCH; - spiderbot_rocket_explode(); -} +void spiderbot_spawn(); void spiderbot_rocket_unguided() { - vector newdir,olddir; + vector newdir, olddir; self.nextthink = time; - olddir = normalize(self.velocity); newdir = normalize(self.pos1 - self.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise; self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed; UpdateCSQCProjectile(self); - if (self.owner.deadflag != DEAD_NO || self.cnt < time) - spiderbot_rocket_explode(); - + if (self.owner.deadflag != DEAD_NO || self.cnt < time || vlen(self.pos1 - self.origin) < 16) + self.use(); } void spiderbot_rocket_guided() @@ -74,10 +80,10 @@ void spiderbot_rocket_guided() self.nextthink = time; - if not (self.owner.vehicle) + if not (self.realowner.vehicle) self.think = spiderbot_rocket_unguided; - crosshair_trace(self.owner); + crosshair_trace(self.realowner); olddir = normalize(self.velocity); newdir = normalize(trace_endpos - self.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise; self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed; @@ -85,26 +91,17 @@ void spiderbot_rocket_guided() UpdateCSQCProjectile(self); if (self.owner.deadflag != DEAD_NO || self.cnt < time) - spiderbot_rocket_explode(); -} - -void spiderbot_rocket_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) -{ - self.health -= damage; - self.velocity += force; - if(self.health < 1) - spiderbot_rocket_explode(); + self.use(); } void spiderbot_guide_release() { entity rkt; - rkt = findchainentity(owner,self.owner); + rkt = findchainentity(realowner, self.owner); if not (rkt) return; crosshair_trace(self.owner); - while(rkt) { if(rkt.think == spiderbot_rocket_guided) @@ -112,13 +109,14 @@ void spiderbot_guide_release() rkt.pos1 = trace_endpos; rkt.think = spiderbot_rocket_unguided; } - rkt = rkt.chain; } } void spiderbot_rocket_do() { + + vector v; entity rocket; if (self.owner.BUTTON_ATCK2) @@ -131,7 +129,6 @@ void spiderbot_rocket_do() return; } - self.wait = 1; } else @@ -151,33 +148,20 @@ void spiderbot_rocket_do() if not (self.owner.BUTTON_ATCK2) return; - sound (self, CHAN_WEAPON, "weapons/rocket_fire.wav", VOL_BASE, ATTN_NORM); - rocket = spawn (); - setsize (rocket, '-1 -1 -1', '1 1 1'); // give it some size so it can be shot - setorigin(rocket,gettaginfo(self.tur_head,gettagindex(self.tur_head,"tag_fire"))); - te_explosion (rocket.origin); - crosshair_trace(self.owner); - rocket.classname = "spiderbot_rocket"; - rocket.bot_dodge = TRUE; - rocket.bot_dodgerating = autocvar_g_vehicle_spiderbot_rocket_damage; - rocket.cnt = time + autocvar_g_vehicle_spiderbot_rocket_lifetime; - rocket.health = autocvar_g_vehicle_spiderbot_rocket_health; - rocket.takedamage = DAMAGE_AIM; - rocket.event_damage = spiderbot_rocket_damage; - rocket.owner = self.owner; - rocket.nextthink = time; - rocket.movetype = MOVETYPE_FLYMISSILE; - rocket.velocity = normalize(v_forward + (v_up * 0.5) + randomvec() * 0.25) * autocvar_g_vehicle_spiderbot_rocket_speed; - rocket.angles = vectoangles(rocket.velocity); - rocket.think = spiderbot_rocket_guided; - rocket.touch = spiderbot_rocket_touch; - rocket.flags = FL_PROJECTILE; - rocket.solid = SOLID_TRIGGER; - rocket.pos1 = trace_endpos; - - CSQCProjectile(rocket, FALSE, PROJECTILE_ROCKET, FALSE); // no culling, has fly sound + v = gettaginfo(self.tur_head,gettagindex(self.tur_head,"tag_fire")); + rocket = vehicles_projectile("spiderbot_rocket_launch", "weapons/rocket_fire.wav", + v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed, + autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1, + DEATH_SBROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, FALSE, FALSE); + + rocket.cnt = time + 15; + rocket.classname = "spiderbot_rocket"; + rocket.pos1 = trace_endpos; + rocket.think = spiderbot_rocket_guided; + rocket.nextthink = time; + rocket.cnt = time + autocvar_g_vehicle_spiderbot_rocket_lifetime; self.tur_head.frame += 1; if (self.tur_head.frame == 9) @@ -188,140 +172,52 @@ void spiderbot_rocket_do() self.gun2.cnt = time + self.attack_finished_single; } -/* -void spiderbot_minigun_fire_Flash_Go() { - if (self.frame > 10) - { - self.alpha = -1; - setmodel(self,""); - return; - } - - self.frame = self.frame + 2; - self.alpha = self.alpha - 0.2; - self.scale -= 0.01; - self.nextthink = time + 0.02; -} -*/ - -void spiderbot_minigun_fire(entity gun, float trail) -{ - vector v; - - v = gettaginfo(gun,gettagindex(gun,"barrels")); - v_forward = normalize(v_forward); - - sound (gun, CHAN_WEAPON, "weapons/uzi_fire.wav", VOL_BASE, ATTN_NORM); - - fireBullet (v, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_damage, - autocvar_g_vehicle_spiderbot_minigun_spread, DEATH_SBMINIGUN, 0); - - - UziFlash(); - setattachment(self.muzzle_flash, self.tur_head, "tag_fire"); - - if(trail) - trailparticles(self, particleeffectnum("EF_MGTURRETTRAIL"), v, trace_endpos); -} - -void spiderbot_miniguns_do() +float spiderbot_frame() { + vector ad, vf; + entity player, spider; float ftmp; - if((self.vehicle_reload1 == 1) || (!self.owner.BUTTON_ATCK)) - { - - ftmp = 1 / autocvar_g_vehicle_spiderbot_minigun_cooldown * sys_frametime; - self.owner.vehicle_reload1 = max(self.owner.vehicle_reload1 - ftmp, 0); - if(self.owner.vehicle_reload1 <= 0) - self.vehicle_reload1 = 0; - - return ; - } - - if (self.owner.BUTTON_ATCK) - { - - // Animate miniguns - self.gun1.angles_z += (1440 * sys_frametime); - self.gun2.angles_z -= (1440 * sys_frametime); - if(self.gun1.angles_z >= 360) - { - self.gun1.angles_z = 0; - self.gun2.angles_z = 360; - } - - if (self.tur_head.attack_finished_single < time) - { - // Fire bullets, alternating trails left<->right - self = self.owner; - if(self.uzi_bulletcounter == 1) - { - spiderbot_minigun_fire(self.vehicle.gun1, 0); - spiderbot_minigun_fire(self.vehicle.gun2, 1); - self.uzi_bulletcounter = 0; - } - else - { - spiderbot_minigun_fire(self.vehicle.gun1, 1); - spiderbot_minigun_fire(self.vehicle.gun2, 0); - self.uzi_bulletcounter += 1; - } - - self = self.vehicle; - - ftmp = autocvar_g_vehicle_spiderbot_minigun_refire / autocvar_g_vehicle_spiderbot_minigun_heat; - self.owner.vehicle_reload1 += ftmp; - - if(self.owner.vehicle_reload1 >= 1) - { - self.vehicle_reload1 = 1; - self.owner.vehicle_reload1 = 1; - self.tur_head.attack_finished_single = autocvar_g_vehicle_spiderbot_minigun_cooldown + time; - } - else - self.tur_head.attack_finished_single = autocvar_g_vehicle_spiderbot_minigun_refire + time; - } - - self = self.owner; - return; - } -} - -float spiderbot_pplug() -{ - vector ad; - entity player,spider; - float ftmp; - - if not (self.owner) - { - } - + if(intermission_running) + return 1; + player = self; spider = self.vehicle; + self = spider; - player.BUTTON_ZOOM = 0; - player.BUTTON_CROUCH = 0; - player.switchweapon = 0; - - if(player.BUTTON_USE) - { - self = spider; - spiderbot_exit(0); - self = player; - return 0; - } + vehicles_painframe(); + + player.BUTTON_ZOOM = 0; + player.BUTTON_CROUCH = 0; + player.switchweapon = 0; + +#if 1 // 0 to enable per-gun impact aux crosshairs + // Avarage gun impact point's -> aux cross + ad = gettaginfo(spider.tur_head, gettagindex(spider.tur_head, "tag_hardpoint01")); + vf = v_forward; + ad += gettaginfo(spider.tur_head, gettagindex(spider.tur_head, "tag_hardpoint02")); + vf += v_forward; + ad = ad * 0.5; + v_forward = vf * 0.5; + traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider); + UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 0); +#else + ad = gettaginfo(spider.gun1, gettagindex(spider.gun1, "barrels")); + traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider); + UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 0); + vf = ad; + ad = gettaginfo(spider.gun2, gettagindex(spider.gun2, "barrels")); + traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider); + UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 1); + ad = 0.5 * (ad + vf); +#endif crosshair_trace(player); - ad = vectoangles(normalize(trace_endpos - gettaginfo(spider.tur_head,gettagindex(spider.tur_head,"tag_hud")))) - (spider.tur_head.angles + spider.angles); - - fixedmakevectors(spider.angles); - if(ad_x > 180) ad_x -= 360; - if(ad_x < -180) ad_x += 360; - if(ad_y > 180) ad_y -= 360; - if(ad_y < -180) ad_y += 360; - + ad = vectoangles(normalize(trace_endpos - ad)); + ad = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(spider.angles), AnglesTransform_FromAngles(ad))) - spider.tur_head.angles; + ad = AnglesTransform_Normalize(ad, TRUE); + //UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload2) + ('0 1 0' * (1 - player.vehicle_reload2)), 2); + // Rotate head ftmp = autocvar_g_vehicle_spiderbot_head_turnspeed * sys_frametime; ad_y = bound(-ftmp, ad_y, ftmp); @@ -329,18 +225,32 @@ float spiderbot_pplug() // Pitch head ftmp = autocvar_g_vehicle_spiderbot_head_pitchspeed * sys_frametime; - ad_x = bound(-ftmp, ad_x, ftmp); + ad_x = bound(ftmp * -1, ad_x, ftmp); spider.tur_head.angles_x = bound(autocvar_g_vehicle_spiderbot_head_pitchlimit_down, spider.tur_head.angles_x + ad_x, autocvar_g_vehicle_spiderbot_head_pitchlimit_up); // Turn Body ftmp = autocvar_g_vehicle_spiderbot_turnspeed * sys_frametime; ftmp = bound(-ftmp, spider.tur_head.angles_y, ftmp); - self = spider; + //fixedmakevectors(spider.angles); + makevectors(spider.angles + '-2 0 0' * spider.angles_x); + + movelib_groundalign4point(autocvar_g_vehicle_spiderbot_springlength, autocvar_g_vehicle_spiderbot_springup, autocvar_g_vehicle_spiderbot_springblend); + if(spider.flags & FL_ONGROUND) { - if(player.BUTTON_JUMP && self.tur_head.wait < time) + if(spider.frame == 4 && self.tur_head.wait != 0) { + sound (self, CH_TRIGGER_SINGLE, "vehicles/spiderbot_land.wav", VOL_VEHICLEENGINE, ATTN_NORM); + spider.frame = 5; + } + + if(player.BUTTON_JUMP && self.tur_head.wait < time) + { + sound (self, CH_TRIGGER_SINGLE, "vehicles/spiderbot_jump.wav", VOL_VEHICLEENGINE, ATTN_NORM); + //dprint("spiderbot_jump:", ftos(soundlength("vehicles/spiderbot_jump.wav")), "\n"); + self.delay = 0; + self.tur_head.wait = time + 2; player.BUTTON_JUMP = 0; spider.velocity = v_forward * 700 + v_up * 600; @@ -350,6 +260,13 @@ float spiderbot_pplug() { if(vlen(player.movement) == 0) { + if(self.sound_nexttime < time || self.delay != 3) + { + self.delay = 3; + self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_idle.wav"); + //dprint("spiderbot_idle:", ftos(soundlength("vehicles/spiderbot_idle.wav")), "\n"); + sound (self, CH_TRIGGER_SINGLE, "vehicles/spiderbot_idle.wav", VOL_VEHICLEENGINE, ATTN_NORM); + } movelib_beak_simple(autocvar_g_vehicle_spiderbot_speed_stop); spider.frame = 5; } @@ -372,6 +289,14 @@ float spiderbot_pplug() } player.movement_y = 0; movelib_move_simple(normalize(v_forward * player.movement_x),autocvar_g_vehicle_spiderbot_speed_walk,autocvar_g_vehicle_spiderbot_movement_inertia); + + if(self.sound_nexttime < time || self.delay != 1) + { + self.delay = 1; + self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_walk.wav"); + sound (self, CH_TRIGGER_SINGLE, "vehicles/spiderbot_walk.wav", VOL_VEHICLEENGINE, ATTN_NORM); + //dprint("spiderbot_walk:", ftos(soundlength("vehicles/spiderbot_walk.wav")), "\n"); + } } else if(player.movement_y != 0) { @@ -386,34 +311,91 @@ float spiderbot_pplug() spider.frame = 3; } movelib_move_simple(normalize(v_right * player.movement_y),autocvar_g_vehicle_spiderbot_speed_strafe,autocvar_g_vehicle_spiderbot_movement_inertia); + if(self.sound_nexttime < time || self.delay != 2) + { + self.delay = 2; + self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_strafe.wav"); + sound (self, CH_TRIGGER_SINGLE, "vehicles/spiderbot_strafe.wav", VOL_VEHICLEENGINE, ATTN_NORM); + //dprint("spiderbot_strafe:", ftos(soundlength("vehicles/spiderbot_strafe.wav")), "\n"); + } } + } + } + } + + self.angles_x = bound(-45, self.angles_x, 45); + self.angles_z = bound(-45, self.angles_z, 45); + + if(player.BUTTON_ATCK) + { + spider.cnt = time; + if(spider.vehicle_ammo1 >= autocvar_g_vehicle_spiderbot_minigun_ammo_cost && spider.tur_head.attack_finished_single <= time) + { + entity gun; + vector v; + spider.misc_bulletcounter += 1; + + self = player; + + mod(spider.misc_bulletcounter, 2) ? gun = spider.gun1 : gun = spider.gun2; + v = gettaginfo(gun, gettagindex(gun, "barrels")); + v_forward = normalize(v_forward); + v += v_forward * 50; + + fireBullet (v, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_damage, + autocvar_g_vehicle_spiderbot_minigun_spread, DEATH_SBMINIGUN, 0); + sound (gun, CH_WEAPON_A, "weapons/uzi_fire.wav", VOL_BASE, ATTN_NORM); + trailparticles(self, particleeffectnum("spiderbot_minigun_trail"), v, trace_endpos); + pointparticles(particleeffectnum("spiderbot_minigun_muzzleflash"), v, v_forward * 2500, 1); + + self = spider; + + spider.vehicle_ammo1 -= autocvar_g_vehicle_spiderbot_minigun_ammo_cost; + spider.tur_head.attack_finished_single = time + autocvar_g_vehicle_spiderbot_minigun_refire; + player.vehicle_ammo1 = (spider.vehicle_ammo1 / autocvar_g_vehicle_spiderbot_minigun_ammo_max) * 100; + spider.gun1.angles_z += 45; + spider.gun2.angles_z -= 45; + if(spider.gun1.angles_z >= 360) + { + spider.gun1.angles_z = 0; + spider.gun2.angles_z = 0; } } - movelib_groundalign4point(300,100,0.25); } + else + vehicles_regen(cnt, vehicle_ammo1, autocvar_g_vehicle_spiderbot_minigun_ammo_max, + autocvar_g_vehicle_spiderbot_minigun_ammo_regen_pause, + autocvar_g_vehicle_spiderbot_minigun_ammo_regen, frametime); + - spiderbot_miniguns_do(); spiderbot_rocket_do(); - vehicle_stdproc_shiledregen(CCVAR("_shield"), frametime); - vehicle_stdproc_healthregen(CCVAR("_health"), frametime); + + if(self.vehicle_flags & VHF_SHIELDREGEN) + vehicles_regen(dmg_time, vehicle_shield, autocvar_g_vehicle_spiderbot_shield, autocvar_g_vehicle_spiderbot_shield_regen_pause, autocvar_g_vehicle_spiderbot_shield_regen, frametime); + + if(self.vehicle_flags & VHF_HEALTHREGEN) + vehicles_regen(dmg_time, vehicle_health, autocvar_g_vehicle_spiderbot_health, autocvar_g_vehicle_spiderbot_health_regen_pause, autocvar_g_vehicle_spiderbot_health_regen, frametime); player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0; player.vehicle_ammo2 = spider.tur_head.frame; if(spider.gun2.cnt <= time) - player.vehicle_reload2 = 1; + player.vehicle_reload2 = 100; else - player.vehicle_reload2 = 1 - ((spider.gun2.cnt - time) / spider.attack_finished_single); + player.vehicle_reload2 = 100 - ((spider.gun2.cnt - time) / spider.attack_finished_single) * 100; - setorigin(player,spider.origin + '0 0 64'); + setorigin(player, spider.origin + '0 0 1' * SPIDERBOT_MAX_z); player.velocity = spider.velocity; - self = player; + VEHICLE_UPDATE_PLAYER(health, spiderbot); - return 1; -} + if(self.vehicle_flags & VHF_HASSHIELD) + VEHICLE_UPDATE_PLAYER(shield, spiderbot); + self = player; + return 1; +} void spiderbot_think() { if(self.flags & FL_ONGROUND) @@ -424,71 +406,23 @@ void spiderbot_think() void spiderbot_enter() { - // Remove this when bots know how to use the spiderbot - if (clienttype(other) != CLIENTTYPE_REAL) - return; - - self.colormod = self.tur_head.colormod = '0 0 0'; + self.movetype = MOVETYPE_WALK; - if(teams_matter) - if(self.team) - if(self.team != other.team) - return; + self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_spiderbot_health) * 100; + self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_spiderbot_shield) * 100; - self.owner = other; - self.switchweapon = other.switchweapon; - - self.event_damage = vehicle_stdproc_damage ; - self.colormap = self.owner.colormap; - self.tur_head.colormap = self.owner.colormap; - self.vehicle_hudmodel.viewmodelforclient = self.owner; - self.nextthink = 0; - self.owner.angles = self.angles; - self.owner.takedamage = DAMAGE_NO; - self.owner.solid = SOLID_NOT; - self.owner.movetype = MOVETYPE_NOCLIP; - self.owner.alpha = -1; - self.owner.PlayerPhysplug = spiderbot_pplug; - self.owner.vehicle = self; - self.owner.event_damage = SUB_Null; - self.owner.hud = HUD_SPIDERBOT; - self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_spiderbot_health); - self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_spiderbot_shield); - self.owner.view_ofs = '0 0 0'; - self.owner.vehicle_ammo1 = self.vehicle_ammo1; - self.owner.vehicle_ammo2 = self.vehicle_ammo2; - self.owner.vehicle_reload1 = self.vehicle_reload1; - self.owner.vehicle_reload2 = self.vehicle_reload2; - - //if(other.flags & FL_ONGROUND) - other.flags &~= FL_ONGROUND; - - //if(self.flags & FL_ONGROUND) - self.flags &~= FL_ONGROUND; - - self.team = self.owner.team; - self.flags -= FL_NOTARGET; - - if(clienttype(other) == CLIENTTYPE_REAL) + if(self.owner.flagcarried) { - msg_entity = other; - WriteByte (MSG_ONE, SVC_SETVIEWPORT); - WriteEntity(MSG_ONE, self.vehicle_viewport); - - WriteByte (MSG_ONE, SVC_SETVIEWANGLES); // 10 = SVC_SETVIEWANGLES - WriteAngle(MSG_ONE, self.tur_head.angles_x + self.angles_x); // tilt - WriteAngle(MSG_ONE, self.tur_head.angles_y + self.angles_y); // yaw - WriteAngle(MSG_ONE, 0); // roll + setattachment(self.owner.flagcarried, self.tur_head, ""); + setorigin(self.owner.flagcarried, '-20 0 120'); } } void spiderbot_exit(float eject) { entity e; - self.frame = 5; - - self.flags |= FL_NOTARGET; - + vector spot; + e = findchain(classname,"spiderbot_rocket"); while(e) { @@ -500,256 +434,203 @@ void spiderbot_exit(float eject) e = e.chain; } - self.owner.switchweapon = self.switchweapon; - - self.velocity = '0 0 0'; - if(clienttype(self.owner) == CLIENTTYPE_REAL) - { - msg_entity = self.owner; - WriteByte (MSG_ONE, SVC_SETVIEWPORT); - WriteEntity( MSG_ONE, self.owner); - - WriteByte (MSG_ONE, SVC_SETVIEWANGLES); // 10 = SVC_SETVIEWANGLES - WriteAngle(MSG_ONE, 0); // tilt - WriteAngle(MSG_ONE, self.angles_y); // yaw - WriteAngle(MSG_ONE, 0); // roll - } - - self.think = spiderbot_think; - self.nextthink = time; - self.owner.takedamage = DAMAGE_AIM; - self.owner.solid = SOLID_SLIDEBOX; - self.owner.movetype = MOVETYPE_WALK; - - setsize(self.owner,PL_MIN,PL_MAX); - - self.owner.alpha = 1; - self.owner.PlayerPhysplug = SUB_Null; - self.owner.vehicle = world; - self.owner.view_ofs = PL_VIEW_OFS; - self.owner.hud = HUD_NORMAL; - self.owner.event_damage = PlayerDamage; - - self.colormap = 1024; - self.tur_head.colormap = 1024; - - if not (teams_matter) - self.team = 0; - else - { - self.team = self.spiderbot_spawnpnt.team ; - if (self.team == COLOR_TEAM1) self.colormod = '1.4 0.8 0.8'; - if (self.team == COLOR_TEAM2) self.colormod = '0.8 0.8 1.4'; - self.tur_head.colormod = self.colormod; - } - - self.vehicle_hudmodel.viewmodelforclient = self; - self.tur_head.nodrawtoclient = self; - - setattachment(self.owner,world,""); + self.velocity = '0 0 0'; + self.think = spiderbot_think; + self.nextthink = time; + self.frame = 5; + self.movetype = MOVETYPE_WALK; + + if not (self.owner) + return; makevectors(self.angles); if(eject) { - setorigin(self.owner,self.origin + v_forward * 100 + '0 0 64'); + spot = self.origin + v_forward * 100 + '0 0 64'; + spot = vehicles_findgoodexit(spot); + setorigin(self.owner , spot); self.owner.velocity = (v_up + v_forward * 0.25) * 750; } else - setorigin(self.owner,self.origin - v_forward * 200 + '0 0 64'); - + { + spot = self.origin - v_forward * 200 + '0 0 64'; + spot = vehicles_findgoodexit(spot); + setorigin(self.owner , spot); + } + self.owner = world; } - -float spiderbot_crushable(entity e) +void spider_impact() { - if(e.classname == "corpse") - return 1; - - if(e.classname == "player") - return 1; - - if(e.classname == "monster_zombie") - return 1; - - return 0; + if(autocvar_g_vehicle_spiderbot_bouncepain_x) + vehilces_impact(autocvar_g_vehicle_spiderbot_bouncepain_x, autocvar_g_vehicle_spiderbot_bouncepain_y, autocvar_g_vehicle_spiderbot_bouncepain_z); } - -void spiderbot_touch() -{ - if(self.owner) - { - if(vlen(self.velocity) == 0) - return; - - if not (spiderbot_crushable(other)) - return; - - //todo: add check for velocity/angle here (so we dont cush players runing into us from behind) - - Damage(other,self,self.owner,autocvar_g_vehicle_spiderbot_crush_dmg,DEATH_SBCRUSH,'0 0 0', normalize(other.origin - self.origin) * autocvar_g_vehicle_spiderbot_crush_force ); - return; - } - - if(other.classname != "player") - return; - - if(other.deadflag != DEAD_NO) - return; - - if(other.vehicle != world) - return; - - spiderbot_enter(); -} - -float spiderbot_customizeentityforclient() +void spiderbot_spawn() { - if(self.deadflag == DEAD_DEAD) - return FALSE; - - return TRUE; + self.frame = 5; + self.tur_head.frame = 1; + self.think = spiderbot_think; + self.nextthink = time; + self.vehicle_health = autocvar_g_vehicle_spiderbot_health; + self.vehicle_shield = autocvar_g_vehicle_spiderbot_shield; + self.movetype = MOVETYPE_WALK; + self.solid = SOLID_SLIDEBOX; + self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = 1; + self.tur_head.angles = '0 0 0'; + + setorigin(self, self.pos1 + '0 0 128'); + self.angles = self.pos2; + self.vehicle_impact = spider_impact; } -void spiderbot_spawn() +void spiderbot_headfade() { - self.frame = 5; - self.think = spiderbot_think; - self.nextthink = time; - - setsize(self,spiderbot_MIN,spiderbot_MAX); - - self.owner = world; - self.velocity = '0 0 0'; - self.vehicle_health = CCVAR("_health"); - self.vehicle_shield = CCVAR("_shield"); - self.event_damage = vehicle_stdproc_damage; - self.iscreature = TRUE; - self.movetype = MOVETYPE_WALK; - self.solid = SOLID_SLIDEBOX; - self.takedamage = DAMAGE_AIM; - self.touch = spiderbot_touch; - self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = 1; - self.tur_head.angles = '0 0 0'; - self.colormap = 1024; - self.tur_head.colormap = 1024; - self.deadflag = DEAD_NO; - self.bot_attack = TRUE; - self.flags |= FL_NOTARGET; - self.vehicle_hudmodel.viewmodelforclient = self; - self.tur_head.frame = 1; - - setorigin(self,self.spiderbot_spawnpnt.origin + '0 0 1.25' * spiderbot_MAX_z); - self.angles = self.spiderbot_spawnpnt.angles; - - if (self.team == COLOR_TEAM1) - self.colormod = '1.4 0.8 0.8'; - else if (self.team == COLOR_TEAM2) - self.colormod = '0.8 0.8 1.4'; - else - self.colormod = '0 0 0'; - - self.tur_head.colormod = self.colormod; - + self.think = spiderbot_headfade; + self.nextthink = self.fade_time; + self.alpha = 1 - (time - self.fade_time) * self.fade_rate; - pointparticles(particleeffectnum("teleport"), self.origin + '0 0 64', '0 0 0', 1); + if(self.cnt < time || self.alpha < 0.1) + { + if(self.alpha > 0.1) + { + sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("explosion_big"), self.origin + '0 0 100', '0 0 0', 1); + } + remove(self); + } } void spiderbot_blowup() { - sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); - pointparticles(particleeffectnum("rocket_explode"), findbetterlocation (self.origin, 16), '0 0 0', 1); + if(self.cnt > time) + { + if(random() < 0.1) + { + sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("explosion_small"), randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1); + } + self.nextthink = time + 0.1; + return; + } + + entity h, g1, g2, b; + b = spawn(); + h = spawn(); + g1 = spawn(); + g2 = spawn(); + + setmodel(b, "models/vehicles/spiderbot.dpm"); + setmodel(h, "models/vehicles/spiderbot_top.dpm"); + setmodel(g1, "models/vehicles/spiderbot_barrels.dpm"); + setmodel(g2, "models/vehicles/spiderbot_barrels.dpm"); + + setorigin(b, self.origin); + b.frame = 11; + b.angles = self.angles; + setsize(b, self.mins, self.maxs); + + setorigin(h, gettaginfo(self, gettagindex(self, "tag_head"))); + h.movetype = MOVETYPE_BOUNCE; + h.solid = SOLID_BBOX; + h.velocity = v_up * (500 + random() * 500) + randomvec() * 128; + h.modelflags = MF_ROCKET; + h.effects = EF_FLAME | EF_LOWPRECISION; + h.avelocity = randomvec() * 360; + + h.alpha = 1; + h.cnt = time + (3.5 * random()); + h.fade_rate = 1 / min(autocvar_g_vehicle_spiderbot_respawntime, 10); + h.fade_time = time; + h.think = spiderbot_headfade; + h.nextthink = time; + + setorigin(g1, gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_hardpoint01"))); + g1.movetype = MOVETYPE_TOSS; + g1.solid = SOLID_CORPSE; + g1.velocity = v_forward * 700 + (randomvec() * 32); + g1.avelocity = randomvec() * 180; + + setorigin(g2, gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_hardpoint02"))); + g2.movetype = MOVETYPE_TOSS; + g2.solid = SOLID_CORPSE; + g2.velocity = v_forward * 700 + (randomvec() * 32); + g2.avelocity = randomvec() * 180; + + h.colormod = b.colormod = g1.colormod = g2.colormod = '-2 -2 -2'; + + SUB_SetFade(b, time + 5, min(autocvar_g_vehicle_spiderbot_respawntime, 1)); + //SUB_SetFade(h, time, min(autocvar_g_vehicle_spiderbot_respawntime, 10)); + SUB_SetFade(g1, time, min(autocvar_g_vehicle_spiderbot_respawntime, 10)); + SUB_SetFade(g2, time, min(autocvar_g_vehicle_spiderbot_respawntime, 10)); RadiusDamage (self, self, 250, 15, 250, world, 250, DEATH_SBBLOWUP, world); self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = -1; - self.nextthink = time + autocvar_g_vehicle_spiderbot_respawntime; - self.think = spiderbot_spawn; self.movetype = MOVETYPE_NONE; - - setorigin(self, self.tur_aimpos); + self.deadflag = DEAD_DEAD; + self.solid = SOLID_NOT; + self.tur_head.effects &~= EF_FLAME; + self.vehicle_hudmodel.viewmodelforclient = self; } void spiderbot_die() { - - self.health = 0; - self.event_damage = SUB_Null; - self.iscreature = FALSE; - self.solid = SOLID_NOT; - self.takedamage = DAMAGE_NO; - self.touch = SUB_Null; - self.nextthink = time + random() * 2; - self.think = spiderbot_blowup; - self.deadflag = DEAD_DEAD; - self.vehicle_hudmodel.viewmodelforclient = self; - self.frame = 0; - self.tur_head.frame = 1; - + self.health = 0; + self.event_damage = SUB_Null; + self.takedamage = DAMAGE_NO; + self.touch = SUB_Null; + self.cnt = 3.4 + time + random() * 2; + self.think = spiderbot_blowup; + self.nextthink = time; + self.deadflag = DEAD_DYING; + self.frame = 5; + self.tur_head.effects |= EF_FLAME; + self.colormod = self.tur_head.colormod = '-1 -1 -1'; + self.frame = 10; + self.movetype = MOVETYPE_TOSS; } void vewhicle_spiderbot_dinit() { + if not (vehicle_initialize( + "Spiderbot", + "models/vehicles/spiderbot.dpm", + "models/vehicles/spiderbot_top.dpm", + "models/vehicles/spiderbot_cockpit.dpm", + "tag_head", "tag_hud", "", + HUD_SPIDERBOT, + SPIDERBOT_MIN, SPIDERBOT_MAX, + FALSE, + spiderbot_spawn, autocvar_g_vehicle_spiderbot_respawntime, + spiderbot_frame, + spiderbot_enter, spiderbot_exit, + spiderbot_die, spiderbot_think, + FALSE)) + { + remove(self); + return; + } - self.spiderbot_spawnpnt = spawn(); - self.spiderbot_spawnpnt.angles = self.angles; - - setorigin(self,self.origin); - tracebox(self.origin + '0 0 100', spiderbot_MIN, spiderbot_MAX, self.origin - '0 0 10000', MOVE_WORLDONLY, self); - setorigin(self.spiderbot_spawnpnt,trace_endpos); - - if(self.team && !teams_matter) - self.team = 0; - else - self.spiderbot_spawnpnt.team = self.team; - - addstat(STAT_HUD, AS_INT, hud); - addstat(STAT_VEHICLESTAT_HEALTH, AS_FLOAT, vehicle_health); - addstat(STAT_VEHICLESTAT_SHIELD, AS_FLOAT, vehicle_shield); - addstat(STAT_VEHICLESTAT_ENERGY, AS_FLOAT, vehicle_energy); - addstat(STAT_VEHICLESTAT_AMMO1, AS_INT, vehicle_ammo1); - addstat(STAT_VEHICLESTAT_RELOAD1, AS_FLOAT, vehicle_reload1); - addstat(STAT_VEHICLESTAT_AMMO2, AS_INT, vehicle_ammo2); - addstat(STAT_VEHICLESTAT_RELOAD2, AS_FLOAT, vehicle_reload2); - - if (self.netname == "") - self.netname = "spiderbot"; - self.tur_head = spawn(); self.gun1 = spawn(); self.gun2 = spawn(); - self.vehicle_viewport = spawn(); - self.vehicle_hudmodel = spawn(); - self.vehicle_flags = VHF_HASSHIELD | VHF_SHIELDREGEN | VHF_HEALTHREGEN | VHF_DEATHEJECT; - self.cvar_basename = "g_vehicle_spiderbot"; - self.gravity = 2; - setmodel(self, "models/vehicles/spiderbot.dpm"); - setmodel(self.tur_head, "models/vehicles/spiderbot_top.dpm"); setmodel(self.gun1, "models/vehicles/spiderbot_barrels.dpm"); setmodel(self.gun2, "models/vehicles/spiderbot_barrels.dpm"); - setmodel(self.vehicle_hudmodel, "models/vehicles/spiderbot_cockpit.dpm"); - setmodel(self.vehicle_viewport, "null"); - - setattachment(self.tur_head, self, "tag_head"); - setattachment(self.vehicle_hudmodel, self.tur_head, "tag_hud"); - setattachment(self.vehicle_viewport, self.vehicle_hudmodel, ""); setattachment(self.gun1, self.tur_head, "tag_hardpoint01"); setattachment(self.gun2, self.tur_head, "tag_hardpoint02"); - self.tur_head.owner = self; - self.customizeentityforclient = spiderbot_customizeentityforclient; - - self.tur_aimpos = self.origin; - - spiderbot_spawn(); - - self.vehicle_die = spiderbot_die; - self.vehicle_exit = spiderbot_exit; + self.gravity = 2; + self.mass = 5000; } void spawnfunc_vehicle_spiderbot() { + self.vehicle_flags |= VHF_DMGSHAKE; + //self.vehicle_flags |= VHF_DMGROLL; + //self.vehicle_flags |= VHF_DMGHEADROLL; + precache_model ( "models/vhshield.md3"); precache_model ( "models/vehicles/spiderbot.dpm"); precache_model ( "models/vehicles/spiderbot_top.dpm"); @@ -757,9 +638,31 @@ void spawnfunc_vehicle_spiderbot() precache_model ( "models/vehicles/spiderbot_cockpit.dpm"); precache_model ( "models/uziflash.md3"); - precache_sound ( "weapons/rocket_impact.wav" ); - - //self.team = -1; + precache_sound ( "weapons/uzi_fire.wav" ); + precache_sound ( "weapons/rocket_impact.wav"); + + precache_sound ( "vehicles/spiderbot_die.wav"); + precache_sound ( "vehicles/spiderbot_idle.wav"); + precache_sound ( "vehicles/spiderbot_jump.wav"); + precache_sound ( "vehicles/spiderbot_strafe.wav"); + precache_sound ( "vehicles/spiderbot_walk.wav"); + precache_sound ( "vehicles/spiderbot_land.wav"); + + vehicles_configcheck("vehicle_spiderbot.cfg", autocvar_g_vehicle_spiderbot_health); + if(autocvar_g_vehicle_spiderbot_shield) + self.vehicle_flags |= VHF_HASSHIELD; + + if(autocvar_g_vehicle_spiderbot_shield_regen) + self.vehicle_flags |= VHF_SHIELDREGEN; + + if(autocvar_g_vehicle_spiderbot_health_regen) + self.vehicle_flags |= VHF_HEALTHREGEN; + self.think = vewhicle_spiderbot_dinit; - self.nextthink = time + 0.5; + + if(g_assault) + self.nextthink = time + 0.5; + else + self.nextthink = time + (autocvar_g_vehicles_delayspawn ? autocvar_g_vehicle_spiderbot_respawntime + (random() * autocvar_g_vehicles_delayspawn_jitter) : 0.5); } +#endif // SVQC diff --git a/qcsrc/server/vehicles/vehicles.qc b/qcsrc/server/vehicles/vehicles.qc index 7cc2949f6d..8063c2791f 100644 --- a/qcsrc/server/vehicles/vehicles.qc +++ b/qcsrc/server/vehicles/vehicles.qc @@ -1,53 +1,686 @@ -void vehicle_stdproc_enter() +float autocvar_g_vehicles_crush_dmg; +float autocvar_g_vehicles_crush_force; +float autocvar_g_vehicles_delayspawn; +float autocvar_g_vehicles_delayspawn_jitter; +float autocvar_g_vehicles_allow_flagcarry; + +void vehicles_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force); +void vehicles_return(); +void vehicles_enter(); +void vehicles_touch(); +void vehicles_reset_colors(); +void vehicles_clearrturn(); +void vehicles_setreturn(); + + +/** AuxiliaryXhair* + Send additional points of interest to be drawn, to vehicle owner +**/ +float MAX_AXH = 4; +.entity AuxiliaryXhair[MAX_AXH]; + +float SendAuxiliaryXhair(entity to, float sf) { + + WriteByte(MSG_ENTITY, ENT_CLIENT_AUXILIARYXHAIR); + + WriteByte(MSG_ENTITY, self.cnt); + + WriteCoord(MSG_ENTITY, self.origin_x); + WriteCoord(MSG_ENTITY, self.origin_y); + WriteCoord(MSG_ENTITY, self.origin_z); + + WriteByte(MSG_ENTITY, rint(self.colormod_x * 255)); + WriteByte(MSG_ENTITY, rint(self.colormod_y * 255)); + WriteByte(MSG_ENTITY, rint(self.colormod_z * 255)); + + return TRUE; } -void vehicle_stdproc_exit(float eject) +void UpdateAuxiliaryXhair(entity own, vector loc, vector clr, float axh_id) { + entity axh; + + axh_id = bound(0, axh_id, MAX_AXH); + axh = own.(AuxiliaryXhair[axh_id]); + + if(axh == world || wasfreed(axh)) // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist?) + { + axh = spawn(); + axh.cnt = axh_id; + axh.drawonlytoclient = own; + axh.owner = own; + Net_LinkEntity(axh, FALSE, 0, SendAuxiliaryXhair); + } + + setorigin(axh, loc); + axh.colormod = clr; + axh.SendFlags = 0x01; + own.(AuxiliaryXhair[axh_id]) = axh; } -void vehicle_stdproc_shiledregen(float rmax, float dt) +/* +// SVC_TEMPENTITY based, horrible with even 50 ping. hm. +// WriteByte(MSG_ONE, SVC_TEMPENTITY) uses reliable messagess, never use for thinsg that need continous updates. +void SendAuxiliaryXhair2(entity own, vector loc, vector clr, float axh_id) { - if(self.vehicle_shield < rmax) - if(self.dmg_time + CCVAR("_shield_regen_dmgpause") < time) + msg_entity = own; + + WriteByte(MSG_ONE, SVC_TEMPENTITY); + WriteByte(MSG_ONE, TE_CSQC_AUXILIARYXHAIR); + + WriteByte(MSG_ONE, axh_id); + + WriteCoord(MSG_ONE, loc_x); + WriteCoord(MSG_ONE, loc_y); + WriteCoord(MSG_ONE, loc_z); + + WriteByte(MSG_ONE, rint(clr_x * 255)); + WriteByte(MSG_ONE, rint(clr_y * 255)); + WriteByte(MSG_ONE, rint(clr_z * 255)); + +} +*/ +// End AuxiliaryXhair + +/** + Notifies the client that he enterd a vehicle, and sends + realavent data. + + only sends vehicle_id atm (wich is a HUD_* constant, ex. HUD_SPIDERBOT) +**/ +void CSQCVehicleSetup(entity own, float vehicle_id) +{ + msg_entity = own; + + WriteByte(MSG_ONE, SVC_TEMPENTITY); + WriteByte(MSG_ONE, TE_CSQC_VEHICLESETUP); + WriteByte(MSG_ONE, vehicle_id); +} + +/** vehicles_locktarget + + Generic target locking. + + Figure out if what target is "locked" (if any), for missile tracking as such. + + after calling, "if(self.lock_target != world && self.lock_strength == 1)" mean + you have a locked in target. + + Exspects a crosshair_trace() or equivalent to be + dont before calling. + +**/ +.entity lock_target; +.float lock_strength; +.float lock_time; +.float lock_soundtime; +void vehicles_locktarget(float incr, float decr, float _lock_time) +{ + if(self.lock_target && self.lock_target.deadflag != DEAD_NO) { - self.vehicle_shield = min(self.vehicle_shield + CCVAR("_shield_regen") * dt, rmax); + self.lock_target = world; + self.lock_strength = 0; + self.lock_time = 0; + } - if(self.owner) - self.owner.vehicle_shield = self.vehicle_shield / rmax; + if(self.lock_time > time) + { + if(self.lock_target) + if(self.lock_soundtime < time) + { + self.lock_soundtime = time + 0.5; + play2(self.owner, "vehicles/locked.wav"); + } + + return; + } + + if(trace_ent != world) + { + if(teamplay && trace_ent.team == self.team) + trace_ent = world; + + if(trace_ent.deadflag != DEAD_NO) + trace_ent = world; + + if not (trace_ent.vehicle_flags & VHF_ISVEHICLE || trace_ent.turrcaps_flags & TFL_TURRCAPS_ISTURRET) + trace_ent = world; + } + + if(self.lock_target == world && trace_ent != world) + self.lock_target = trace_ent; + + if(self.lock_target && trace_ent == self.lock_target) + { + if(self.lock_strength != 1 && self.lock_strength + incr >= 1) + { + play2(self.owner, "vehicles/lock.wav"); + self.lock_soundtime = time + 0.8; + } + else if (self.lock_strength != 1 && self.lock_soundtime < time) + { + play2(self.owner, "vehicles/locking.wav"); + self.lock_soundtime = time + 0.3; + } + + } + + // Have a locking target + // Trace hit current target + if(trace_ent == self.lock_target && trace_ent != world) + { + self.lock_strength = min(self.lock_strength + incr, 1); + if(self.lock_strength == 1) + self.lock_time = time + _lock_time; + } + else + { + if(trace_ent) + self.lock_strength = max(self.lock_strength - decr * 2, 0); + else + self.lock_strength = max(self.lock_strength - decr, 0); + + if(self.lock_strength == 0) + self.lock_target = world; } } -void vehicle_stdproc_healthregen(float rmax, float dt) +#define VEHICLE_UPDATE_PLAYER(fld,vhname) \ +self.owner.vehicle_##fld = (self.vehicle_##fld / autocvar_g_vehicle_##vhname##_##fld) * 100 + +#define vehicles_sweap_collision(orig,vel,dt,acm,mult) \ +traceline(orig, orig + vel * dt, MOVE_NORMAL, self); \ +if(trace_fraction != 1) \ + acm += normalize(self.origin - trace_endpos) * (vlen(vel) * mult) + +// Hover movement support +float force_fromtag_power; +float force_fromtag_normpower; +vector force_fromtag_origin; +vector vehicles_force_fromtag_hover(string tag_name, float spring_length, float max_power) { + force_fromtag_origin = gettaginfo(self, gettagindex(self, tag_name)); + v_forward = normalize(v_forward) * -1; + traceline(force_fromtag_origin, force_fromtag_origin - (v_forward * spring_length), MOVE_NORMAL, self); + + force_fromtag_power = (1 - trace_fraction) * max_power; + force_fromtag_normpower = force_fromtag_power / max_power; + + return v_forward * force_fromtag_power; +} + +// Experimental hovermode wich uses attraction/repulstion from surface insted of gravity/repulsion +// Can possibly be use to move abt any surface (inclusing walls/celings) +vector vehicles_force_fromtag_maglev(string tag_name, float spring_length, float max_power) +{ + + force_fromtag_origin = gettaginfo(self, gettagindex(self, tag_name)); + v_forward = normalize(v_forward) * -1; + traceline(force_fromtag_origin, force_fromtag_origin - (v_forward * spring_length), MOVE_NORMAL, self); - if(self.dmg_time + CCVAR("_health_regen_dmgpause") < time) - if(self.vehicle_health < rmax) + // TODO - this may NOT be compatible with wall/celing movement, unhardcode 0.25 (engine count multiplier) + if(trace_fraction == 1.0) { - self.vehicle_health = min(self.vehicle_health + CCVAR("_health_regen") * dt, rmax); + force_fromtag_normpower = -0.25; + return '0 0 -200'; + } - if(self.owner) - self.owner.vehicle_health = self.vehicle_health / rmax; + force_fromtag_power = ((1 - trace_fraction) - trace_fraction) * max_power; + force_fromtag_normpower = force_fromtag_power / max_power; + + return v_forward * force_fromtag_power; +} + +// Generic vehile projectile system +void vehicles_projectile_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) +{ + // Ignore damage from oterh projectiles from my owner (dont mess up volly's) + if(inflictor.owner == self.owner) + return; + + self.health -= damage; + self.velocity += force; + if(self.health < 1) + { + self.takedamage = DAMAGE_NO; + self.event_damage = SUB_Null; + self.think = self.use; + self.nextthink = time; } + } -void vehicle_stdproc_energyregen(float rmax, float dt) +void vehicles_projectile_explode() { - if(self.vehicle_energy < rmax) + if(self.owner && other != world) { - self.vehicle_energy = min(self.vehicle_energy + CCVAR("_energy_regen") * dt, rmax); + if(other == self.owner.vehicle) + return; + + if(other == self.owner.vehicle.tur_head) + return; + } + + PROJECTILE_TOUCH; + + self.event_damage = SUB_Null; + RadiusDamage (self, self.realowner, self.shot_dmg, 0, self.shot_radius, self, self.shot_force, self.totalfrags, other); + + remove (self); +} + +entity vehicles_projectile(string _mzlfx, string _mzlsound, + vector _org, vector _vel, + float _dmg, float _radi, float _force, float _size, + float _deahtype, float _projtype, float _health, + float _cull, float _clianim) +{ + entity proj; + + proj = spawn(); + + PROJECTILE_MAKETRIGGER(proj); + setorigin(proj, _org); + + proj.shot_dmg = _dmg; + proj.shot_radius = _radi; + proj.shot_force = _force; + proj.totalfrags = _deahtype; + proj.solid = SOLID_BBOX; + proj.movetype = MOVETYPE_FLYMISSILE; + proj.flags = FL_PROJECTILE; + proj.bot_dodge = TRUE; + proj.bot_dodgerating = _dmg; + proj.velocity = _vel; + proj.touch = vehicles_projectile_explode; + proj.use = vehicles_projectile_explode; + proj.owner = self; + proj.realowner = self.owner; + proj.think = SUB_Remove; + proj.nextthink = time + 30; + + if(_health) + { + proj.takedamage = DAMAGE_AIM; + proj.event_damage = vehicles_projectile_damage; + proj.health = _health; + } + else + proj.flags = FL_PROJECTILE | FL_NOTARGET; + + if(_mzlsound) + sound (self, CH_WEAPON_A, _mzlsound, VOL_BASE, ATTN_NORM); + + if(_mzlfx) + pointparticles(particleeffectnum(_mzlfx), proj.origin, proj.velocity, 1); + + + setsize (proj, '-1 -1 -1' * _size, '1 1 1' * _size); + + CSQCProjectile(proj, _clianim, _projtype, _cull); + + return proj; +} +// End generic vehile projectile system + +/** vehicles_spawn + Exetuted for all vehicles on (re)spawn. + Sets defaults for newly spawned units. +**/ +void vehicles_spawn() +{ + dprint("Spawning vehicle: ", self.netname, "\n"); + + // De-own & reset + self.vehicle_hudmodel.viewmodelforclient = self; + + self.owner = world; + self.touch = vehicles_touch; + self.event_damage = vehicles_damage; + self.iscreature = TRUE; + self.damagedbycontents = TRUE; + self.movetype = MOVETYPE_WALK; + self.solid = SOLID_SLIDEBOX; + self.takedamage = DAMAGE_AIM; + self.deadflag = DEAD_NO; + self.bot_attack = TRUE; + self.flags = FL_NOTARGET; + self.avelocity = '0 0 0'; + self.velocity = '0 0 0'; + + // Reset locking + self.lock_strength = 0; + self.lock_target = world; + self.misc_bulletcounter = 0; + + // Return to spawn + self.angles = self.pos2; + setorigin(self, self.pos1 + '0 0 0'); + // Show it + pointparticles(particleeffectnum("teleport"), self.origin + '0 0 64', '0 0 0', 1); + + vehicles_reset_colors(); + self.vehicle_spawn(); +} + +// Better way of determening whats crushable needed! (fl_crushable?) +float vehicles_crushable(entity e) +{ + if(e.classname == "player") + return TRUE; + + if(e.classname == "monster_zombie") + return TRUE; + + return FALSE; +} + +void vehilces_impact(float _minspeed, float _speedfac, float _maxpain) +{ + if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT) + return; + + if(self.play_time < time) + { + float wc = vlen(self.velocity - self.oldvelocity); + //dprint("oldvel: ", vtos(self.oldvelocity), "\n"); + //dprint("vel: ", vtos(self.velocity), "\n"); + if(_minspeed < wc) + { + float take = take = min(_speedfac * wc, _maxpain); + Damage (self, world, world, take, DEATH_FALL, self.origin, '0 0 0'); + self.play_time = time + 0.25; + + //dprint("wc: ", ftos(wc), "\n"); + //dprint("take: ", ftos(take), "\n"); + } + } +} + +.void() vehicle_impact; +void vehicles_touch() +{ + // Vehicle currently in use + if(self.owner) + { + if(other != world) + if(vehicles_crushable(other)) + { + if(vlen(self.velocity) != 0) + Damage(other, self, self.owner, autocvar_g_vehicles_crush_dmg, DEATH_VHCRUSH, '0 0 0', normalize(other.origin - self.origin) * autocvar_g_vehicles_crush_force); + + return; // Dont do selfdamage when hitting "soft targets". + } + + if(self.play_time < time) + if(self.vehicle_impact) + self.vehicle_impact(); + + return; + } + + if(other.classname != "player") + return; + + if(other.deadflag != DEAD_NO) + return; + + if(other.vehicle != world) + return; + + // Remove this when bots know how to use vehicles. + if (clienttype(other) != CLIENTTYPE_REAL) + return; + + vehicles_enter(); +} + +void vehicles_enter() +{ + // Remove this when bots know how to use vehicles + if (clienttype(other) != CLIENTTYPE_REAL) + return; + + if(self.phase > time) + return; + + if(teamplay) + if(self.team) + if(self.team != other.team) + return; + + RemoveGrapplingHook(other); + + self.vehicle_ammo1 = 0; + self.vehicle_ammo2 = 0; + self.vehicle_reload1 = 0; + self.vehicle_reload2 = 0; + self.vehicle_energy = 0; + + self.owner = other; + self.switchweapon = other.switchweapon; + + // .viewmodelforclient works better. + //self.vehicle_hudmodel.drawonlytoclient = self.owner; + + self.vehicle_hudmodel.viewmodelforclient = self.owner; + + self.event_damage = vehicles_damage; + self.nextthink = 0; + self.owner.angles = self.angles; + self.owner.takedamage = DAMAGE_NO; + self.owner.solid = SOLID_NOT; + self.owner.movetype = MOVETYPE_NOCLIP; + self.owner.alpha = -1; + self.owner.vehicle = self; + self.owner.event_damage = SUB_Null; + self.owner.view_ofs = '0 0 0'; + self.colormap = self.owner.colormap; + if(self.tur_head) + self.tur_head.colormap = self.owner.colormap; + + self.owner.hud = self.hud; + self.owner.PlayerPhysplug = self.PlayerPhysplug; + + self.owner.vehicle_ammo1 = self.vehicle_ammo1; + self.owner.vehicle_ammo2 = self.vehicle_ammo2; + self.owner.vehicle_reload1 = self.vehicle_reload1; + self.owner.vehicle_reload2 = self.vehicle_reload2; + + // Cant do this, hides attached objects too. + //self.exteriormodeltoclient = self.owner; + //self.tur_head.exteriormodeltoclient = self.owner; + + other.flags &~= FL_ONGROUND; + self.flags &~= FL_ONGROUND; + + self.team = self.owner.team; + self.flags -= FL_NOTARGET; + + msg_entity = other; + WriteByte (MSG_ONE, SVC_SETVIEWPORT); + WriteEntity(MSG_ONE, self.vehicle_viewport); + + WriteByte (MSG_ONE, SVC_SETVIEWANGLES); + if(self.tur_head) + { + WriteAngle(MSG_ONE, self.tur_head.angles_x + self.angles_x); // tilt + WriteAngle(MSG_ONE, self.tur_head.angles_y + self.angles_y); // yaw + WriteAngle(MSG_ONE, 0); // roll + } + else + { + WriteAngle(MSG_ONE, self.angles_x * -1); // tilt + WriteAngle(MSG_ONE, self.angles_y); // yaw + WriteAngle(MSG_ONE, 0); // roll + } + + vehicles_clearrturn(); + + CSQCVehicleSetup(self.owner, self.hud); + + if(other.flagcarried) + { + if(!autocvar_g_vehicles_allow_flagcarry) + DropFlag(other.flagcarried, world, world); + else + { + other.flagcarried.scale = 1; + setattachment(other.flagcarried, self, ""); + setorigin(other, '0 0 96'); + } + } + + self.vehicle_enter(); +} + +/** vehicles_findgoodexit + Locates a valid location for the player to exit the vehicle. + Will first try prefer_spot, then up 100 random spots arround the vehicle + wich are in direct line of sight and empty enougth to hold a players bbox +**/ +vector vehicles_findgoodexit(vector prefer_spot) +{ + //vector exitspot; + float mysize; + + tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, prefer_spot, MOVE_NORMAL, self.owner); + if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid) + return prefer_spot; + + mysize = vlen(self.maxs - self.mins); + float i; + vector v, v2; + v2 = 0.5 * (self.absmin + self.absmax); + for(i = 0; i < 100; ++i) + { + v = randomvec(); + v_z = 0; + v = v2 + normalize(v) * mysize; + tracebox(v2, PL_MIN, PL_MAX, v, MOVE_NORMAL, self.owner); + if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid) + return v; + } + + /* + exitspot = (self.origin + '0 0 48') + v_forward * mysize; + tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner); + if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid) + return exitspot; + + exitspot = (self.origin + '0 0 48') - v_forward * mysize; + tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner); + if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid) + return exitspot; + + exitspot = (self.origin + '0 0 48') + v_right * mysize; + tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner); + if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid) + return exitspot; + + exitspot = (self.origin + '0 0 48') - v_right * mysize; + tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner); + if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid) + return exitspot; + */ + + return self.origin; +} + +/** vehicles_exit + Standarrd vehicle release fucntion. + custom code goes in self.vehicle_exit +**/ +void vehicles_exit(float eject) +{ + entity oldself; + if(self.flags & FL_CLIENT) + { + oldself = self; + self = self.vehicle; + } + + self.flags |= FL_NOTARGET; + + if (self.owner) + { + msg_entity = self.owner; + WriteByte (MSG_ONE, SVC_SETVIEWPORT); + WriteEntity( MSG_ONE, self.owner); + + WriteByte (MSG_ONE, SVC_SETVIEWANGLES); + WriteAngle(MSG_ONE, 0); // pich + WriteAngle(MSG_ONE, self.angles_y); // yaw + WriteAngle(MSG_ONE, 0); // roll + + setsize(self.owner, PL_MIN,PL_MAX); + + self.owner.takedamage = DAMAGE_AIM; + self.owner.solid = SOLID_SLIDEBOX; + self.owner.movetype = MOVETYPE_WALK; + self.owner.effects &~= EF_NODRAW; + self.owner.alpha = 1; + self.owner.PlayerPhysplug = SUB_Null; + self.owner.vehicle = world; + self.owner.view_ofs = PL_VIEW_OFS; + self.owner.event_damage = PlayerDamage; + self.owner.hud = HUD_NORMAL; + self.owner.switchweapon = self.switchweapon; + //self.owner.BUTTON_USE = 0; + + CSQCVehicleSetup(self.owner, HUD_NORMAL); + } + + if(self.deadflag == DEAD_NO) + self.avelocity = '0 0 0'; + + self.vehicle_hudmodel.viewmodelforclient = self; + self.tur_head.nodrawtoclient = world; + vehicles_setreturn(); + + self.phase = time + 1; + + if(!teamplay) + self.team = 0; + else + self.team = self.tur_head.team; + + if(self.owner.flagcarried) + { + self.owner.flagcarried.scale = 0.6; + setattachment(self.owner.flagcarried, self.owner, ""); + setorigin(self.owner.flagcarried, FLAG_CARRY_POS); + } + + sound (self, CH_TRIGGER_SINGLE, "misc/null.wav", 1, ATTN_NORM); + self.vehicle_exit(eject); + self.owner = world; + vehicles_reset_colors(); + + if(oldself) + self = oldself; +} + + +void vehicles_regen(.float timer, .float regen_field, float field_max, float rpause, float regen, float delta_time) +{ + if(self.regen_field < field_max) + if(self.timer + rpause < time) + { + self.regen_field = min(self.regen_field + regen * delta_time, field_max); if(self.owner) - self.owner.vehicle_energy = self.vehicle_energy / rmax; + self.owner.regen_field = (self.regen_field / field_max) * 100; } } void shieldhit_think() { - self.alpha = self.alpha - 0.2; + self.alpha -= 0.1; if (self.alpha <= 0) { - setmodel(self,""); + //setmodel(self, ""); self.alpha = -1; } else @@ -56,65 +689,363 @@ void shieldhit_think() } } -void vehicle_stdproc_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) -{ - - float ddmg_take; +void vehicles_painframe() +{ + if(self.owner.vehicle_health <= 50) + if(self.pain_frame < time) + { + float _ftmp; + _ftmp = self.owner.vehicle_health / 50; + self.pain_frame = time + 0.1 + (random() * 0.5 * _ftmp); + pointparticles(particleeffectnum("smoke_small"), (self.origin + (randomvec() * 80)), '0 0 0', 1); + + if(self.vehicle_flags & VHF_DMGSHAKE) + self.velocity += randomvec() * 30; + + if(self.vehicle_flags & VHF_DMGROLL) + if(self.vehicle_flags & VHF_DMGHEADROLL) + self.tur_head.angles += randomvec(); + else + self.angles += randomvec(); + + } +} +void vehicles_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) +{ self.dmg_time = time; if((self.vehicle_flags & VHF_HASSHIELD) && (self.vehicle_shield > 0)) { - - - if (wasfreed(self.tur_head.enemy) || self.tur_head.enemy == world) + if (wasfreed(self.vehicle_shieldent) || self.vehicle_shieldent == world) { - self.tur_head.enemy = spawn(); - self.tur_head.enemy.effects = EF_LOWPRECISION; - } + self.vehicle_shieldent = spawn(); + self.vehicle_shieldent.effects = EF_LOWPRECISION; - setmodel(self.tur_head.enemy, "models/vhshield.md3"); - setattachment(self.tur_head.enemy, self, ""); + setmodel(self.vehicle_shieldent, "models/vhshield.md3"); + setattachment(self.vehicle_shieldent, self, ""); + setorigin(self.vehicle_shieldent, real_origin(self) - self.origin); + self.vehicle_shieldent.scale = 256 / vlen(self.maxs - self.mins); + self.vehicle_shieldent.think = shieldhit_think; + } - self.tur_head.enemy.colormod = '1 1 1'; - self.tur_head.enemy.alpha = 0.45; - self.tur_head.enemy.scale = (256 / vlen(self.maxs - self.mins)); - self.tur_head.enemy.angles = vectoangles(normalize(hitloc - self.origin)) - self.angles; - self.tur_head.enemy.think = shieldhit_think; - self.tur_head.enemy.nextthink = time; + self.vehicle_shieldent.colormod = '1 1 1'; + self.vehicle_shieldent.alpha = 0.45; + self.vehicle_shieldent.angles = vectoangles(normalize(hitloc - (self.origin + self.vehicle_shieldent.origin))) - self.angles; + self.vehicle_shieldent.nextthink = time; self.vehicle_shield -= damage; + if(self.vehicle_shield < 0) { - self.tur_head.enemy.colormod = '10 0 -1'; - ddmg_take = fabs(self.vehicle_shield); - self.vehicle_shield = 0; - self.tur_head.enemy.alpha = 0.75; - self.vehicle_health -= ddmg_take; + self.vehicle_health -= fabs(self.vehicle_shield); + self.vehicle_shieldent.colormod = '2 0 0'; + self.vehicle_shield = 0; + self.vehicle_shieldent.alpha = 0.75; + + if(sound_allowed(MSG_BROADCAST, attacker)) + spamsound (self, CH_PAIN, "onslaught/ons_hit2.wav", VOL_BASE, ATTN_NORM); // FIXME: PLACEHOLDER } + else + if(sound_allowed(MSG_BROADCAST, attacker)) + spamsound (self, CH_PAIN, "onslaught/electricity_explode.wav", VOL_BASE, ATTN_NORM); // FIXME: PLACEHOLDER + } else - self.vehicle_health -= damage; - - if(self.owner) { - self.owner.vehicle_health = self.vehicle_health / CCVAR("_health"); - - if(self.vehicle_flags & VHF_HASSHIELD) - self.owner.vehicle_shield = self.vehicle_shield / cvar(strcat(self.cvar_basename,"_shield")); + self.vehicle_health -= damage; + if(sound_allowed(MSG_BROADCAST, attacker)) + spamsound (self, CH_PAIN, "onslaught/ons_hit2.wav", VOL_BASE, ATTN_NORM); // FIXME: PLACEHOLDER } + self.velocity += force; // * (vlen(force) / self.mass); + if(self.vehicle_health <= 0) { if(self.owner) if(self.vehicle_flags & VHF_DEATHEJECT) - self.vehicle_exit(VHEF_EJECT); + vehicles_exit(VHEF_EJECT); + else + vehicles_exit(VHEF_RELESE); self.vehicle_die(); + vehicles_setreturn(); + } +} + +void vehicles_clearrturn() +{ + entity ret; + // Remove "return helper", if any. + ret = findchain(classname, "vehicle_return"); + while(ret) + { + if(ret.enemy == self) + { + ret.classname = ""; + ret.think = SUB_Remove; + ret.nextthink = time + 0.1; + + if(ret.waypointsprite_attached) + WaypointSprite_Kill(ret.waypointsprite_attached); + + return; + } + ret = ret.chain; } +} + +void vehicles_return() +{ + pointparticles(particleeffectnum("teleport"), self.enemy.origin + '0 0 64', '0 0 0', 1); + + self.enemy.think = vehicles_spawn; + self.enemy.nextthink = time; + + if(self.waypointsprite_attached) + WaypointSprite_Kill(self.waypointsprite_attached); + + remove(self); +} + +void vehicles_showwp_goaway() +{ + if(self.waypointsprite_attached) + WaypointSprite_Kill(self.waypointsprite_attached); + + remove(self); + +} + +void vehicles_showwp() +{ + entity oldself; + vector rgb; + + if(self.cnt) + { + self.think = vehicles_return; + self.nextthink = self.cnt; + } + else + { + self.think = vehicles_return; + self.nextthink = time +1; + + oldself = self; + self = spawn(); + setmodel(self, "null"); + self.team = oldself.enemy.team; + self.enemy = oldself.enemy; + setorigin(self, oldself.enemy.pos1); + + self.nextthink = time + 5; + self.think = vehicles_showwp_goaway; + } + + if(teamplay && self.team) + rgb = TeamColor(self.team); + else + rgb = '1 1 1'; + WaypointSprite_Spawn("vehicle", 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, TRUE, RADARICON_POWERUP, rgb); + if(self.waypointsprite_attached) + { + WaypointSprite_UpdateRule(self.waypointsprite_attached, self.enemy.team, SPRITERULE_DEFAULT); + if(oldself == world) + WaypointSprite_UpdateBuildFinished(self.waypointsprite_attached, self.nextthink); + WaypointSprite_Ping(self.waypointsprite_attached); + } + + if(oldself != world) + self = oldself; +} + +void vehicles_setreturn() +{ + entity ret; + + vehicles_clearrturn(); + + ret = spawn(); + ret.classname = "vehicle_return"; + ret.enemy = self; + ret.team = self.team; + ret.think = vehicles_showwp; + + if(self.deadflag != DEAD_NO) + { + ret.cnt = time + self.vehicle_respawntime; + ret.nextthink = min(time + self.vehicle_respawntime, time + self.vehicle_respawntime - 5); + } + else + { + ret.nextthink = min(time + self.vehicle_respawntime, time + self.vehicle_respawntime - 1); + } + + setmodel(ret, "null"); + setorigin(ret, self.pos1 + '0 0 96'); + +} + +void vehicles_configcheck(string configname, float check_cvar) +{ + if(check_cvar == 0) + localcmd(strcat("exec ", configname, "\n")); +} + +void vehicles_reset_colors() +{ + entity e; + float _effects, _colormap; + vector _glowmod, _colormod; + + if(autocvar_g_nodepthtestplayers) + _effects = EF_NODEPTHTEST; + + if(autocvar_g_fullbrightplayers) + _effects |= EF_FULLBRIGHT; + + if(self.team) + _colormap = 1024 + (self.team - 1) * 17; + else + _colormap = 1024; + + _glowmod = '0 0 0'; + _colormod = '0 0 0'; + + // Find all ents attacked to main model and setup effects, colormod etc. + e = findchainentity(tag_entity, self); + while(e) + { + if(e != self.vehicle_shieldent) + { + e.effects = _effects; // | EF_LOWPRECISION; + e.colormod = _colormod; + e.colormap = _colormap; + e.alpha = 1; + } + e = e.chain; + } + + self.vehicle_hudmodel.effects = self.effects = _effects; // | EF_LOWPRECISION; + self.vehicle_hudmodel.colormod = self.colormod = _colormod; + self.vehicle_hudmodel.colormap = self.colormap = _colormap; + self.vehicle_viewport.effects = (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NOGUNBOB | EF_NOSHADOW | EF_LOWPRECISION | EF_SELECTABLE | EF_TELEPORT_BIT); + + self.alpha = 1; + self.avelocity = '0 0 0'; + self.velocity = '0 0 0'; + self.effects = _effects; +} + +float vehicle_initialize(string net_name, + string bodymodel, + string topmodel, + string hudmodel, + string toptag, + string hudtag, + string viewtag, + float vhud, + vector min_s, + vector max_s, + float nodrop, + void() spawnproc, + float _respawntime, + float() physproc, + void() enterproc, + void(float extflag) exitfunc, + void() dieproc, + void() thinkproc, + float use_csqc) +{ + addstat(STAT_HUD, AS_INT, hud); + addstat(STAT_VEHICLESTAT_HEALTH, AS_INT, vehicle_health); + addstat(STAT_VEHICLESTAT_SHIELD, AS_INT, vehicle_shield); + addstat(STAT_VEHICLESTAT_ENERGY, AS_INT, vehicle_energy); + + addstat(STAT_VEHICLESTAT_AMMO1, AS_INT, vehicle_ammo1); + addstat(STAT_VEHICLESTAT_RELOAD1, AS_INT, vehicle_reload1); + + addstat(STAT_VEHICLESTAT_AMMO2, AS_INT, vehicle_ammo2); + addstat(STAT_VEHICLESTAT_RELOAD2, AS_INT, vehicle_reload2); + + if(bodymodel == "") + error("vehicles: missing bodymodel!"); + + if(hudmodel == "") + error("vehicles: missing hudmodel!"); + + if(net_name == "") + self.netname = self.classname; + else + self.netname = net_name; + + if(self.team && !teamplay) + self.team = 0; + + self.vehicle_flags |= VHF_ISVEHICLE; + + setmodel(self, bodymodel); + + self.vehicle_viewport = spawn(); + self.vehicle_hudmodel = spawn(); + self.tur_head = spawn(); + self.tur_head.owner = self; + self.takedamage = DAMAGE_AIM; + self.bot_attack = TRUE; + self.iscreature = TRUE; + self.damagedbycontents = TRUE; + self.hud = vhud; + + self.vehicle_die = dieproc; + self.vehicle_exit = exitfunc; + self.vehicle_enter = enterproc; + self.PlayerPhysplug = physproc; + self.event_damage = vehicles_damage; + self.touch = vehicles_touch; + self.think = vehicles_spawn; + self.nextthink = time; + self.vehicle_respawntime = _respawntime; + self.vehicle_spawn = spawnproc; + + if(autocvar_g_nodepthtestplayers) + self.effects = self.effects | EF_NODEPTHTEST; + + if(autocvar_g_fullbrightplayers) + self.effects = self.effects | EF_FULLBRIGHT; + + setmodel(self.vehicle_hudmodel, hudmodel); + setmodel(self.vehicle_viewport, "null"); + + if(topmodel != "") + { + setmodel(self.tur_head, topmodel); + setattachment(self.tur_head, self, toptag); + setattachment(self.vehicle_hudmodel, self.tur_head, hudtag); + setattachment(self.vehicle_viewport, self.vehicle_hudmodel, viewtag); + } + else + { + setattachment(self.tur_head, self, ""); + setattachment(self.vehicle_hudmodel, self, hudtag); + setattachment(self.vehicle_viewport, self.vehicle_hudmodel, viewtag); + } + + setsize(self, min_s, max_s); + if not (nodrop) + { + setorigin(self, self.origin); + tracebox(self.origin + '0 0 100', min_s, max_s, self.origin - '0 0 10000', MOVE_WORLDONLY, self); + setorigin(self, trace_endpos); + } + self.pos1 = self.origin; + self.pos2 = self.angles; + self.tur_head.team = self.team; + + return TRUE; } void bugmenot() @@ -123,5 +1054,5 @@ void bugmenot() self.vehicle_enter = self.vehicle_exit; self.vehicle_die = self.vehicle_exit; self.vehicle_spawn = self.vehicle_exit; - //self.vehicle_message = self.vehicle_exit; + self.AuxiliaryXhair = self.AuxiliaryXhair; } diff --git a/qcsrc/server/vehicles/vehicles.qh b/qcsrc/server/vehicles/vehicles.qh index 8e452478e2..79fc9cbf9a 100644 --- a/qcsrc/server/vehicles/vehicles.qh +++ b/qcsrc/server/vehicles/vehicles.qh @@ -1,61 +1,8 @@ -//#define VEHICLES_ENABLED #ifdef VEHICLES_ENABLED - -#message "with tZork vehicles (experimental)" - -float SVC_SETVIEWPORT = 5; // Net.Protocol 0x05 -float SVC_SETVIEWANGLES = 10; // Net.Protocol 0x0A -float SVC_UPDATEENTITY = 128; // Net.Protocol 0x80 - -#define CCVAR(part) cvar(strcat(self.cvar_basename,part)) -//.string cvar_basename; - -.float vehicle_flags; -#define VHF_HASSHIELD 2 -#define VHF_SHIELDREGEN 4 -#define VHF_HEALTHREGEN 8 -#define VHF_DEATHEJECT 16 -#define VHF_ENERGYREGEN 32 - -.float hud; - -.entity gun1; -.entity gun2; - -.entity shield; - -.float vehicle_health; -.float vehicle_shield; -.float vehicle_energy; - -.float vehicle_ammo1; -.float vehicle_reload1; - -.float vehicle_ammo2; -.float vehicle_reload2; - -.entity vehicle; -.entity vehicle_viewport; -.entity vehicle_hudmodel; - -//.float anim_start; -//.float anim_end; - -.float dmg_time; - -#define VHEF_NORMAL 0 -#define VHEF_EJECT 1 - -var .void(float exit_flags) vehicle_exit; -var .void() vehicle_enter; -var .void() vehicle_die; -var .void() vehicle_spawn; -//var .float(float message) vehicle_message; - #include "vehicles.qc" -#include "spiderbot.qc" #include "racer.qc" +#include "spiderbot.qc" #include "raptor.qc" - +//#include "bumblebee.qc" #endif diff --git a/qcsrc/server/vehicles/vehicles_def.qh b/qcsrc/server/vehicles/vehicles_def.qh new file mode 100644 index 0000000000..dcb1854f36 --- /dev/null +++ b/qcsrc/server/vehicles/vehicles_def.qh @@ -0,0 +1,65 @@ +// #define VEHICLES_USE_ODE +#define VEHICLES_ENABLED +#ifdef VEHICLES_ENABLED + +//#message "with tZork vehicles (experimental)" + +.float vehicle_flags; +float VHF_ISVEHICLE = 2; /// Indicates vehicle +float VHF_HASSHIELD = 4; /// Vehicle has shileding +float VHF_SHIELDREGEN = 8; /// Vehicles shield regenerates +float VHF_HEALTHREGEN = 16; /// Vehicles health regenerates +float VHF_ENERGYREGEN = 32; /// Vehicles energy regenerates +float VHF_DEATHEJECT = 64; /// Vehicle ejects pilot upon fatal damage +float VHF_MOVE_GROUND = 128; /// Vehicle moves on gound +float VHF_MOVE_HOVER = 256; /// Vehicle hover close to gound +float VHF_MOVE_FLY = 512; /// Vehicle is airborn +float VHF_DMGSHAKE = 1024; +float VHF_DMGROLL = 2048; +float VHF_DMGHEADROLL = 4096; + +.entity gun1; +.entity gun2; + +.float vehicle_health; /// If self is player this is 0..100 indicating precentage of health left on vehicle. If self is vehile, this is the real health value. +.float vehicle_energy; /// If self is player this is 0..100 indicating precentage of energy left on vehicle. If self is vehile, this is the real energy value. +.float vehicle_shield; /// If self is player this is 0..100 indicating precentage of shield left on vehicle. If self is vehile, this is the real shield value. +.entity vehicle_shieldent; /// Entity to disply the shild effect on damage + +.float vehicle_ammo1; /// If self is player this field's use depends on the individual vehile. If self is vehile, this is the real ammo1 value. +.float vehicle_reload1; /// If self is player this field's use depends on the individual vehile. If self is vehile, this is the real reload1 value. +.float vehicle_ammo2; /// If self is player this field's use depends on the individual vehile. If self is vehile, this is the real ammo2 value. +.float vehicle_reload2; /// If self is player this field's use depends on the individual vehile. If self is vehile, this is the real reload2 value. + +.entity vehicle; +.entity vehicle_viewport; +.entity vehicle_hudmodel; + +.float sound_nexttime; +#define VOL_VEHICLEENGINE 1 + +.float hud; +.float dmg_time; +.float vehicle_respawntime; +.void() vehicle_spawn; + +void vehicles_exit(float eject); +var .void(float exit_flags) vehicle_exit; +float VHEF_NORMAL = 0; /// User pressed exit key +float VHEF_EJECT = 1; /// User pressed exit key 3 times fast (not implemented) or vehile is dying +float VHEF_RELESE = 2; /// Release ownership, client possibly allready dissconnected / went spec / changed team / used "kill" (not implemented) + +float SVC_SETVIEWPORT = 5; // Net.Protocol 0x05 +float SVC_SETVIEWANGLES = 10; // Net.Protocol 0x0A +float SVC_UPDATEENTITY = 128; // Net.Protocol 0x80 + +var .void() vehicle_enter; /// Vehicles custom funciton to be executed when owner exit it +var .void() vehicle_die; /// Vehicles custom function to be executed when vehile die +var .void() vehicle_spawn; /// Vehicles custom fucntion to be efecuted when vehicle (re)spawns + +#ifdef VEHICLES_USE_ODE +void(entity e, float physics_enabled) physics_enable = #540; // enable or disable physics on object +void(entity e, vector force, vector force_pos) physics_addforce = #541; // apply a force from certain origin, length of force vector is power of force +void(entity e, vector torque) physics_addtorque = #542; // add relative torque +#endif // VEHICLES_USE_ODE +#endif // VEHICLES_ENABLED diff --git a/qcsrc/server/verbstack.qc b/qcsrc/server/verbstack.qc deleted file mode 100644 index b0601afe64..0000000000 --- a/qcsrc/server/verbstack.qc +++ /dev/null @@ -1,274 +0,0 @@ -/// Some default stacks. -.entity verbs_idle; -.entity verbs_attack; -.entity verbs_move; -//.entity vchain; - -/// This global gets set to the verb in question each time the stack manager calls verb_call -entity verb; -//.entity current_verb; -//.float verb_done; - -/// Execure this verb -#define VCM_DO 0 -/// Return the value of this verb. Return VS_CALL_REMOVE to delete it. -#define VCM_EVAL 1 -/// This verb is beeing removed NOW (not sent when verb_call returns VS_CALL_REMOVE) -#define VCM_REMOVE 2 - -/// Verb callback -.float(float message) verb_call; - -/// Points to this verb's stack. -.entity verbstack; - -/// Static value of this verb -.float verb_static_value; - -/// verb_call returns this when a verb in not doable -#define VS_CALL_NO 0 -/// verb_call(VCM_DO) returns this when a verb is executing -#define VS_CALL_YES_DOING -1 -/// verb_call(VCM_DO) returns this when a verb did execure and is done -#define VS_CALL_YES_DONE -2 -/// verb_call(VCM_DO) returns this when a verb should be deleted by the stack manager -#define VS_CALL_REMOVE -3 - -/* -void verbstack_updatechain(entity stack) -{ - entity vrb, v; - if not (stack) - return; - - dprint("verbstack_updatechain\n"); - - vrb = findchainentity(verbstack, stack); - if not (vrb) - { - stack.vchain = world; - return; - } - - stack.vchain = vrb; - v = vrb; - - while(vrb) - { - vrb = vrb.chain; - - - } -} - -void verbstack_remove(entity vverb) -{ - entity vstack; - dprint("verbstack_remove\n"); - - vstack = verb.verbstack; - remove(vverb); - vverb.verbstack = world; - verbstack_updatechain(vstack); - - //vverb.think = SUB_Remove; - //vverb.nextthink = time; -} - -void verbstack_thinkremove() -{ - dprint("verbstack_thinkremove\n"); - verbstack_remove(self); -} -*/ - -/** - Push a new verb onto the specified stack. Set vrb_life to make it time-limited. -**/ -entity verbstack_push(entity stack, float(float eval) vrb_call, float val_static, float vrb_life,entity verb_owner) -{ - entity vrb; - - if not(stack) - return world; - - if not(vrb_call) - return world; - - vrb = spawn(); - vrb.owner = verb_owner; - vrb.verbstack = stack; - vrb.verb_call = vrb_call; - vrb.verb_static_value = val_static; - - vrb.classname = "verb"; - stack.classname = "verbstack"; - - if(vrb_life) - { - //vrb.think = verbstack_thinkremove; - vrb.think = SUB_Remove; - vrb.nextthink = time + vrb_life; - } - - //verbstack_updatechain(stack); - - return vrb; -} - -/** - Find the best verb in this stack and execurte it. - ALso remove any verbs returning VS_CALL_REMOVE on VCM_EVAL or VCM_DO -**/ -float verbstack_pop(entity stack) -{ - entity vrb, bestverb, oldself; - float value, bestvalue; - - oldself = self; - - vrb = findchainentity(verbstack,stack); - //vrb = stack.vchain; - //dprint("owner:", stack.owner.classname, " vsn:", stack.classname,"\n"); - while(vrb) - { - //dprint("vn:", vrb.classname,"\n"); - verb = vrb; - vrb = vrb.chain; - self = verb.owner; - value = verb.verb_call(VCM_EVAL); - - if(value < 0) - { - if(value == VS_CALL_REMOVE) - remove(verb); - } - else - { - if(value > bestvalue) - { - bestverb = verb; - bestvalue = value; - } - } - } - - if(bestverb) - { - verb = bestverb; - self = verb.owner; - value = verb.verb_call(VCM_DO); - - if(value == VS_CALL_REMOVE) - remove(bestverb); - } - - self = oldself; - - return value; -} - -float verbstack_popfifo(entity stack) -{ - entity oldself; - float ret; - - oldself = self; - verb = findentity(stack,verbstack,stack); - if not (verb) - ret = 0; - else - { - self = verb.owner; - ret = verb.verb_call(VCM_DO); - - if(ret == VS_CALL_REMOVE) - remove(verb); - } - - self = oldself; - return ret; -} - -/** - Find the best verb in this stack and return it. - ALso remove any verbs returning VS_CALL_REMOVE on VCM_EVAL. -**/ -entity verbstack_pull(entity stack) -{ - entity vrb; - entity bestverb, oldself; - float value, bestvalue; - - oldself = self; - - vrb = findchainentity(verbstack,stack); - while(vrb) - { - self = vrb.owner; - - verb = vrb; - vrb = vrb.chain; - value = verb.verb_call(VCM_EVAL); - - if(value < 0) - { - if(value == VS_CALL_REMOVE) - remove(verb); - } - else - { - if(value > bestvalue) - { - bestverb = verb; - bestvalue = value; - } - } - } - - self = oldself; - - return bestverb; -} - -entity verbstack_pullfifo(entity stack) -{ - return findentity(stack,verbstack,stack); -} - -/** - Delete every verb on this stack, signaling them with VCM_REMOVE first. -**/ -void verbstack_flush(entity stack) -{ - entity vrb, oldself; - - oldself = self; - - vrb = findchainentity(verbstack,stack); - while(vrb) - { - self = vrb.owner; - - verb = vrb; - vrb = vrb.chain; - verb.verb_call(VCM_REMOVE); - remove(verb); - } - - self = oldself; - - //stack.vchain = world; -} - -void verbstack_doverb(entity vrb) -{ - float value; - - verb = vrb; - self = verb.owner; - value = verb.verb_call(VCM_DO); - - if(value == VS_CALL_REMOVE) - remove(vrb); -} diff --git a/qcsrc/server/vote.qc b/qcsrc/server/vote.qc deleted file mode 100644 index fbc8032bb1..0000000000 --- a/qcsrc/server/vote.qc +++ /dev/null @@ -1,675 +0,0 @@ -float VoteCheckNasty(string cmd) -{ - if(strstrofs(cmd, ";", 0) >= 0) - return TRUE; - if(strstrofs(cmd, "\n", 0) >= 0) - return TRUE; - if(strstrofs(cmd, "\r", 0) >= 0) - return TRUE; - if(strstrofs(cmd, "$", 0) >= 0) - return TRUE; - return FALSE; -} - -string GetKickVoteVictim_newcommand; -string GetKickVoteVictim_reason; - -entity GetKickVoteVictim(string vote, string cmd, entity caller) -{ - float tokens; - string ns; - entity e; - string reason; - - tokens = tokenize_console(vote); - ns = ""; - - e = GetCommandPlayerSlotTargetFromTokenizedCommand(tokens, 1); - if(e) - { - if(ParseCommandPlayerSlotTarget_firsttoken < tokens) - GetKickVoteVictim_reason = substring(vote, argv_start_index(ParseCommandPlayerSlotTarget_firsttoken), argv_end_index(-1) - argv_start_index(ParseCommandPlayerSlotTarget_firsttoken)); - else - GetKickVoteVictim_reason = ""; - - reason = ""; - if(cmd != "vdo" || GetKickVoteVictim_reason == "") - reason = "~"; // by convention, ~ prefixes a "unverified" kickban which will not be networked - - if(substring(GetKickVoteVictim_reason, 0, 1) == "~") - { - reason = "~"; - GetKickVoteVictim_reason = substring(GetKickVoteVictim_reason, 1, strlen(GetKickVoteVictim_reason) - 1); - } - - if(caller) - reason = strcat(reason, "player ", strdecolorize(caller.netname)); - else - reason = strcat(reason, "console vote"); - if(GetKickVoteVictim_reason != "") - reason = strcat(reason, ": ", strdecolorize(GetKickVoteVictim_reason)); - - if not(cvar_value_issafe(reason)) - reason = uri_escape(reason); - - GetKickVoteVictim_newcommand = strcat(argv(0), " # ", ftos(num_for_edict(e))); - if(argv(0) == "kickban") - { - GetKickVoteVictim_newcommand = strcat(GetKickVoteVictim_newcommand, " ", ftos(autocvar_g_ban_default_bantime), " ", ftos(autocvar_g_ban_default_masksize), " ", reason); - } - else if(argv(0) == "kick") - { - GetKickVoteVictim_newcommand = strcat(GetKickVoteVictim_newcommand, " ", reason); - } - return e; - } - - print_to(caller, strcat("Usage: ", cmd, " ", argv(0), " #playernumber (as in \"status\")\n")); - return world; -} - -string RemapVote_display; -string RemapVote_vote; -float RemapVote(string vote, string cmd, entity e) -{ - float vote_argc; - entity victim; - vote_argc = tokenize_console(vote); - - if(!VoteAllowed(argv(0), cmd)) - return FALSE; - - // VoteAllowed tokenizes! - vote_argc = tokenize_console(vote); - - // remap chmap to gotomap (forces intermission) - if(vote_argc < 2) - if(argv(0) == "chmap" || argv(0) == "gotomap" || argv(0) == "kick" || argv(0) == "kickban") // won't work without arguments - return FALSE; - if(argv(0) == "chmap") - { - vote = strcat("gotomap ", substring(vote, argv_start_index(1), argv_end_index(-1) - argv_start_index(1))); - vote_argc = tokenize_console(vote); - } - if(argv(0) == "gotomap") - { - if(!(vote = ValidateMap(substring(vote, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)), e))) - return FALSE; - vote = strcat("gotomap ", vote); - vote_argc = tokenize_console(vote); // ValidateMap may have done some stuff to it - } - - // make kick and kickban votes a bit nicer (and reject them if formatted badly) - if(argv(0) == "kick" || argv(0) == "kickban") - { - if(!(victim = GetKickVoteVictim(vote, cmd, e))) - return FALSE; - RemapVote_vote = GetKickVoteVictim_newcommand; - RemapVote_display = strcat("^1", vote, " (^7", victim.netname, "^1): ", GetKickVoteVictim_reason); - } - else - { - RemapVote_vote = vote; - RemapVote_display = strzone(strcat("^1", vote)); - } - - return TRUE; -} - -void VoteDialog_UpdateHighlight(float selected) { - WriteByte(MSG_ONE, SVC_TEMPENTITY); - WriteByte(MSG_ONE, TE_CSQC_VOTE); - WriteByte(MSG_ONE, 1); - WriteByte(MSG_ONE, selected); -} - -void VoteDialog_Reset() { - WriteByte(MSG_ALL, SVC_TEMPENTITY); - WriteByte(MSG_ALL, TE_CSQC_VOTERESET); -} - -float GameCommand_Vote(string s, entity e) { - local float playercount; - float argc; - argc = tokenize_console(s); - if(argv(0) == "help") { - print_to(e, " vote COMMANDS ARGUMENTS. See 'vhelp' for more info."); - return TRUE; - } else if(argv(0) == "vote") { - if(argv(1) == "") { - print_to(e, "^1You have to supply a vote command. See 'vhelp' for more info."); - } else if(argv(1) == "help") { - VoteHelp(e); - } else if(argv(1) == "status") { - if(votecalled) { - print_to(e, strcat("^7Vote for ", votecalledvote_display, "^7 called by ^7", VoteNetname(votecaller), "^7.")); - } else { - print_to(e, "^1No vote called."); - } - } else if(argv(1) == "call") { - if(!e || autocvar_sv_vote_call) { - if(autocvar_sv_vote_nospectators && e && e.classname != "player") { - print_to(e, "^1Error: Only players can call a vote."); // TODO invent a cvar name for allowing votes by spectators during warmup anyway - } - else if(timeoutStatus) { //don't allow a vote call during a timeout - print_to(e, "^1Error: You can not call a vote while a timeout is active."); - } - else if(votecalled) { - print_to(e, "^1There is already a vote called."); - } else { - local string vote; - vote = VoteParse(s, argc); - if(vote == "") { - print_to(e, "^1Your vote is empty. See 'vhelp' for more info."); - } else if(e - && time < e.vote_next) { - print_to(e, strcat("^1You have to wait ^2", ftos(ceil(e.vote_next - time)), "^1 seconds before you can again call a vote.")); - } else if(VoteCheckNasty(vote)) { - print_to(e, "Syntax error in command. See 'vhelp' for more info."); - } else if(RemapVote(vote, "vcall", e)) { - votecalledvote = strzone(RemapVote_vote); - votecalledvote_display = strzone(RemapVote_display); - votecalled = TRUE; - votecalledmaster = FALSE; - votefinished = time + autocvar_sv_vote_timeout; - votecaller = e; // remember who called the vote - if(e) { - e.vote_vote = 1; // of course you vote yes - e.vote_next = time + autocvar_sv_vote_wait; - } - bprint("\{1}^2* ^3", VoteNetname(votecaller), "^2 calls a vote for ", votecalledvote_display, "\n"); - if(autocvar_sv_eventlog) - GameLogEcho(strcat(":vote:vcall:", ftos(votecaller.playerid), ":", votecalledvote_display)); - VoteCount(); // needed if you are the only one - Nagger_VoteChanged(); - msg_entity = e; - VoteDialog_UpdateHighlight(1); - - local entity player; - FOR_EACH_REALCLIENT(player) - { - ++playercount; - } - if(playercount > 1) // don't announce a "vote now" sound if player is alone - Announce("votecall"); - } else { - print_to(e, "^1This vote is not ok. See 'vhelp' for more info."); - } - } - } else { - print_to(e, "^1Vote calling is NOT allowed."); - } - } else if(argv(1) == "stop") { - if(!votecalled) { - print_to(e, "^1No vote called."); - } else if(e == votecaller) { // the votecaller can stop a vote - VoteDialog_Reset(); - VoteStop(e); - } else if(!e) { // server admin / console can too - VoteDialog_Reset(); - VoteStop(e); - } else if(e.vote_master) { // masters can too - VoteDialog_Reset(); - VoteStop(e); - } else { - print_to(e, "^1You are not allowed to stop that Vote."); - } - } else if(argv(1) == "master") { - if(autocvar_sv_vote_master) { - if(votecalled) { - print_to(e, "^1There is already a vote called."); - } else { - votecalled = TRUE; - votecalledmaster = TRUE; - votecalledvote = strzone("XXX"); - votecalledvote_display = strzone("^3master"); - votefinished = time + autocvar_sv_vote_timeout; - votecaller = e; // remember who called the vote - if(e) { - e.vote_vote = 1; // of course you vote yes - e.vote_next = time + autocvar_sv_vote_wait; - } - bprint("\{1}^2* ^3", VoteNetname(votecaller), "^2 calls a vote to become ^3master^2.\n"); - if(autocvar_sv_eventlog) - GameLogEcho(strcat(":vote:vcall:", ftos(votecaller.playerid), ":", votecalledvote_display)); - VoteCount(); // needed if you are the only one - Nagger_VoteChanged(); - } - } else { - print_to(e, "^1Vote to become master is NOT allowed."); - } - } else if(argv(1) == "do") { - if(!e || e.vote_master) { - local string dovote; - dovote = VoteParse(s, argc); - if(dovote == "") { - print_to(e, "^1Your command was empty. See 'vhelp' for more info."); - } else if(VoteCheckNasty(dovote)) { - print_to(e, "Syntax error in command. See 'vhelp' for more info."); - } else if(RemapVote(dovote, "vdo", e)) { // strcat seems to be necessary - bprint("\{1}^2* ^3", VoteNetname(e), "^2 used their ^3master^2 status to do \"^2", RemapVote_display, "^2\".\n"); - if(autocvar_sv_eventlog) - GameLogEcho(strcat(":vote:vdo:", ftos(e.playerid), ":", RemapVote_display)); - localcmd(strcat(RemapVote_vote, "\n")); - } else { - print_to(e, "^1This command is not ok. See 'vhelp' for more info."); - } - } else { - print_to(e, "^1You are NOT a master. You might need to login or vote to become master first. See 'vhelp' for more info."); - } - } else if(argv(1) == "login") { - local string masterpwd; - masterpwd = autocvar_sv_vote_master_password; - if(masterpwd != "") { - local float granted; - granted = (masterpwd == argv(2)); - if (e) - e.vote_master = granted; - if(granted) { - print("Accepted master login from ", VoteNetname(e), "\n"); - bprint("\{1}^2* ^3", VoteNetname(e), "^2 logged in as ^3master^2\n"); - if(autocvar_sv_eventlog) - GameLogEcho(strcat(":vote:vlogin:", ftos(e.playerid))); - } - else - print("REJECTED master login from ", VoteNetname(e), "\n"); - } - else - print_to(e, "^1Login to become master is NOT allowed."); - } else if(argv(1) == "yes") { - if(!votecalled) { - print_to(e, "^1No vote called."); - } else if (!e) { - print_to(e, "^1You can't vote from the server console."); - } else if(e.vote_vote == 0 - || autocvar_sv_vote_change) { - msg_entity = e; - VoteDialog_UpdateHighlight(1); - print_to(e, "^1You accepted the vote."); - e.vote_vote = 1; - centerprint_expire(e, CENTERPRIO_VOTE); - if(!autocvar_sv_vote_singlecount) { - VoteCount(); - } - } else { - print_to(e, "^1You have already voted."); - } - } else if(argv(1) == "no") { - if(!votecalled) { - print_to(e, "^1No vote called."); - } else if (!e) { - print_to(e, "^1You can't vote from the server console."); - } else if(e.vote_vote == 0 - || autocvar_sv_vote_change) { - msg_entity = e; - VoteDialog_UpdateHighlight(2); - print_to(e, "^1You rejected the vote."); - e.vote_vote = -1; - centerprint_expire(e, CENTERPRIO_VOTE); - if(!autocvar_sv_vote_singlecount) { - VoteCount(); - } - } else { - print_to(e, "^1You have already voted."); - } - } else if(argv(1) == "abstain" || argv(1) == "dontcare") { - if(!votecalled) { - print_to(e, "^1No vote called."); - } else if (!e) { - print_to(e, "^1You can't vote from the server console."); - } else if(e.vote_vote == 0 - || autocvar_sv_vote_change) { - msg_entity = e; - VoteDialog_UpdateHighlight(3); - print_to(e, "^1You abstained from your vote."); - e.vote_vote = -2; - centerprint_expire(e, CENTERPRIO_VOTE); - if(!autocvar_sv_vote_singlecount) { - VoteCount(); - } - } else { - print_to(e, "^1You have already voted."); - } - } else { - // ignore this? - print_to(e, "^1Unknown vote command."); - } - return TRUE; - } - return FALSE; -} - -void VoteHelp(entity e) { - local string vmasterdis; - if(!autocvar_sv_vote_master) { - vmasterdis = " ^1(disabled)"; - } - - local string vlogindis; - if("" == autocvar_sv_vote_master_password) { - vlogindis = " ^1(disabled)"; - } - - local string vcalldis; - if(!autocvar_sv_vote_call) { - vcalldis = " ^1(disabled)"; - } - - print_to(e, "^7You can use voting with \"^2cmd vote help^7\" \"^2cmd vote status^7\" \"^2cmd vote call ^3COMMAND ARGUMENTS^7\" \"^2cmd vote stop^7\" \"^2cmd vote master^7\" \"^2cmd vote login^7\" \"^2cmd vote do ^3COMMAND ARGUMENTS^7\" \"^2cmd vote yes^7\" \"^2cmd vote no^7\" \"^2cmd vote abstain^7\" \"^2cmd vote dontcare^7\"."); - print_to(e, "^7Or if your version is up to date you can use these aliases \"^2vhelp^7\" \"^2vstatus^7\" \"^2vcall ^3COMMAND ARGUMENTS^7\" \"^2vstop^7\" \"^2vmaster^7\" \"^2vlogin^7\" \"^2vdo ^3COMMAND ARGUMENTS^7\" \"^2vyes^7\" \"^2vno^7\" \"^2abstain^7\" \"^2vdontcare^7\"."); - print_to(e, "^7\"^2help^7\" shows this info."); - print_to(e, "^7\"^2status^7\" shows if there is a vote called and who called it."); - print_to(e, strcat("^7\"^2call^7\" is used to call a vote. See the list of allowed commands.", vcalldis, "^7")); - print_to(e, "^7\"^2stop^7\" can be used by the vote caller or an admin to stop a vote and maybe correct it."); - print_to(e, strcat("^7\"^2master^7\" call a vote to become master who can execute commands without a vote", vmasterdis, "^7")); - print_to(e, strcat("^7\"^2login^7\" login to become master who can execute commands without a vote.", vlogindis, "^7")); - print_to(e, "^7\"^2do^7\" executes a command if you are a master. See the list of allowed commands."); - print_to(e, "^7\"^2yes^7\", \"^2no^7\", \"^2abstain^7\" and \"^2dontcare^7\" to make your vote."); - print_to(e, "^7If enough of the players vote yes the vote is accepted."); - print_to(e, "^7If enough of the players vote no the vote is rejected."); - print_to(e, strcat("^7If neither the vote will timeout after ", ftos(autocvar_sv_vote_timeout), "^7 seconds.")); - print_to(e, "^7You can call a vote for or execute these commands:"); - print_to(e, strcat("^3", autocvar_sv_vote_commands, "^7 and maybe further ^3arguments^7")); -} - -string VoteNetname(entity e) -{ - if(e) { - return e.netname; - } else { - if(autocvar_sv_adminnick != "") { - return autocvar_sv_adminnick; - } else { - return autocvar_hostname; - } - } -} - -string ValidateMap(string m, entity e) -{ - m = MapInfo_FixName(m); - if(!m) - { - print_to(e, "This map is not available on this server."); - return string_null; - } - if(!autocvar_sv_vote_override_mostrecent) - if(Map_IsRecent(m)) - { - print_to(e, "This server does not allow for recent maps to be played again. Please be patient for some rounds."); - return string_null; - } - if(!MapInfo_CheckMap(m)) - { - print_to(e, strcat("^1Invalid mapname, \"^3", m, "^1\" does not support the current game mode.")); - return string_null; - } - - return m; -} - - -void VoteThink() { - if(votefinished > 0) // a vote was called - if(time > votefinished) // time is up - { - VoteCount(); - } -} - -string VoteParse(string all, float argc) { - if(argc < 3) - return ""; - return substring(all, argv_start_index(2), argv_end_index(-1) - argv_start_index(2)); -} - -float VoteCommandInList(string votecommand, string list) -{ - string l; - l = strcat(" ", list, " "); - - if(strstrofs(l, strcat(" ", votecommand, " "), 0) >= 0) - return TRUE; - - // if gotomap is allowed, chmap is too, and vice versa - if(votecommand == "gotomap") - if(strstrofs(l, " chmap ", 0) >= 0) - return TRUE; - if(votecommand == "chmap") - if(strstrofs(l, " gotomap ", 0) >= 0) - return TRUE; - - return FALSE; -} - -float VoteAllowed(string votecommand, string cmd) { - if(VoteCommandInList(votecommand, autocvar_sv_vote_commands)) - return TRUE; - - if(cmd == "vdo") - { - if(VoteCommandInList(votecommand, autocvar_sv_vote_master_commands)) - return TRUE; - } - else - { - if(VoteCommandInList(votecommand, autocvar_sv_vote_only_commands)) - return TRUE; - } - - return FALSE; -} - -void VoteReset() { - local entity player; - - FOR_EACH_CLIENT(player) - { - player.vote_vote = 0; - centerprint_expire(player, CENTERPRIO_VOTE); - } - - if(votecalled) - { - strunzone(votecalledvote); - strunzone(votecalledvote_display); - } - - votecalled = FALSE; - votecalledmaster = FALSE; - votefinished = 0; -} - -void VoteAccept() { - bprint("\{1}^2* ^3", VoteNetname(votecaller), "^2's vote for ^1", votecalledvote_display, "^2 was accepted\n"); - if(votecalledmaster) - { - if(votecaller) { - votecaller.vote_master = 1; - } - } else { - localcmd(strcat(votecalledvote, "\n")); - } - if(votecaller) { - votecaller.vote_next = 0; // people like your votes, - // no wait for next vote - } - VoteReset(); - Announce("voteaccept"); -} - -void VoteReject() { - bprint("\{1}^2* ^3", VoteNetname(votecaller), "^2's vote for ", votecalledvote_display, "^2 was rejected\n"); - VoteReset(); - Announce("votefail"); -} - -void VoteTimeout() { - bprint("\{1}^2* ^3", VoteNetname(votecaller), "^2's vote for ", votecalledvote_display, "^2 timed out\n"); - VoteReset(); - Announce("votefail"); -} - -void VoteStop(entity stopper) { - bprint("\{1}^2* ^3", VoteNetname(stopper), "^2 stopped ^3", VoteNetname(votecaller), "^2's vote\n"); - if(autocvar_sv_eventlog) - GameLogEcho(strcat(":vote:vstop:", ftos(stopper.playerid))); - if(stopper == votecaller) { - // no wait for next vote so you can correct your vote - if(votecaller) { - votecaller.vote_next = time + autocvar_sv_vote_stop; - } - } - VoteReset(); -} - -void VoteSpam(float yescount, float nocount, float abstaincount, float notvoters, float mincount, string result) -{ - string s; - if(mincount >= 0) - { - s = strcat("\{1}^2* vote results: ^1", ftos(yescount), "^2:^1"); - s = strcat(s, ftos(nocount), "^2 (^1"); - s = strcat(s, ftos(mincount), "^2 needed), ^1"); - s = strcat(s, ftos(abstaincount), "^2 didn't care, ^1"); - s = strcat(s, ftos(notvoters), "^2 didn't vote\n"); - } - else - { - s = strcat("\{1}^2* vote results: ^1", ftos(yescount), "^2:^1"); - s = strcat(s, ftos(nocount), "^2, ^1"); - s = strcat(s, ftos(abstaincount), "^2 didn't care, ^1"); - s = strcat(s, ftos(notvoters), "^2 didn't have to vote\n"); - } - bprint(s); - if(autocvar_sv_eventlog) - { - s = strcat(":vote:v", result, ":", ftos(yescount)); - s = strcat(s, ":", ftos(nocount)); - s = strcat(s, ":", ftos(abstaincount)); - s = strcat(s, ":", ftos(notvoters)); - s = strcat(s, ":", ftos(mincount)); - GameLogEcho(s); - } -} - -void VoteDialog_Update(float msg, float vyes, float vno, float needed) { - WriteByte(msg, SVC_TEMPENTITY); - WriteByte(msg, TE_CSQC_VOTE); - WriteByte(msg, 0); - WriteByte(msg, vyes); - WriteByte(msg, vno); - WriteByte(msg, needed); -} - -void VoteCount() { - local float playercount; - playercount = 0; - local float yescount; - yescount = 0; - local float nocount; - nocount = 0; - local float abstaincount; - abstaincount = 0; - local entity player; - //same for real players - local float realplayercount; - local float realplayeryescount; - local float realplayernocount; - local float realplayerabstaincount; - realplayercount = realplayernocount = realplayerabstaincount = realplayeryescount = 0; - - FOR_EACH_REALCLIENT(player) - { - if(player.vote_vote == -1) { - ++nocount; - } else if(player.vote_vote == 1) { - ++yescount; - } else if(player.vote_vote == -2) { - ++abstaincount; - } - ++playercount; - //do the same for real players - if(player.classname == "player") { - if(player.vote_vote == -1) { - ++realplayernocount; - } else if(player.vote_vote == 1) { - ++realplayeryescount; - } else if(player.vote_vote == -2) { - ++realplayerabstaincount; - } - ++realplayercount; - } - } - - //in tournament mode, if we have at least one player then don't make the vote dependent on spectators (so specs don't have to press F1) - if(autocvar_sv_vote_nospectators) - if(realplayercount > 0) { - yescount = realplayeryescount; - nocount = realplayernocount; - abstaincount = realplayerabstaincount; - playercount = realplayercount; - } - - float votefactor, simplevotefactor; - votefactor = bound(0.5, autocvar_sv_vote_majority_factor, 0.999); - simplevotefactor = autocvar_sv_vote_simple_majority_factor; - float needed; - needed = floor((playercount - abstaincount) * max(votefactor, simplevotefactor)) + 1; - VoteDialog_Update(MSG_ALL, yescount, nocount, needed); - - if(votecalledmaster - && playercount == 1) { - // if only one player is on the server becoming vote - // master is not allowed. This could be used for - // trolling or worse. 'self' is the user who has - // called the vote because this function is called - // by SV_ParseClientCommand. Maybe all voting should - // be disabled for a single player? - print_to(votecaller, "^1You are the only player on this server so you can not become vote master."); - if(votecaller) { - votecaller.vote_next = 0; - } - VoteReset(); - } else { - if(yescount > (playercount - abstaincount) * votefactor) - { - VoteSpam(yescount, nocount, abstaincount, playercount - yescount - nocount - abstaincount, -1, "yes"); - VoteAccept(); - VoteDialog_Reset(); - } - else if(nocount >= (playercount - abstaincount) * (1 - votefactor)) // that means, yescount cannot reach minyes any more - { - VoteSpam(yescount, nocount, abstaincount, playercount - yescount - nocount - abstaincount, -1, "no"); - VoteReject(); - VoteDialog_Reset(); - } - else if(time > votefinished) - { - if(simplevotefactor) - { - string result; - simplevotefactor = bound(votefactor, simplevotefactor, 0.999); - if(yescount > (yescount + nocount) * simplevotefactor) - result = "yes"; - else if(yescount + nocount > 0) - result = "no"; - else - result = "timeout"; - VoteSpam(yescount, nocount, abstaincount, playercount - yescount - nocount - abstaincount, floor(min((playercount - abstaincount) * votefactor, (yescount + nocount) * simplevotefactor)) + 1, result); - if(result == "yes") - VoteAccept(); - else if(result == "no") - VoteReject(); - else - VoteTimeout(); - } - else - { - VoteSpam(yescount, nocount, abstaincount, playercount - yescount - nocount - abstaincount, floor((playercount - abstaincount) * votefactor) + 1, "timeout"); - VoteTimeout(); - } - VoteDialog_Reset(); - } - } -} diff --git a/qcsrc/server/vote.qh b/qcsrc/server/vote.qh deleted file mode 100644 index 7d937a93c1..0000000000 --- a/qcsrc/server/vote.qh +++ /dev/null @@ -1,26 +0,0 @@ -float votecalled; -string votecalledvote; -string votecalledvote_display; -float votecalledmaster; -entity votecaller; -float votefinished; -.float vote_master; -.float vote_next; -.float vote_vote; - -float VoteCheckNasty(string cmd); -entity GetKickVoteVictim(string vote, string cmd, entity caller); -float GameCommand_Vote(string s, entity e); -void VoteHelp(entity e); -string VoteNetname(entity e); -string ValidateMap(string m, entity e); -void VoteThink(); -string VoteParse(string s, float tokens); -float VoteAllowed(string vote, string cmd); -void VoteReset(); -void VoteAccept(); -void VoteReject(); -void VoteTimeout(); -void VoteStop(entity stopper); -void VoteSpam(float yescount, float nocount, float abstaincount, float notvoters, float mincount, string result); -void VoteCount(); diff --git a/qcsrc/server/w_all.qc b/qcsrc/server/w_all.qc index 5730744037..ac4ef47ed3 100644 --- a/qcsrc/server/w_all.qc +++ b/qcsrc/server/w_all.qc @@ -16,6 +16,6 @@ #include "w_hook.qc" #include "w_hlac.qc" #include "w_tuba.qc" -#include "w_campingrifle.qc" +#include "w_rifle.qc" #include "w_fireball.qc" #include "w_seeker.qc" diff --git a/qcsrc/server/w_campingrifle.qc b/qcsrc/server/w_campingrifle.qc deleted file mode 100644 index 777f0d112b..0000000000 --- a/qcsrc/server/w_campingrifle.qc +++ /dev/null @@ -1,333 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON(CAMPINGRIFLE, w_campingrifle, IT_NAILS, 7, WEP_FLAG_NORMAL | WEP_TYPE_HITSCAN, BOT_PICKUP_RATING_MID, "campingrifle", "campingrifle", "Sniper Rifle"); -#else -#ifdef SVQC -//Camping rifle Primary mode: manually operated bolt*, Secondary: full automatic** -//* Manually operating the bolt means that all the power of the gas is used to propell the bullet. In this mode the bolt is prevented from moving backwards in response to the firing of the bullet. -//** In fully automatic mode some of the gas is used to extract and reload the next cartrige, thus there is less power and range. - -.float campingrifle_accumulator; - -float W_CampingRifle_CheckMaxBullets(float checkammo) -{ - float maxbulls; - maxbulls = autocvar_g_balance_campingrifle_magazinecapacity; - if(!maxbulls) - maxbulls = 8; // match HUD - if(checkammo) - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - maxbulls = min(maxbulls, floor(self.ammo_nails / min(autocvar_g_balance_campingrifle_primary_ammo, autocvar_g_balance_campingrifle_secondary_ammo))); - if(self.campingrifle_bulletcounter > maxbulls || !autocvar_g_balance_campingrifle_magazinecapacity) - self.campingrifle_bulletcounter = maxbulls; - return (self.campingrifle_bulletcounter == maxbulls); -} - -void W_CampingRifle_ReloadedAndReady() -{ - float t; - self.campingrifle_bulletcounter = autocvar_g_balance_campingrifle_magazinecapacity; - W_CampingRifle_CheckMaxBullets(TRUE); - t = ATTACK_FINISHED(self) - autocvar_g_balance_campingrifle_reloadtime - 1; - ATTACK_FINISHED(self) = t; - w_ready(); -} - -float W_CampingRifle_Reload() -{ - float t; - - W_CampingRifle_CheckMaxBullets(TRUE); - - if(self.ammo_nails < min(autocvar_g_balance_campingrifle_primary_ammo, autocvar_g_balance_campingrifle_secondary_ammo)) // when we get here, bulletcounter must be 0 or -1 - { - print("cannot reload... not enough bullets\n"); - self.campingrifle_bulletcounter = -1; // reload later - W_SwitchToOtherWeapon(self); - return 0; - } - - if (self.campingrifle_bulletcounter >= autocvar_g_balance_campingrifle_magazinecapacity) - return 0; - - if (self.weaponentity) - { - if (self.weaponentity.wframe == WFRAME_RELOAD) - return 0; - - // allow to switch away while reloading, but this will cause a new reload! - self.weaponentity.state = WS_READY; - } - - sound (self, CHAN_WEAPON2, "weapons/campingrifle_reload.wav", VOL_BASE, ATTN_NORM); - - t = max(time, ATTACK_FINISHED(self)) + autocvar_g_balance_campingrifle_reloadtime + 1; - ATTACK_FINISHED(self) = t; - - weapon_thinkf(WFRAME_RELOAD, autocvar_g_balance_campingrifle_reloadtime, W_CampingRifle_ReloadedAndReady); - - self.campingrifle_bulletcounter = -1; - - return 1; -} - -void W_CampingRifle_CheckReloadAndReady() -{ - w_ready(); - if(self.campingrifle_bulletcounter <= 0) - if(W_CampingRifle_Reload()) - return; -} - -void W_CampingRifle_FireBullet(float pSpread, float pDamage, float pHeadshotAddedDamage, float pForce, float pSpeed, float pLifetime, float pAmmo, float deathtype, float pBulletConstant) -{ - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_nails -= pAmmo; - - if(deathtype & HITTYPE_SECONDARY) - W_SetupShot (self, autocvar_g_antilag_bullets && pSpeed >= autocvar_g_antilag_bullets, 2, "weapons/campingrifle_fire2.wav", CHAN_WEAPON, autocvar_g_balance_campingrifle_secondary_damage + autocvar_g_balance_campingrifle_secondary_headshotaddeddamage); - else - W_SetupShot (self, autocvar_g_antilag_bullets && pSpeed >= autocvar_g_antilag_bullets, 2, "weapons/campingrifle_fire.wav", CHAN_WEAPON, autocvar_g_balance_campingrifle_primary_damage + autocvar_g_balance_campingrifle_primary_headshotaddeddamage); - - pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 2000, 1); - - if(self.BUTTON_ZOOM) // if zoomed, shoot from the eye - { - w_shotdir = v_forward; - w_shotorg = self.origin + self.view_ofs + ((w_shotorg - self.origin - self.view_ofs) * v_forward) * v_forward; - } - - if(deathtype & HITTYPE_SECONDARY) - fireBallisticBullet(w_shotorg, w_shotdir, pSpread, pSpeed, pLifetime, pDamage, pHeadshotAddedDamage / pDamage, pForce, deathtype, (autocvar_g_balance_campingrifle_secondary_tracer ? EF_RED : EF_BLUE), 1, pBulletConstant); - else - fireBallisticBullet(w_shotorg, w_shotdir, pSpread, pSpeed, pLifetime, pDamage, pHeadshotAddedDamage / pDamage, pForce, deathtype, (autocvar_g_balance_campingrifle_primary_tracer ? EF_RED : EF_BLUE), 1, pBulletConstant); - endFireBallisticBullet(); - - if (autocvar_g_casings >= 2) - SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self); - - self.campingrifle_bulletcounter = self.campingrifle_bulletcounter - 1; - W_CampingRifle_CheckMaxBullets(TRUE); -} - -void W_CampingRifle_Attack() -{ - W_CampingRifle_FireBullet(autocvar_g_balance_campingrifle_primary_spread, autocvar_g_balance_campingrifle_primary_damage, autocvar_g_balance_campingrifle_primary_headshotaddeddamage, autocvar_g_balance_campingrifle_primary_force, autocvar_g_balance_campingrifle_primary_speed, autocvar_g_balance_campingrifle_primary_lifetime, autocvar_g_balance_campingrifle_primary_ammo, WEP_CAMPINGRIFLE, autocvar_g_balance_campingrifle_primary_bulletconstant); -} - -void W_CampingRifle_Attack2() -{ - W_CampingRifle_FireBullet(autocvar_g_balance_campingrifle_secondary_spread, autocvar_g_balance_campingrifle_secondary_damage, autocvar_g_balance_campingrifle_secondary_headshotaddeddamage, autocvar_g_balance_campingrifle_secondary_force, autocvar_g_balance_campingrifle_secondary_speed, autocvar_g_balance_campingrifle_secondary_lifetime, autocvar_g_balance_campingrifle_secondary_ammo, WEP_CAMPINGRIFLE | HITTYPE_SECONDARY, autocvar_g_balance_campingrifle_secondary_bulletconstant); -} - -void spawnfunc_weapon_campingrifle (void) -{ - weapon_defaultspawnfunc(WEP_CAMPINGRIFLE); -} - -.void(void) campingrifle_bullethail_attackfunc; -.float campingrifle_bullethail_frame; -.float campingrifle_bullethail_animtime; -.float campingrifle_bullethail_refire; -void W_CampingRifle_BulletHail_Continue() -{ - float r, sw, af; - W_CampingRifle_CheckReloadAndReady(); - if(self.campingrifle_bulletcounter < 0) - return; // reloading, so we are done - sw = self.switchweapon; // make it not detect weapon changes as reason to abort firing - af = ATTACK_FINISHED(self); - self.switchweapon = self.weapon; - ATTACK_FINISHED(self) = time; - print(ftos(self.ammo_nails), "\n"); - r = weapon_prepareattack(self.campingrifle_bullethail_frame == WFRAME_FIRE2, self.campingrifle_bullethail_refire); - if(self.switchweapon == self.weapon) - self.switchweapon = sw; - if(r) - { - self.campingrifle_bullethail_attackfunc(); - weapon_thinkf(self.campingrifle_bullethail_frame, self.campingrifle_bullethail_animtime, W_CampingRifle_BulletHail_Continue); - print("thinkf set\n"); - } - else - { - ATTACK_FINISHED(self) = af; // reset attack_finished if we didn't fire, so the last shot enforces the refire time - print("out of ammo... ", ftos(self.weaponentity.state), "\n"); - } -} - -void W_CampingRifle_BulletHail(float mode, void(void) AttackFunc, float fr, float animtime, float refire) -{ - // if we get here, we have at least one bullet to fire - AttackFunc(); - if(mode) - { - // continue hail - self.campingrifle_bullethail_attackfunc = AttackFunc; - self.campingrifle_bullethail_frame = fr; - self.campingrifle_bullethail_animtime = animtime; - self.campingrifle_bullethail_refire = refire; - weapon_thinkf(fr, animtime, W_CampingRifle_BulletHail_Continue); - } - else - { - // just one shot - weapon_thinkf(fr, animtime, W_CampingRifle_CheckReloadAndReady); - } -} - -.float bot_secondary_campingriflemooth; -float w_campingrifle(float req) -{ - float full; - if (req == WR_AIM) - { - self.BUTTON_ATCK=FALSE; - self.BUTTON_ATCK2=FALSE; - if(vlen(self.origin-self.enemy.origin) > 1000) - self.bot_secondary_campingriflemooth = 0; - if(self.bot_secondary_campingriflemooth == 0) - { - if(bot_aim(autocvar_g_balance_campingrifle_primary_speed, 0, autocvar_g_balance_campingrifle_primary_lifetime, TRUE)) - { - self.BUTTON_ATCK = TRUE; - if(random() < 0.01) self.bot_secondary_campingriflemooth = 1; - } - } - else - { - if(bot_aim(autocvar_g_balance_campingrifle_secondary_speed, 0, autocvar_g_balance_campingrifle_secondary_lifetime, TRUE)) - { - self.BUTTON_ATCK2 = TRUE; - if(random() < 0.03) self.bot_secondary_campingriflemooth = 0; - } - } - } - else if (req == WR_THINK) - { - if(self.campingrifle_bulletcounter < 0) // forced reload (e.g. because interrupted) - { - if(self.switchweapon == self.weapon) - if(self.weaponentity.state == WS_READY) - W_CampingRifle_Reload(); - } - else - { - self.campingrifle_accumulator = bound(time - autocvar_g_balance_campingrifle_bursttime, self.campingrifle_accumulator, time); - if (self.BUTTON_ATCK) - if (weapon_prepareattack_check(0, autocvar_g_balance_campingrifle_primary_refire)) - if (time >= self.campingrifle_accumulator + autocvar_g_balance_campingrifle_primary_burstcost) - { - weapon_prepareattack_do(0, autocvar_g_balance_campingrifle_primary_refire); - W_CampingRifle_BulletHail(autocvar_g_balance_campingrifle_primary_bullethail, W_CampingRifle_Attack, WFRAME_FIRE1, autocvar_g_balance_campingrifle_primary_animtime, autocvar_g_balance_campingrifle_primary_refire); - self.campingrifle_accumulator += autocvar_g_balance_campingrifle_primary_burstcost; - } - if (self.BUTTON_ATCK2) - { - if (autocvar_g_balance_campingrifle_secondary) - { - if (weapon_prepareattack_check(1, autocvar_g_balance_campingrifle_secondary_refire)) - if (time >= self.campingrifle_accumulator + autocvar_g_balance_campingrifle_secondary_burstcost) - { - weapon_prepareattack_do(1, autocvar_g_balance_campingrifle_secondary_refire); - W_CampingRifle_BulletHail(autocvar_g_balance_campingrifle_secondary_bullethail, W_CampingRifle_Attack2, WFRAME_FIRE2, autocvar_g_balance_campingrifle_secondary_animtime, autocvar_g_balance_campingrifle_primary_refire); - self.campingrifle_accumulator += autocvar_g_balance_campingrifle_secondary_burstcost; - } - } - } - } - } - else if (req == WR_PRECACHE) - { - precache_model ("models/weapons/g_campingrifle.md3"); - precache_model ("models/weapons/v_campingrifle.md3"); - precache_model ("models/weapons/h_campingrifle.iqm"); - precache_sound ("weapons/campingrifle_reload.wav"); - precache_sound ("weapons/campingrifle_fire.wav"); - precache_sound ("weapons/campingrifle_fire2.wav"); - } - else if (req == WR_SETUP) - { - weapon_setup(WEP_CAMPINGRIFLE); - - full = W_CampingRifle_CheckMaxBullets(TRUE); - if(autocvar_g_balance_campingrifle_auto_reload_on_switch) - if(!full) - self.campingrifle_bulletcounter = -1; - } - else if (req == WR_CHECKAMMO1) - return self.ammo_nails >= autocvar_g_balance_campingrifle_primary_ammo; - else if (req == WR_CHECKAMMO2) - return self.ammo_nails >= autocvar_g_balance_campingrifle_secondary_ammo; - else if (req == WR_RELOAD) - { - W_CampingRifle_Reload(); - } - else if (req == WR_RESETPLAYER) - { - self.campingrifle_accumulator = time - autocvar_g_balance_campingrifle_bursttime; - self.campingrifle_bulletcounter = autocvar_g_balance_campingrifle_magazinecapacity; - W_CampingRifle_CheckMaxBullets(FALSE); - } - return TRUE; -}; -#endif -#ifdef CSQC -float w_campingrifle(float req) -{ - if(req == WR_IMPACTEFFECT) - { - vector org2; - org2 = w_org + w_backoff * 2; - pointparticles(particleeffectnum("machinegun_impact"), org2, w_backoff * 1000, 1); - if(!w_issilent) - { - if(w_random < 0.2) - sound(self, CHAN_PROJECTILE, "weapons/ric1.wav", VOL_BASE, ATTN_NORM); - else if(w_random < 0.4) - sound(self, CHAN_PROJECTILE, "weapons/ric2.wav", VOL_BASE, ATTN_NORM); - else if(w_random < 0.5) - sound(self, CHAN_PROJECTILE, "weapons/ric3.wav", VOL_BASE, ATTN_NORM); - } - } - else if(req == WR_PRECACHE) - { - precache_sound("weapons/ric1.wav"); - precache_sound("weapons/ric2.wav"); - precache_sound("weapons/ric3.wav"); - } - else if (req == WR_SUICIDEMESSAGE) - { - if(w_deathtype & HITTYPE_SECONDARY) - w_deathtypestring = "%s shot themself automatically"; - else - w_deathtypestring = "%s sniped themself somehow"; - } - else if (req == WR_KILLMESSAGE) - { - if(w_deathtype & HITTYPE_SECONDARY) - { - if(w_deathtype & HITTYPE_BOUNCE) - w_deathtypestring = "%s failed to hide from %s's bullet hail"; - else - w_deathtypestring = "%s died in %s's bullet hail"; - } - else - { - if(w_deathtype & HITTYPE_BOUNCE) - { - // TODO special headshot message here too? - w_deathtypestring = "%s failed to hide from %s's rifle"; - } - else - { - if(w_deathtype & HITTYPE_HEADSHOT) - w_deathtypestring = "%s got hit in the head by %s"; - else - w_deathtypestring = "%s was sniped by %s"; - } - } - } - return TRUE; -} -#endif -#endif diff --git a/qcsrc/server/w_common.qc b/qcsrc/server/w_common.qc index 49e2773836..a05c17bd4b 100644 --- a/qcsrc/server/w_common.qc +++ b/qcsrc/server/w_common.qc @@ -23,12 +23,14 @@ void W_GiveWeapon (entity e, float wep, string name) } .float railgundistance; +.vector railgunforce; void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, float deathtype) { - local vector hitloc, force, endpoint, dir; - local entity ent, endent; - local float endq3surfaceflags; + vector hitloc, force, endpoint, dir; + entity ent, endent; + float endq3surfaceflags; float totaldmg; + entity o; float length; vector beampos; @@ -51,12 +53,18 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f // trace multiple times until we hit a wall, each obstacle will be made // non-solid so we can hit the next, while doing this we spawn effects and // note down which entities were hit so we can damage them later + o = self; while (1) { if(self.antilag_debug) - WarpZone_traceline_antilag (self, start, end, FALSE, self, self.antilag_debug); + WarpZone_traceline_antilag (self, start, end, FALSE, o, self.antilag_debug); else - WarpZone_traceline_antilag (self, start, end, FALSE, self, ANTILAG_LATENCY(self)); + WarpZone_traceline_antilag (self, start, end, FALSE, o, ANTILAG_LATENCY(self)); + if(o && WarpZone_trace_firstzone) + { + o = world; + continue; + } // if it is world we can't hurt it so stop now if (trace_ent == world || trace_fraction == 1) @@ -67,6 +75,7 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f trace_ent.railgunhitloc = end; trace_ent.railgunhitsolidbackup = trace_ent.solid; trace_ent.railgundistance = vlen(WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos) - start); + trace_ent.railgunforce = WarpZone_TransformVelocity(WarpZone_trace_transform, force); // stop if this is a wall if (trace_ent.solid == SOLID_BSP) @@ -108,7 +117,7 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f if(!pseudoprojectile) pseudoprojectile = spawn(); // we need this so the sound uses the "entchannel4" volume - soundtoat(MSG_ONE, pseudoprojectile, beampos, CHAN_PROJECTILE, snd, VOL_BASE * f, ATTN_NONE); + soundtoat(MSG_ONE, pseudoprojectile, beampos, CH_SHOTS, snd, VOL_BASE * f, ATTN_NONE); } if(pseudoprojectile) @@ -125,12 +134,12 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f f = ExponentialFalloff(mindist, maxdist, halflifedist, ent.railgundistance); ffs = ExponentialFalloff(mindist, maxdist, forcehalflifedist, ent.railgundistance); - if(accuracy_isgooddamage(self.owner, ent)) + if(accuracy_isgooddamage(self.realowner, ent)) totaldmg += bdamage * f; // apply the damage if (ent.takedamage) - Damage (ent, self, self, bdamage * f, deathtype, hitloc, force * ffs); + Damage (ent, self, self, bdamage * f, deathtype, hitloc, ent.railgunforce * ffs); // create a small explosion to throw gibs around (if applicable) //setorigin (explosion, hitloc); @@ -176,18 +185,18 @@ void W_BallisticBullet_Hit (void) damage_headshotbonus = self.dmg_edge * f; railgun_start = self.origin - 2 * frametime * self.velocity; railgun_end = self.origin + 2 * frametime * self.velocity; - g = accuracy_isgooddamage(self.owner, other); - Damage(other, self, self.owner, self.dmg * f, self.projectiledeathtype, self.origin, self.dmg_force * normalize(self.velocity) * f); + g = accuracy_isgooddamage(self.realowner, other); + Damage(other, self, self.realowner, self.dmg * f, self.projectiledeathtype, self.origin, self.dmg_force * normalize(self.velocity) * f); damage_headshotbonus = 0; if(headshot) f *= q; - if(DEATH_WEAPONOF(self.projectiledeathtype) == WEP_CAMPINGRIFLE) + if(self.dmg_edge > 0) { if(headshot) - AnnounceTo(self.owner, "headshot"); + AnnounceTo(self.realowner, "headshot"); if(yoda) - AnnounceTo(self.owner, "awesome"); + AnnounceTo(self.realowner, "awesome"); } // calculate hits for ballistic weapons @@ -196,7 +205,7 @@ void W_BallisticBullet_Hit (void) // do not exceed 100% q = min(self.dmg * q, self.dmg_total + f * self.dmg) - self.dmg_total; self.dmg_total += f * self.dmg; - accuracy_add(self.owner, self.owner.weapon, 0, q); + accuracy_add(self.realowner, self.realowner.weapon, 0, q); } } @@ -344,6 +353,8 @@ void fireBallisticBullet_trace_callback(vector start, vector hit, vector end) { if(vlen(trace_endpos - fireBallisticBullet_trace_callback_ent.origin) > 16) zcurveparticles_from_tracetoss(fireBallisticBullet_trace_callback_eff, fireBallisticBullet_trace_callback_ent.origin, trace_endpos, fireBallisticBullet_trace_callback_ent.velocity); + WarpZone_trace_forent = world; + self.owner = world; } void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, float lifetime, float damage, float headshotbonus, float force, float dtype, float tracereffects, float gravityfactor, float bulletconstant) @@ -357,7 +368,7 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f entity proj; proj = spawn(); proj.classname = "bullet"; - proj.owner = self; + proj.owner = proj.realowner = self; PROJECTILE_MAKETRIGGER(proj); if(gravityfactor > 0) { @@ -391,6 +402,8 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f if(tracereffects & EF_RED) eff = particleeffectnum("tr_rifle"); + else if(tracereffects & EF_BLUE) + eff = particleeffectnum("tr_rifle_weak"); else eff = particleeffectnum("tr_bullet"); @@ -405,7 +418,8 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f if(lag) FOR_EACH_PLAYER(pl) - antilag_takeback(pl, time - lag); + if(pl != self) + antilag_takeback(pl, time - lag); oldself = self; self = proj; @@ -427,7 +441,7 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f trace_fraction = 0; fireBallisticBullet_trace_callback_ent = self; fireBallisticBullet_trace_callback_eff = eff; - WarpZone_TraceToss_ThroughZone(self, oldself, world, fireBallisticBullet_trace_callback); + WarpZone_TraceToss_ThroughZone(self, self.owner, world, fireBallisticBullet_trace_callback); self.velocity = v0; self.gravity = g0; @@ -483,7 +497,8 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f if(lag) FOR_EACH_PLAYER(pl) - antilag_restore(pl); + if(pl != self) + antilag_restore(pl); remove(proj); @@ -513,15 +528,56 @@ void fireBullet (vector start, vector dir, float spread, float damage, float for if ((trace_fraction != 1.0) && (pointcontents (trace_endpos) != CONTENT_SKY)) { - pointparticles(particleeffectnum("TE_KNIGHTSPIKE"),end,trace_plane_normal * 2500,1); - if (trace_ent.solid == SOLID_BSP && !(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)) - Damage_DamageInfo(trace_endpos, damage, 0, 0, dir * max(1, force), dtype, self); + if not (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT) + Damage_DamageInfo(trace_endpos, damage, 0, 0, dir * max(1, force), dtype, self); + Damage (trace_ent, self, self, damage, dtype, trace_endpos, dir * force); - //void(float effectnum, vector org, vector vel, float howmany) pointparticles = #337; // same as in CSQC } trace_endpos = end; } +float W_CheckProjectileDamage(entity inflictor, entity projowner, float deathtype, float exception) +{ + float is_from_contents = (deathtype == DEATH_SLIME || deathtype == DEATH_LAVA); + float is_from_owner = (inflictor == projowner); + float is_from_exception = (exception != -1); + + //dprint(strcat("W_CheckProjectileDamage: from_contents ", ftos(is_from_contents), " : from_owner ", ftos(is_from_owner), " : exception ", strcat(ftos(is_from_exception), " (", ftos(exception), "). \n"))); + + if(autocvar_g_projectiles_damage <= -2) + { + return FALSE; // no damage to projectiles at all, not even with the exceptions + } + else if(autocvar_g_projectiles_damage == -1) + { + if(is_from_exception) + return (exception); // if exception is detected, allow it to override + else + return FALSE; // otherwise, no other damage is allowed + } + else if(autocvar_g_projectiles_damage == 0) + { + if(is_from_exception) + return (exception); // if exception is detected, allow it to override + else if not(is_from_contents) + return FALSE; // otherwise, only allow damage from contents + } + else if(autocvar_g_projectiles_damage == 1) + { + if(is_from_exception) + return (exception); // if exception is detected, allow it to override + else if not(is_from_contents || is_from_owner) + return FALSE; // otherwise, only allow self damage and damage from contents + } + else if(autocvar_g_projectiles_damage == 2) // allow any damage, but override for exceptions + { + if(is_from_exception) + return (exception); // if exception is detected, allow it to override + } + + return TRUE; // if none of these return, then allow damage anyway. +} + void W_PrepareExplosionByDamage(entity attacker, void() explode) { self.takedamage = DAMAGE_NO; diff --git a/qcsrc/server/w_crylink.qc b/qcsrc/server/w_crylink.qc index 4495b720c5..0b3118bb60 100644 --- a/qcsrc/server/w_crylink.qc +++ b/qcsrc/server/w_crylink.qc @@ -1,5 +1,5 @@ #ifdef REGISTER_WEAPON -REGISTER_WEAPON(CRYLINK, w_crylink, IT_CELLS, 6, WEP_FLAG_NORMAL | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_MID, "crylink", "crylink", "Crylink"); +REGISTER_WEAPON(CRYLINK, w_crylink, IT_CELLS, 6, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_MID, "crylink", "crylink", _("Crylink")); #else #ifdef SVQC .float gravity; @@ -16,6 +16,8 @@ void W_Crylink_CheckLinks(entity e) if(e == world) error("W_Crylink_CheckLinks: entity is world"); + if(e.classname != "spike" || wasfreed(e)) + error(sprintf("W_Crylink_CheckLinks: entity is not a spike but a %s (freed: %d)", e.classname, wasfreed(e))); p = e; for(i = 0; i < 1000; ++i) @@ -32,10 +34,14 @@ void W_Crylink_CheckLinks(entity e) void W_Crylink_Dequeue_Raw(entity own, entity prev, entity me, entity next) { + W_Crylink_CheckLinks(next); if(me == own.crylink_lastgroup) own.crylink_lastgroup = ((me == next) ? world : next); prev.queuenext = next; next.queueprev = prev; + me.classname = "spike_oktoremove"; + if(me != next) + W_Crylink_CheckLinks(next); } void W_Crylink_Dequeue(entity e) @@ -43,20 +49,33 @@ void W_Crylink_Dequeue(entity e) W_Crylink_Dequeue_Raw(e.realowner, e.queueprev, e, e.queuenext); } +void W_Crylink_Reset(void) +{ + W_Crylink_Dequeue(self); + remove(self); +} + // force projectile to explode void W_Crylink_LinkExplode (entity e, entity e2) { float a; + + if(e == e2) + return; + a = bound(0, 1 - (time - e.fade_time) * e.fade_rate, 1); if(e == e.realowner.crylink_lastgroup) e.realowner.crylink_lastgroup = world; - RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_primary_damage * a, autocvar_g_balance_crylink_primary_edgedamage * a, autocvar_g_balance_crylink_primary_radius, world, autocvar_g_balance_crylink_primary_force * a, e.projectiledeathtype, other); + if(e.projectiledeathtype & HITTYPE_SECONDARY) + RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_secondary_damage * a, autocvar_g_balance_crylink_secondary_edgedamage * a, autocvar_g_balance_crylink_secondary_radius, world, autocvar_g_balance_crylink_secondary_force * a, e.projectiledeathtype, other); + else + RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_primary_damage * a, autocvar_g_balance_crylink_primary_edgedamage * a, autocvar_g_balance_crylink_primary_radius, world, autocvar_g_balance_crylink_primary_force * a, e.projectiledeathtype, other); - if(e.queuenext != e2) - W_Crylink_LinkExplode(e.queuenext, e2); + W_Crylink_LinkExplode(e.queuenext, e2); + e.classname = "spike_oktoremove"; remove (e); } @@ -151,6 +170,8 @@ vector W_Crylink_LinkJoin(entity e, float jspeed, float jtime) // p->velocity -> HUEG away from center } + W_Crylink_CheckLinks(e); + return targ_origin; } @@ -203,23 +224,12 @@ void W_Crylink_LinkJoinEffect_Think() remove(self); } - // NO bounce protection, as bounces are limited! void W_Crylink_Touch (void) { float finalhit; float f; - //PROJECTILE_TOUCH; - local entity savenext, saveprev, saveown; - saveown = self.realowner; - savenext = self.queuenext; - saveprev = self.queueprev; - if(WarpZone_Projectile_Touch()) - { - if(wasfreed(self)) - W_Crylink_Dequeue_Raw(saveown, saveprev, self, savenext); - return; - } + PROJECTILE_TOUCH; float a; a = bound(0, 1 - (time - self.fade_time) * self.fade_rate, 1); @@ -236,6 +246,7 @@ void W_Crylink_Touch (void) if(self == self.realowner.crylink_lastgroup) self.realowner.crylink_lastgroup = world; W_Crylink_LinkExplode(self.queuenext, self); + self.classname = "spike_oktoremove"; remove (self); return; } @@ -259,20 +270,10 @@ void W_Crylink_Touch2 (void) { float finalhit; float f; - //PROJECTILE_TOUCH; - local entity savenext, saveprev, saveown; - savenext = self.queuenext; - saveprev = self.queueprev; - saveown = self.realowner; - if(WarpZone_Projectile_Touch()) - { - if(wasfreed(self)) - W_Crylink_Dequeue_Raw(saveown, saveprev, self, savenext); - return; - } + PROJECTILE_TOUCH; float a; - a = 1 - (time - self.fade_time) * self.fade_rate; + a = bound(0, 1 - (time - self.fade_time) * self.fade_rate, 1); finalhit = ((self.cnt <= 0) || (other.takedamage != DAMAGE_NO)); if(finalhit) @@ -286,6 +287,7 @@ void W_Crylink_Touch2 (void) if(self == self.realowner.crylink_lastgroup) self.realowner.crylink_lastgroup = world; W_Crylink_LinkExplode(self.queuenext, self); + self.classname = "spike_oktoremove"; remove (self); return; } @@ -313,21 +315,20 @@ void W_Crylink_Fadethink (void) void W_Crylink_Attack (void) { - local float counter, shots; - local entity proj, prevproj, firstproj; - local vector s; + float counter, shots; + entity proj, prevproj, firstproj; + vector s; vector forward, right, up; float maxdmg; - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_cells = self.ammo_cells - autocvar_g_balance_crylink_primary_ammo; + W_DecreaseAmmo(ammo_cells, autocvar_g_balance_crylink_primary_ammo, autocvar_g_balance_crylink_reload_ammo); maxdmg = autocvar_g_balance_crylink_primary_damage*autocvar_g_balance_crylink_primary_shots; maxdmg *= 1 + autocvar_g_balance_crylink_primary_bouncedamagefactor * autocvar_g_balance_crylink_primary_bounces; if(autocvar_g_balance_crylink_primary_joinexplode) maxdmg += autocvar_g_balance_crylink_primary_joinexplode_damage; - W_SetupShot (self, FALSE, 2, "weapons/crylink_fire.wav", CHAN_WEAPON, maxdmg); + W_SetupShot (self, FALSE, 2, "weapons/crylink_fire.wav", CH_WEAPON_A, maxdmg); forward = v_forward; right = v_right; up = v_up; @@ -338,6 +339,7 @@ void W_Crylink_Attack (void) while (counter < shots) { proj = spawn (); + proj.reset = W_Crylink_Reset; proj.realowner = proj.owner = self; proj.classname = "spike"; proj.bot_dodge = TRUE; @@ -397,6 +399,7 @@ void W_Crylink_Attack (void) proj.fade_rate = 1 / autocvar_g_balance_crylink_primary_other_fadetime; proj.nextthink = time + autocvar_g_balance_crylink_primary_other_lifetime + autocvar_g_balance_crylink_primary_other_fadetime; } + proj.teleport_time = time + autocvar_g_balance_crylink_primary_joindelay; proj.cnt = autocvar_g_balance_crylink_primary_bounces; //proj.scale = 1 + 1 * proj.cnt; @@ -412,24 +415,28 @@ void W_Crylink_Attack (void) counter = counter + 1; } - self.crylink_lastgroup = proj; + if(autocvar_g_balance_crylink_primary_joinspread != 0 || autocvar_g_balance_crylink_primary_jointime != 0) + { + self.crylink_lastgroup = proj; + W_Crylink_CheckLinks(proj); + self.crylink_waitrelease = 1; + } } void W_Crylink_Attack2 (void) { - local float counter, shots; - local entity proj, prevproj, firstproj; + float counter, shots; + entity proj, prevproj, firstproj; float maxdmg; - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_cells = self.ammo_cells - autocvar_g_balance_crylink_secondary_ammo; + W_DecreaseAmmo(ammo_cells, autocvar_g_balance_crylink_secondary_ammo, autocvar_g_balance_crylink_reload_ammo); maxdmg = autocvar_g_balance_crylink_secondary_damage*autocvar_g_balance_crylink_secondary_shots; maxdmg *= 1 + autocvar_g_balance_crylink_secondary_bouncedamagefactor * autocvar_g_balance_crylink_secondary_bounces; if(autocvar_g_balance_crylink_secondary_joinexplode) maxdmg += autocvar_g_balance_crylink_secondary_joinexplode_damage; - W_SetupShot (self, FALSE, 2, "weapons/crylink_fire2.wav", CHAN_WEAPON, maxdmg); + W_SetupShot (self, FALSE, 2, "weapons/crylink_fire2.wav", CH_WEAPON_A, maxdmg); shots = autocvar_g_balance_crylink_secondary_shots; pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots); @@ -437,6 +444,7 @@ void W_Crylink_Attack2 (void) while (counter < shots) { proj = spawn (); + proj.reset = W_Crylink_Reset; proj.realowner = proj.owner = self; proj.classname = "spike"; proj.bot_dodge = TRUE; @@ -484,6 +492,7 @@ void W_Crylink_Attack2 (void) proj.fade_rate = 1 / autocvar_g_balance_crylink_secondary_line_fadetime; proj.nextthink = time + autocvar_g_balance_crylink_secondary_line_lifetime + autocvar_g_balance_crylink_secondary_line_fadetime; } + proj.teleport_time = time + autocvar_g_balance_crylink_secondary_joindelay; proj.cnt = autocvar_g_balance_crylink_secondary_bounces; //proj.scale = 1 + 1 * proj.cnt; @@ -499,7 +508,12 @@ void W_Crylink_Attack2 (void) counter = counter + 1; } - self.crylink_lastgroup = proj; + if(autocvar_g_balance_crylink_secondary_joinspread != 0 || autocvar_g_balance_crylink_secondary_jointime != 0) + { + self.crylink_lastgroup = proj; + W_Crylink_CheckLinks(proj); + self.crylink_waitrelease = 2; + } } void spawnfunc_weapon_crylink (void) @@ -509,6 +523,7 @@ void spawnfunc_weapon_crylink (void) float w_crylink(float req) { + float ammo_amount; if (req == WR_AIM) { if (random() < 0.10) @@ -518,31 +533,32 @@ float w_crylink(float req) } else if (req == WR_THINK) { + if(autocvar_g_balance_crylink_reload_ammo && self.clip_load < min(autocvar_g_balance_crylink_primary_ammo, autocvar_g_balance_crylink_secondary_ammo)) // forced reload + weapon_action(self.weapon, WR_RELOAD); + if (self.BUTTON_ATCK) { - if (!self.crylink_waitrelease) + if (self.crylink_waitrelease != 1) if (weapon_prepareattack(0, autocvar_g_balance_crylink_primary_refire)) { W_Crylink_Attack(); weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_crylink_primary_animtime, w_ready); - if(autocvar_g_balance_crylink_primary_joinspread != 0 || autocvar_g_balance_crylink_primary_jointime != 0) - self.crylink_waitrelease = 1; } } - else if(self.BUTTON_ATCK2 && autocvar_g_balance_crylink_secondary) + + if(self.BUTTON_ATCK2 && autocvar_g_balance_crylink_secondary) { - if (!self.crylink_waitrelease) + if (self.crylink_waitrelease != 2) if (weapon_prepareattack(1, autocvar_g_balance_crylink_secondary_refire)) { W_Crylink_Attack2(); weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_crylink_secondary_animtime, w_ready); - if(autocvar_g_balance_crylink_secondary_joinspread != 0 || autocvar_g_balance_crylink_secondary_jointime != 0) - self.crylink_waitrelease = 2; } } - else + + if ((self.crylink_waitrelease == 1 && !self.BUTTON_ATCK) || (self.crylink_waitrelease == 2 && !self.BUTTON_ATCK2)) { - if (self.crylink_waitrelease) + if (!self.crylink_lastgroup || time > self.crylink_lastgroup.teleport_time) { // fired and released now! if(self.crylink_lastgroup) @@ -550,7 +566,6 @@ float w_crylink(float req) vector pos; entity linkjoineffect; - if(self.crylink_waitrelease == 1) { pos = W_Crylink_LinkJoin(self.crylink_lastgroup, autocvar_g_balance_crylink_primary_joinspread * autocvar_g_balance_crylink_primary_speed, autocvar_g_balance_crylink_primary_jointime); @@ -567,11 +582,10 @@ float w_crylink(float req) linkjoineffect.nextthink = time + w_crylink_linkjoin_time; linkjoineffect.owner = self; setorigin(linkjoineffect, pos); - - } self.crylink_waitrelease = 0; if(!w_crylink(WR_CHECKAMMO1) && !w_crylink(WR_CHECKAMMO2)) + if not(self.items & IT_UNLIMITED_WEAPON_AMMO) { // ran out of ammo! self.cnt = WEP_CRYLINK; @@ -588,25 +602,39 @@ float w_crylink(float req) precache_sound ("weapons/crylink_fire.wav"); precache_sound ("weapons/crylink_fire2.wav"); precache_sound ("weapons/crylink_linkjoin.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else } else if (req == WR_SETUP) + { weapon_setup(WEP_CRYLINK); + self.current_ammo = ammo_cells; + } else if (req == WR_CHECKAMMO1) { // don't "run out of ammo" and switch weapons while waiting for release if(self.crylink_lastgroup && self.crylink_waitrelease) return TRUE; - return self.ammo_cells >= autocvar_g_balance_crylink_primary_ammo; + + ammo_amount = self.ammo_cells >= autocvar_g_balance_crylink_primary_ammo; + ammo_amount += self.(weapon_load[WEP_CRYLINK]) >= autocvar_g_balance_crylink_primary_ammo; + return ammo_amount; } else if (req == WR_CHECKAMMO2) { // don't "run out of ammo" and switch weapons while waiting for release if(self.crylink_lastgroup && self.crylink_waitrelease) return TRUE; - return self.ammo_cells >= autocvar_g_balance_crylink_secondary_ammo; + + ammo_amount = self.ammo_cells >= autocvar_g_balance_crylink_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_CRYLINK]) >= autocvar_g_balance_crylink_secondary_ammo; + return ammo_amount; + } + else if (req == WR_RELOAD) + { + W_Reload(min(autocvar_g_balance_crylink_primary_ammo, autocvar_g_balance_crylink_secondary_ammo), autocvar_g_balance_crylink_reload_ammo, autocvar_g_balance_crylink_reload_time, "weapons/reload.wav"); } return TRUE; -}; +} #endif #ifdef CSQC float w_crylink(float req) @@ -619,13 +647,13 @@ float w_crylink(float req) { pointparticles(particleeffectnum("crylink_impact"), org2, '0 0 0', 1); if(!w_issilent) - sound(self, CHAN_PROJECTILE, "weapons/crylink_impact2.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/crylink_impact2.wav", VOL_BASE, ATTN_NORM); } else { pointparticles(particleeffectnum("crylink_impactbig"), org2, '0 0 0', 1); if(!w_issilent) - sound(self, CHAN_PROJECTILE, "weapons/crylink_impact.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/crylink_impact.wav", VOL_BASE, ATTN_NORM); } } else if(req == WR_PRECACHE) @@ -635,16 +663,16 @@ float w_crylink(float req) } else if (req == WR_SUICIDEMESSAGE) { - w_deathtypestring = "%s succeeded at self-destructing themself with the Crylink"; + w_deathtypestring = _("%s succeeded at self-destructing themself with the Crylink"); } else if (req == WR_KILLMESSAGE) { if(w_deathtype & HITTYPE_BOUNCE) - w_deathtypestring = "%s could not hide from %s's Crylink"; // unchecked: SPLASH (SECONDARY can't be) + w_deathtypestring = _("%s could not hide from %s's Crylink"); // unchecked: SPLASH (SECONDARY can't be) else if(w_deathtype & HITTYPE_SPLASH) - w_deathtypestring = "%s was too close to %s's Crylink"; // unchecked: SECONDARY + w_deathtypestring = _("%s was too close to %s's Crylink"); // unchecked: SECONDARY else - w_deathtypestring = "%s took a close look at %s's Crylink"; // unchecked: SECONDARY + w_deathtypestring = _("%s took a close look at %s's Crylink"); // unchecked: SECONDARY } return TRUE; } diff --git a/qcsrc/server/w_electro.qc b/qcsrc/server/w_electro.qc index 1ae02b1613..9b1b96e565 100644 --- a/qcsrc/server/w_electro.qc +++ b/qcsrc/server/w_electro.qc @@ -1,5 +1,5 @@ #ifdef REGISTER_WEAPON -REGISTER_WEAPON(ELECTRO, w_electro, IT_CELLS, 5, WEP_FLAG_NORMAL | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_MID, "electro", "electro", "Electro"); +REGISTER_WEAPON(ELECTRO, w_electro, IT_CELLS, 5, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_MID, "electro", "electro", _("Electro")); #else #ifdef SVQC .float electro_count; @@ -9,14 +9,14 @@ void W_Plasma_Explode_Combo (void); void W_Plasma_TriggerCombo(vector org, float rad, entity own) { - local entity e; + entity e; e = WarpZone_FindRadius(org, rad, TRUE); while (e) { if (e.classname == "plasma") { // change owner to whoever caused the combo explosion - e.owner = own; + e.realowner = own; e.takedamage = DAMAGE_NO; e.classname = "plasma_chain"; e.think = W_Plasma_Explode_Combo; @@ -30,21 +30,21 @@ void W_Plasma_Explode (void) { if(other.takedamage == DAMAGE_AIM) if(other.classname == "player") - if(IsDifferentTeam(self.owner, other)) + if(IsDifferentTeam(self.realowner, other)) if(other.deadflag == DEAD_NO) if(IsFlying(other)) - AnnounceTo(self.owner, "electrobitch"); + AnnounceTo(self.realowner, "electrobitch"); self.event_damage = SUB_Null; self.takedamage = DAMAGE_NO; if (self.movetype == MOVETYPE_BOUNCE) { - RadiusDamage (self, self.owner, autocvar_g_balance_electro_secondary_damage, autocvar_g_balance_electro_secondary_edgedamage, autocvar_g_balance_electro_secondary_radius, world, autocvar_g_balance_electro_secondary_force, self.projectiledeathtype, other); + RadiusDamage (self, self.realowner, autocvar_g_balance_electro_secondary_damage, autocvar_g_balance_electro_secondary_edgedamage, autocvar_g_balance_electro_secondary_radius, world, autocvar_g_balance_electro_secondary_force, self.projectiledeathtype, other); } else { - W_Plasma_TriggerCombo(self.origin, autocvar_g_balance_electro_primary_comboradius, self.owner); - RadiusDamage (self, self.owner, autocvar_g_balance_electro_primary_damage, autocvar_g_balance_electro_primary_edgedamage, autocvar_g_balance_electro_primary_radius, world, autocvar_g_balance_electro_primary_force, self.projectiledeathtype, other); + W_Plasma_TriggerCombo(self.origin, autocvar_g_balance_electro_primary_comboradius, self.realowner); + RadiusDamage (self, self.realowner, autocvar_g_balance_electro_primary_damage, autocvar_g_balance_electro_primary_edgedamage, autocvar_g_balance_electro_primary_radius, world, autocvar_g_balance_electro_primary_force, self.projectiledeathtype, other); } remove (self); @@ -52,10 +52,10 @@ void W_Plasma_Explode (void) void W_Plasma_Explode_Combo (void) { - W_Plasma_TriggerCombo(self.origin, autocvar_g_balance_electro_combo_comboradius, self.owner); + W_Plasma_TriggerCombo(self.origin, autocvar_g_balance_electro_combo_comboradius, self.realowner); self.event_damage = SUB_Null; - RadiusDamage (self, self.owner, autocvar_g_balance_electro_combo_damage, autocvar_g_balance_electro_combo_edgedamage, autocvar_g_balance_electro_combo_radius, world, autocvar_g_balance_electro_combo_force, WEP_ELECTRO | HITTYPE_BOUNCE, world); // use THIS type for a combo because primary can't bounce + RadiusDamage (self, self.realowner, autocvar_g_balance_electro_combo_damage, autocvar_g_balance_electro_combo_edgedamage, autocvar_g_balance_electro_combo_radius, world, autocvar_g_balance_electro_combo_force, WEP_ELECTRO | HITTYPE_BOUNCE, world); // use THIS type for a combo because primary can't bounce remove (self); } @@ -68,7 +68,7 @@ void W_Plasma_Touch (void) W_Plasma_Explode (); } else { //UpdateCSQCProjectile(self); - spamsound (self, CHAN_PROJECTILE, "weapons/electro_bounce.wav", VOL_BASE, ATTN_NORM); + spamsound (self, CH_SHOTS, "weapons/electro_bounce.wav", VOL_BASE, ATTN_NORM); self.projectiledeathtype |= HITTYPE_BOUNCE; } } @@ -83,16 +83,22 @@ void W_Plasma_Damage (entity inflictor, entity attacker, float damage, float dea { if(self.health <= 0) return; + // note: combos are usually triggered by W_Plasma_TriggerCombo, not damage + float is_combo = (inflictor.classname == "plasma_chain" || inflictor.classname == "plasma_prim"); + + if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, (is_combo ? 1 : -1))) + return; // g_projectiles_damage says to halt + self.health = self.health - damage; if (self.health <= 0) { self.takedamage = DAMAGE_NO; self.nextthink = time; - if (inflictor.classname == "plasma_chain" || inflictor.classname == "plasma_prim") + if (is_combo) { // change owner to whoever caused the combo explosion - self.owner = inflictor.owner; + self.realowner = inflictor.realowner; self.classname = "plasma_chain"; self.think = W_Plasma_Explode_Combo; self.nextthink = time + min(autocvar_g_balance_electro_combo_radius, vlen(self.origin - inflictor.origin)) / autocvar_g_balance_electro_combo_speed; // delay combo chains, looks cooler @@ -108,15 +114,17 @@ void W_Plasma_Damage (entity inflictor, entity attacker, float damage, float dea void W_Electro_Attack() { - local entity proj; + entity proj; + + W_DecreaseAmmo(ammo_cells, autocvar_g_balance_electro_primary_ammo, autocvar_g_balance_electro_reload_ammo); - W_SetupShot_ProjectileSize (self, '0 0 -3', '0 0 -3', FALSE, 2, "weapons/electro_fire.wav", CHAN_WEAPON, autocvar_g_balance_electro_primary_damage); + W_SetupShot_ProjectileSize (self, '0 0 -3', '0 0 -3', FALSE, 2, "weapons/electro_fire.wav", CH_WEAPON_A, autocvar_g_balance_electro_primary_damage); pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); proj = spawn (); proj.classname = "plasma_prim"; - proj.owner = self; + proj.owner = proj.realowner = self; proj.bot_dodge = TRUE; proj.bot_dodgerating = autocvar_g_balance_electro_primary_damage; proj.use = W_Plasma_Explode; @@ -126,8 +134,6 @@ void W_Electro_Attack() proj.projectiledeathtype = WEP_ELECTRO; setorigin(proj, w_shotorg); - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_cells = self.ammo_cells - autocvar_g_balance_electro_primary_ammo; proj.movetype = MOVETYPE_FLY; W_SETUPPROJECTILEVELOCITY(proj, g_balance_electro_primary); proj.angles = vectoangles(proj.velocity); @@ -135,9 +141,6 @@ void W_Electro_Attack() setsize(proj, '0 0 -3', '0 0 -3'); proj.flags = FL_PROJECTILE; - //sound (proj, CHAN_PAIN, "weapons/electro_fly.wav", VOL_BASE, ATTN_NORM); - //sounds bad - CSQCProjectile(proj, TRUE, PROJECTILE_ELECTRO_BEAM, TRUE); other = proj; MUTATOR_CALLHOOK(EditProjectile); @@ -145,9 +148,11 @@ void W_Electro_Attack() void W_Electro_Attack2() { - local entity proj; + entity proj; + + W_DecreaseAmmo(ammo_cells, autocvar_g_balance_electro_secondary_ammo, autocvar_g_balance_electro_reload_ammo); - W_SetupShot_ProjectileSize (self, '0 0 -4', '0 0 -4', FALSE, 2, "weapons/electro_fire2.wav", CHAN_WEAPON, autocvar_g_balance_electro_secondary_damage); + W_SetupShot_ProjectileSize (self, '0 0 -4', '0 0 -4', FALSE, 2, "weapons/electro_fire2.wav", CH_WEAPON_A, autocvar_g_balance_electro_secondary_damage); w_shotdir = v_forward; // no TrueAim for grenades please @@ -155,7 +160,7 @@ void W_Electro_Attack2() proj = spawn (); proj.classname = "plasma"; - proj.owner = self; + proj.owner = proj.realowner = self; proj.use = W_Plasma_Explode; proj.think = adaptor_think2use_hittype_splash; proj.bot_dodge = TRUE; @@ -165,8 +170,6 @@ void W_Electro_Attack2() proj.projectiledeathtype = WEP_ELECTRO | HITTYPE_SECONDARY; setorigin(proj, w_shotorg); - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_cells = self.ammo_cells - autocvar_g_balance_electro_secondary_ammo; //proj.glow_size = 50; //proj.glow_color = 45; proj.movetype = MOVETYPE_BOUNCE; @@ -178,6 +181,7 @@ void W_Electro_Attack2() proj.health = autocvar_g_balance_electro_secondary_health; proj.event_damage = W_Plasma_Damage; proj.flags = FL_PROJECTILE; + proj.damagedbycontents = (autocvar_g_balance_electro_secondary_damagedbycontents); proj.bouncefactor = autocvar_g_balance_electro_secondary_bouncefactor; proj.bouncestop = autocvar_g_balance_electro_secondary_bouncestop; @@ -193,19 +197,19 @@ void W_Electro_Attack2() CSQCProjectile(proj, TRUE, PROJECTILE_ELECTRO, FALSE); // no culling, it has sound other = proj; MUTATOR_CALLHOOK(EditProjectile); - } +} .vector hook_start, hook_end; float lgbeam_send(entity to, float sf) { WriteByte(MSG_ENTITY, ENT_CLIENT_LGBEAM); sf = sf & 0x7F; - if(sound_allowed(MSG_BROADCAST, self.owner)) + if(sound_allowed(MSG_BROADCAST, self.realowner)) sf |= 0x80; WriteByte(MSG_ENTITY, sf); if(sf & 1) { - WriteByte(MSG_ENTITY, num_for_edict(self.owner)); + WriteByte(MSG_ENTITY, num_for_edict(self.realowner)); WriteCoord(MSG_ENTITY, autocvar_g_balance_electro_primary_range); } if(sf & 2) @@ -224,39 +228,70 @@ float lgbeam_send(entity to, float sf) } .entity lgbeam; .float prevlgfire; +float lgbeam_checkammo() +{ + if(self.realowner.items & IT_UNLIMITED_WEAPON_AMMO) + return TRUE; + else if(autocvar_g_balance_electro_reload_ammo) + return self.realowner.clip_load > 0; + else + return self.realowner.ammo_cells > 0; +} + +entity lgbeam_owner_ent; void lgbeam_think() { - self.owner.prevlgfire = time; - if (self != self.owner.lgbeam) + entity owner_player; + owner_player = self.realowner; + + owner_player.prevlgfire = time; + if (self != owner_player.lgbeam) { remove(self); return; } - if (self.owner.weaponentity.state != WS_INUSE || (self.owner.ammo_cells <= 0 && !(self.owner.items & IT_UNLIMITED_WEAPON_AMMO)) || self.owner.deadflag != DEAD_NO || !self.owner.BUTTON_ATCK || (g_freezetag && self.owner.freezetag_frozen)) + + if (owner_player.weaponentity.state != WS_INUSE || !lgbeam_checkammo() || owner_player.deadflag != DEAD_NO || !owner_player.BUTTON_ATCK || owner_player.freezetag_frozen) { - if(self == self.owner.lgbeam) - self.owner.lgbeam = world; + if(self == owner_player.lgbeam) + owner_player.lgbeam = world; remove(self); return; } self.nextthink = time; - makevectors(self.owner.v_angle); + makevectors(owner_player.v_angle); float dt, f; dt = frametime; - if not(self.owner.items & IT_UNLIMITED_WEAPON_AMMO) + + // if this weapon is reloadable, decrease its load. Else decrease the player's ammo + if not(owner_player.items & IT_UNLIMITED_WEAPON_AMMO) { if(autocvar_g_balance_electro_primary_ammo) { - dt = min(dt, self.owner.ammo_cells / autocvar_g_balance_electro_primary_ammo); - self.owner.ammo_cells = max(0, self.owner.ammo_cells - autocvar_g_balance_electro_primary_ammo * frametime); + if(autocvar_g_balance_electro_reload_ammo) + { + dt = min(dt, owner_player.clip_load / autocvar_g_balance_electro_primary_ammo); + owner_player.clip_load = max(0, owner_player.clip_load - autocvar_g_balance_electro_primary_ammo * frametime); + owner_player.(weapon_load[WEP_ELECTRO]) = owner_player.clip_load; + } + else + { + dt = min(dt, owner_player.ammo_cells / autocvar_g_balance_electro_primary_ammo); + owner_player.ammo_cells = max(0, owner_player.ammo_cells - autocvar_g_balance_electro_primary_ammo * frametime); + } } } - W_SetupShot_Range(self.owner, TRUE, 0, "", 0, autocvar_g_balance_electro_primary_damage * dt, autocvar_g_balance_electro_primary_range); - WarpZone_traceline_antilag(self.owner, w_shotorg, w_shotend, MOVE_NORMAL, self.owner, ANTILAG_LATENCY(self.owner)); + W_SetupShot_Range(owner_player, TRUE, 0, "", 0, autocvar_g_balance_electro_primary_damage * dt, autocvar_g_balance_electro_primary_range); + if(!lgbeam_owner_ent) + { + lgbeam_owner_ent = spawn(); + lgbeam_owner_ent.classname = "lgbeam_owner_ent"; + } + WarpZone_traceline_antilag(lgbeam_owner_ent, w_shotorg, w_shotend, MOVE_NORMAL, lgbeam_owner_ent, ANTILAG_LATENCY(owner_player)); // apply the damage if(trace_ent) @@ -266,11 +301,11 @@ void lgbeam_think() f = ExponentialFalloff(autocvar_g_balance_electro_primary_falloff_mindist, autocvar_g_balance_electro_primary_falloff_maxdist, autocvar_g_balance_electro_primary_falloff_halflifedist, vlen(WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos) - w_shotorg)); - if(accuracy_isgooddamage(self.owner, trace_ent)) - accuracy_add(self.owner, WEP_ELECTRO, 0, autocvar_g_balance_electro_primary_damage * dt * f); - Damage (trace_ent, self.owner, self.owner, autocvar_g_balance_electro_primary_damage * dt * f, WEP_ELECTRO, trace_endpos, force * dt); + if(accuracy_isgooddamage(owner_player, trace_ent)) + accuracy_add(owner_player, WEP_ELECTRO, 0, autocvar_g_balance_electro_primary_damage * dt * f); + Damage (trace_ent, owner_player, owner_player, autocvar_g_balance_electro_primary_damage * dt * f, WEP_ELECTRO, trace_endpos, force * dt); } - W_Plasma_TriggerCombo(trace_endpos, autocvar_g_balance_electro_primary_comboradius, self.owner); + W_Plasma_TriggerCombo(trace_endpos, autocvar_g_balance_electro_primary_comboradius, owner_player); // draw effect if(w_shotorg != self.hook_start) @@ -290,14 +325,15 @@ void W_Electro_Attack3 (void) { // only play fire sound if 0.5 sec has passed since player let go the fire button if(time - self.prevlgfire > 0.5) - sound (self, CHAN_WEAPON, "weapons/lgbeam_fire.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_WEAPON_A, "weapons/lgbeam_fire.wav", VOL_BASE, ATTN_NORM); entity beam, oldself; self.lgbeam = beam = spawn(); + beam.classname = "lgbeam"; beam.solid = SOLID_NOT; beam.think = lgbeam_think; - beam.owner = self; + beam.owner = beam.realowner = self; beam.movetype = MOVETYPE_NONE; beam.shot_spread = 0; beam.bot_dodge = TRUE; @@ -343,6 +379,7 @@ void w_electro_checkattack() .float BUTTON_ATCK_prev; float w_electro(float req) { + float ammo_amount; if (req == WR_AIM) { self.BUTTON_ATCK=FALSE; @@ -375,8 +412,35 @@ float w_electro(float req) } else if (req == WR_THINK) { + if(autocvar_g_balance_electro_reload_ammo) // forced reload + { + if(autocvar_g_balance_electro_lightning) + { + if(self.clip_load > 0) + ammo_amount = 1; + } + else if(self.clip_load >= autocvar_g_balance_electro_primary_ammo) + ammo_amount = 1; + if(self.clip_load >= autocvar_g_balance_electro_secondary_ammo) + ammo_amount += 1; + + if(!ammo_amount) + { + weapon_action(self.weapon, WR_RELOAD); + return FALSE; + } + } if (self.BUTTON_ATCK) { + if(autocvar_g_balance_electro_lightning) + if(self.BUTTON_ATCK_prev) + { + // prolong the animtime while the gun is being fired + if(self.animstate_startframe == self.anim_shoot_x && self.animstate_numframes == self.anim_shoot_y) + weapon_thinkf(WFRAME_DONTCHANGE, autocvar_g_balance_electro_primary_animtime, w_ready); + else + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_electro_primary_animtime, w_ready); + } if (weapon_prepareattack(0, (autocvar_g_balance_electro_lightning ? 0 : autocvar_g_balance_electro_primary_refire))) { if(autocvar_g_balance_electro_lightning) @@ -385,33 +449,40 @@ float w_electro(float req) { W_Electro_Attack3(); } - self.BUTTON_ATCK_prev = 1; + if(!self.BUTTON_ATCK_prev) + { + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_electro_primary_animtime, w_ready); + self.BUTTON_ATCK_prev = 1; + } } else { W_Electro_Attack(); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_electro_primary_animtime, w_ready); } - weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_electro_primary_animtime, w_ready); } } else { if(autocvar_g_balance_electro_lightning) { if (self.BUTTON_ATCK_prev != 0) { + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_electro_primary_animtime, w_ready); ATTACK_FINISHED(self) = time + autocvar_g_balance_electro_primary_refire * W_WeaponRateFactor(); } self.BUTTON_ATCK_prev = 0; } - } - if (self.BUTTON_ATCK2) - if (time >= self.electro_secondarytime) - if (weapon_prepareattack(1, autocvar_g_balance_electro_secondary_refire)) - { - W_Electro_Attack2(); - self.electro_count = autocvar_g_balance_electro_secondary_count; - weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_electro_secondary_animtime, w_electro_checkattack); - self.electro_secondarytime = time + autocvar_g_balance_electro_secondary_refire2; + if (self.BUTTON_ATCK2) + { + if (time >= self.electro_secondarytime) + if (weapon_prepareattack(1, autocvar_g_balance_electro_secondary_refire)) + { + W_Electro_Attack2(); + self.electro_count = autocvar_g_balance_electro_secondary_count; + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_electro_secondary_animtime, w_electro_checkattack); + self.electro_secondarytime = time + autocvar_g_balance_electro_secondary_refire2 * W_WeaponRateFactor(); + } + } } } else if (req == WR_PRECACHE) @@ -424,28 +495,58 @@ float w_electro(float req) precache_sound ("weapons/electro_fire2.wav"); precache_sound ("weapons/electro_impact.wav"); precache_sound ("weapons/electro_impact_combo.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else if(autocvar_g_balance_electro_lightning) { precache_sound ("weapons/lgbeam_fire.wav"); } } else if (req == WR_SETUP) + { weapon_setup(WEP_ELECTRO); + self.current_ammo = ammo_cells; + } else if (req == WR_CHECKAMMO1) { if(autocvar_g_balance_electro_lightning) - return !autocvar_g_balance_electro_primary_ammo || (self.ammo_cells > 0); + { + if(!autocvar_g_balance_electro_primary_ammo) + ammo_amount = 1; + else + ammo_amount = self.ammo_cells > 0; + ammo_amount += self.(weapon_load[WEP_ELECTRO]) > 0; + } else - return self.ammo_cells >= autocvar_g_balance_electro_primary_ammo; + { + ammo_amount = self.ammo_cells >= autocvar_g_balance_electro_primary_ammo; + ammo_amount += self.(weapon_load[WEP_ELECTRO]) >= autocvar_g_balance_electro_primary_ammo; + } + return ammo_amount; } else if (req == WR_CHECKAMMO2) - return self.ammo_cells >= autocvar_g_balance_electro_secondary_ammo; + { + if(autocvar_g_balance_electro_combo_safeammocheck) // true if you can fire at least one secondary blob AND one primary shot after it, otherwise false. + { + ammo_amount = self.ammo_cells >= autocvar_g_balance_electro_secondary_ammo + autocvar_g_balance_electro_primary_ammo; + ammo_amount += self.(weapon_load[WEP_ELECTRO]) >= autocvar_g_balance_electro_secondary_ammo + autocvar_g_balance_electro_primary_ammo; + } + else + { + ammo_amount = self.ammo_cells >= autocvar_g_balance_electro_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_ELECTRO]) >= autocvar_g_balance_electro_secondary_ammo; + } + return ammo_amount; + } else if (req == WR_RESETPLAYER) { self.electro_secondarytime = time; } + else if (req == WR_RELOAD) + { + W_Reload(min(autocvar_g_balance_electro_primary_ammo, autocvar_g_balance_electro_secondary_ammo), autocvar_g_balance_electro_reload_ammo, autocvar_g_balance_electro_reload_time, "weapons/reload.wav"); + } return TRUE; -}; +} #endif #ifdef CSQC float w_electro(float req) @@ -458,7 +559,7 @@ float w_electro(float req) { pointparticles(particleeffectnum("electro_ballexplode"), org2, '0 0 0', 1); if(!w_issilent) - sound(self, CHAN_PROJECTILE, "weapons/electro_impact.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/electro_impact.wav", VOL_BASE, ATTN_NORM); } else { @@ -467,13 +568,13 @@ float w_electro(float req) // this is sent as "primary (w_deathtype & HITTYPE_BOUNCE)" to distinguish it from (w_deathtype & HITTYPE_SECONDARY) bounced balls pointparticles(particleeffectnum("electro_combo"), org2, '0 0 0', 1); if(!w_issilent) - sound(self, CHAN_PROJECTILE, "weapons/electro_impact_combo.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/electro_impact_combo.wav", VOL_BASE, ATTN_NORM); } else { pointparticles(particleeffectnum("electro_impact"), org2, '0 0 0', 1); if(!w_issilent) - sound(self, CHAN_PROJECTILE, "weapons/electro_impact.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/electro_impact.wav", VOL_BASE, ATTN_NORM); } } } @@ -485,27 +586,27 @@ float w_electro(float req) else if (req == WR_SUICIDEMESSAGE) { if(w_deathtype & HITTYPE_SECONDARY) - w_deathtypestring = "%s could not remember where they put plasma"; + w_deathtypestring = _("%s could not remember where they put their electro plasma"); else - w_deathtypestring = "%s played with plasma"; + w_deathtypestring = _("%s played with electro plasma"); } else if (req == WR_KILLMESSAGE) { if(w_deathtype & HITTYPE_SECONDARY) { if(w_deathtype & HITTYPE_SPLASH) // unchecked: BOUNCE - w_deathtypestring = "%s just noticed %s's blue ball"; + w_deathtypestring = _("%s just noticed %s's electro plasma"); else // unchecked: BOUNCE - w_deathtypestring = "%s got in touch with %s's blue ball"; + w_deathtypestring = _("%s got in touch with %s's electro plasma"); } else { if(w_deathtype & HITTYPE_BOUNCE) // combo - w_deathtypestring = "%s felt the electrifying air of %s's combo"; + w_deathtypestring = _("%s felt the electrifying air of %s's electro combo"); else if(w_deathtype & HITTYPE_SPLASH) - w_deathtypestring = "%s got too close to %s's blue beam"; + w_deathtypestring = _("%s got too close to %s's blue electro bolt"); else - w_deathtypestring = "%s was blasted by %s's blue beam"; + w_deathtypestring = _("%s was blasted by %s's blue electro bolt"); } } return TRUE; diff --git a/qcsrc/server/w_fireball.qc b/qcsrc/server/w_fireball.qc index 98b2b7f740..3cc484da9c 100644 --- a/qcsrc/server/w_fireball.qc +++ b/qcsrc/server/w_fireball.qc @@ -1,5 +1,5 @@ #ifdef REGISTER_WEAPON -REGISTER_WEAPON(FIREBALL, w_fireball, IT_FUEL, 9, WEP_TYPE_SPLASH, BOT_PICKUP_RATING_MID, "fireball", "fireball", "Fireball"); +REGISTER_WEAPON(FIREBALL, w_fireball, IT_FUEL, 9, WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_MID, "fireball", "fireball", _("Fireball")); #else #ifdef SVQC .float bot_primary_fireballmooth; // whatever a mooth is @@ -18,7 +18,7 @@ void W_Fireball_Explode (void) self.takedamage = DAMAGE_NO; // 1. dist damage - d = (self.owner.health + self.owner.armorvalue); + d = (self.realowner.health + self.realowner.armorvalue); RadiusDamage (self, self.realowner, autocvar_g_balance_fireball_primary_damage, autocvar_g_balance_fireball_primary_edgedamage, autocvar_g_balance_fireball_primary_radius, world, autocvar_g_balance_fireball_primary_force, self.projectiledeathtype, other); if(self.realowner.health + self.realowner.armorvalue >= d) if(!self.cnt) @@ -28,7 +28,7 @@ void W_Fireball_Explode (void) // 2. bfg effect // NOTE: this cannot be made warpzone aware by design. So, better intentionally ignore warpzones here. for(e = findradius(self.origin, autocvar_g_balance_fireball_primary_bfgradius); e; e = e.chain) - if(e != self.owner) if(e.takedamage == DAMAGE_AIM) if(e.classname != "player" || !self.owner || IsDifferentTeam(e, self)) + if(e != self.realowner) if(e.takedamage == DAMAGE_AIM) if(e.classname != "player" || !self.realowner || IsDifferentTeam(e, self)) { // can we see fireball? traceline(e.origin + e.view_ofs, self.origin, MOVE_NORMAL, e); @@ -73,7 +73,7 @@ void W_Fireball_LaserPlay(float dt, float dist, float damage, float edgedamage, RandomSelection_Init(); for(e = WarpZone_FindRadius(self.origin, dist, TRUE); e; e = e.chain) - if(e != self.owner) if(e.takedamage == DAMAGE_AIM) if(e.classname != "player" || !self.owner || IsDifferentTeam(e, self)) + if(e != self.realowner) if(e.takedamage == DAMAGE_AIM) if(e.classname != "player" || !self.realowner || IsDifferentTeam(e, self)) { p = e.origin; p_x += e.mins_x + random() * (e.maxs_x - e.mins_x); @@ -115,6 +115,10 @@ void W_Fireball_Damage (entity inflictor, entity attacker, float damage, float d { if(self.health <= 0) return; + + if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions + return; // g_projectiles_damage says to halt + self.health = self.health - damage; if (self.health <= 0) { @@ -125,9 +129,9 @@ void W_Fireball_Damage (entity inflictor, entity attacker, float damage, float d void W_Fireball_Attack1() { - local entity proj; + entity proj; - W_SetupShot_ProjectileSize (self, '-16 -16 -16', '16 16 16', FALSE, 2, "weapons/fireball_fire2.wav", CHAN_WEAPON, autocvar_g_balance_fireball_primary_damage + autocvar_g_balance_fireball_primary_bfgdamage); + W_SetupShot_ProjectileSize (self, '-16 -16 -16', '16 16 16', FALSE, 2, "weapons/fireball_fire2.wav", CH_WEAPON_A, autocvar_g_balance_fireball_primary_damage + autocvar_g_balance_fireball_primary_bfgdamage); pointparticles(particleeffectnum("fireball_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); @@ -194,11 +198,10 @@ void W_Fireball_Attack1_Frame1() void W_Fireball_Attack1_Frame0() { - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_fuel = self.ammo_fuel - autocvar_g_balance_fireball_primary_ammo; + W_DecreaseAmmo(ammo_fuel, autocvar_g_balance_fireball_primary_ammo, autocvar_g_balance_fireball_reload_ammo); W_Fireball_AttackEffect(0, '-1.25 -3.75 0'); - sound (self, CHAN_WEAPON, "weapons/fireball_prefire2.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_WEAPON_SINGLE, "weapons/fireball_prefire2.wav", VOL_BASE, ATTN_NORM); weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_fireball_primary_animtime, W_Fireball_Attack1_Frame1); } @@ -242,12 +245,11 @@ void W_Firemine_Touch (void) void W_Fireball_Attack2() { - local entity proj; + entity proj; vector f_diff; float c; - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_fuel = self.ammo_fuel - autocvar_g_balance_fireball_secondary_ammo; + W_DecreaseAmmo(ammo_fuel, autocvar_g_balance_fireball_secondary_ammo, autocvar_g_balance_fireball_reload_ammo); c = mod(self.bulletcounter, 4); switch(c) @@ -266,7 +268,7 @@ void W_Fireball_Attack2() f_diff = '+1.25 +3.75 0'; break; } - W_SetupShot_ProjectileSize(self, '-4 -4 -4', '4 4 4', FALSE, 2, "weapons/fireball_fire.wav", CHAN_WEAPON, autocvar_g_balance_fireball_secondary_damage); + W_SetupShot_ProjectileSize(self, '-4 -4 -4', '4 4 4', FALSE, 2, "weapons/fireball_fire.wav", CH_WEAPON_A, autocvar_g_balance_fireball_secondary_damage); traceline(w_shotorg, w_shotorg + f_diff_x * v_up + f_diff_y * v_right, MOVE_NORMAL, self); w_shotorg = trace_endpos; @@ -304,6 +306,7 @@ void spawnfunc_weapon_fireball (void) float w_fireball(float req) { + float ammo_amount; if (req == WR_AIM) { self.BUTTON_ATCK = FALSE; @@ -327,18 +330,24 @@ float w_fireball(float req) } else if (req == WR_THINK) { - if (self.BUTTON_ATCK) - if (time >= self.fireball_primarytime) - if (weapon_prepareattack(0, autocvar_g_balance_fireball_primary_refire)) + if(autocvar_g_balance_fireball_reload_ammo && self.clip_load < min(autocvar_g_balance_fireball_primary_ammo, autocvar_g_balance_fireball_secondary_ammo)) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else if (self.BUTTON_ATCK) { - W_Fireball_Attack1_Frame0(); - self.fireball_primarytime = time + autocvar_g_balance_fireball_primary_refire2; + if (time >= self.fireball_primarytime) + if (weapon_prepareattack(0, autocvar_g_balance_fireball_primary_refire)) + { + W_Fireball_Attack1_Frame0(); + self.fireball_primarytime = time + autocvar_g_balance_fireball_primary_refire2 * W_WeaponRateFactor(); + } } - if (self.BUTTON_ATCK2) - if (weapon_prepareattack(1, autocvar_g_balance_fireball_secondary_refire)) + else if (self.BUTTON_ATCK2) { - W_Fireball_Attack2(); - weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_fireball_secondary_animtime, w_ready); + if (weapon_prepareattack(1, autocvar_g_balance_fireball_secondary_refire)) + { + W_Fireball_Attack2(); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_fireball_secondary_animtime, w_ready); + } } } else if (req == WR_PRECACHE) @@ -350,19 +359,39 @@ float w_fireball(float req) precache_sound ("weapons/fireball_fire.wav"); precache_sound ("weapons/fireball_fire2.wav"); precache_sound ("weapons/fireball_prefire2.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else } else if (req == WR_SETUP) + { weapon_setup(WEP_FIREBALL); + self.current_ammo = ammo_fuel; + } else if (req == WR_CHECKAMMO1) - return self.ammo_fuel >= autocvar_g_balance_fireball_primary_ammo; + { + ammo_amount = self.ammo_fuel >= autocvar_g_balance_fireball_primary_ammo; + ammo_amount += self.(weapon_load[WEP_FIREBALL]) >= autocvar_g_balance_fireball_primary_ammo; + return ammo_amount; + } else if (req == WR_CHECKAMMO2) - return self.ammo_fuel >= autocvar_g_balance_fireball_secondary_ammo; + { + ammo_amount = self.ammo_fuel >= autocvar_g_balance_fireball_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_FIREBALL]) >= autocvar_g_balance_fireball_secondary_ammo; + return ammo_amount; + } else if (req == WR_RESETPLAYER) { self.fireball_primarytime = time; } + else if (req == WR_RELOAD) + { + // fuel can be a non-whole number, which brakes stuff here when between 0 and 1 + if(self.ammo_fuel < 1) + self.ammo_fuel = 0; + + W_Reload(min(autocvar_g_balance_fireball_primary_ammo, autocvar_g_balance_fireball_secondary_ammo), autocvar_g_balance_fireball_reload_ammo, autocvar_g_balance_fireball_reload_time, "weapons/reload.wav"); + } return TRUE; -}; +} #endif #ifdef CSQC float w_fireball(float req) @@ -379,7 +408,7 @@ float w_fireball(float req) org2 = w_org + w_backoff * 16; pointparticles(particleeffectnum("fireball_explode"), org2, '0 0 0', 1); if(!w_issilent) - sound(self, CHAN_PROJECTILE, "weapons/fireball_impact2.wav", VOL_BASE, ATTN_NORM * 0.25); // long range boom + sound(self, CH_SHOTS, "weapons/fireball_impact2.wav", VOL_BASE, ATTN_NORM * 0.25); // long range boom } } else if(req == WR_PRECACHE) @@ -389,32 +418,32 @@ float w_fireball(float req) else if (req == WR_SUICIDEMESSAGE) { if(w_deathtype & HITTYPE_SECONDARY) - w_deathtypestring = "%s forgot about some firemine"; + w_deathtypestring = _("%s forgot about some firemine"); else - w_deathtypestring = "%s should have used a smaller gun"; + w_deathtypestring = _("%s should have used a smaller gun"); } else if (req == WR_KILLMESSAGE) { if(w_deathtype & HITTYPE_SECONDARY) { if(w_deathtype & HITTYPE_HEADSHOT) - w_deathtypestring = "%s tried to catch %s's firemine"; + w_deathtypestring = _("%s tried to catch %s's firemine"); else - w_deathtypestring = "%s fatefully ignored %s's firemine"; + w_deathtypestring = _("%s fatefully ignored %s's firemine"); } else { if(w_deathtype & HITTYPE_BOUNCE) { if(w_deathtype & HITTYPE_SPLASH) // BFG effect - w_deathtypestring = "%s could not hide from %s's fireball"; + w_deathtypestring = _("%s could not hide from %s's fireball"); else // laser - w_deathtypestring = "%s saw the pretty lights of %s's fireball"; + w_deathtypestring = _("%s saw the pretty lights of %s's fireball"); } else if(w_deathtype & HITTYPE_SPLASH) - w_deathtypestring = "%s got too close to %s's fireball"; + w_deathtypestring = _("%s got too close to %s's fireball"); else - w_deathtypestring = "%s tasted %s's fireball"; + w_deathtypestring = _("%s tasted %s's fireball"); } } return TRUE; diff --git a/qcsrc/server/w_grenadelauncher.qc b/qcsrc/server/w_grenadelauncher.qc index b46c091ce5..352ce883bd 100644 --- a/qcsrc/server/w_grenadelauncher.qc +++ b/qcsrc/server/w_grenadelauncher.qc @@ -1,5 +1,5 @@ #ifdef REGISTER_WEAPON -REGISTER_WEAPON(GRENADE_LAUNCHER, w_glauncher, IT_ROCKETS, 4, WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_MID, "gl", "grenadelauncher", "Mortar"); +REGISTER_WEAPON(GRENADE_LAUNCHER, w_glauncher, IT_ROCKETS, 4, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_MID, "gl", "grenadelauncher", _("Mortar")) #else #ifdef SVQC .float gl_detonate_later; @@ -9,10 +9,10 @@ void W_Grenade_Explode (void) { if(other.takedamage == DAMAGE_AIM) if(other.classname == "player") - if(IsDifferentTeam(self.owner, other)) + if(IsDifferentTeam(self.realowner, other)) if(other.deadflag == DEAD_NO) if(IsFlying(other)) - AnnounceTo(self.owner, "airshot"); + AnnounceTo(self.realowner, "airshot"); self.event_damage = SUB_Null; self.takedamage = DAMAGE_NO; @@ -20,7 +20,7 @@ void W_Grenade_Explode (void) if(self.movetype == MOVETYPE_NONE) self.velocity = self.oldvelocity; - RadiusDamage (self, self.owner, autocvar_g_balance_grenadelauncher_primary_damage, autocvar_g_balance_grenadelauncher_primary_edgedamage, autocvar_g_balance_grenadelauncher_primary_radius, world, autocvar_g_balance_grenadelauncher_primary_force, self.projectiledeathtype, other); + RadiusDamage (self, self.realowner, autocvar_g_balance_grenadelauncher_primary_damage, autocvar_g_balance_grenadelauncher_primary_edgedamage, autocvar_g_balance_grenadelauncher_primary_radius, world, autocvar_g_balance_grenadelauncher_primary_force, self.projectiledeathtype, other); remove (self); } @@ -29,9 +29,10 @@ void W_Grenade_Explode2 (void) { if(other.takedamage == DAMAGE_AIM) if(other.classname == "player") - if(IsDifferentTeam(self.owner, other)) - if(IsFlying(other)) - AnnounceTo(self.owner, "airshot"); + if(IsDifferentTeam(self.realowner, other)) + if(other.deadflag == DEAD_NO) + if(IsFlying(other)) + AnnounceTo(self.realowner, "airshot"); self.event_damage = SUB_Null; self.takedamage = DAMAGE_NO; @@ -39,7 +40,7 @@ void W_Grenade_Explode2 (void) if(self.movetype == MOVETYPE_NONE) self.velocity = self.oldvelocity; - RadiusDamage (self, self.owner, autocvar_g_balance_grenadelauncher_secondary_damage, autocvar_g_balance_grenadelauncher_secondary_edgedamage, autocvar_g_balance_grenadelauncher_secondary_radius, world, autocvar_g_balance_grenadelauncher_secondary_force, self.projectiledeathtype, other); + RadiusDamage (self, self.realowner, autocvar_g_balance_grenadelauncher_secondary_damage, autocvar_g_balance_grenadelauncher_secondary_edgedamage, autocvar_g_balance_grenadelauncher_secondary_radius, world, autocvar_g_balance_grenadelauncher_secondary_force, self.projectiledeathtype, other); remove (self); } @@ -48,11 +49,14 @@ void W_Grenade_Damage (entity inflictor, entity attacker, float damage, float de { if (self.health <= 0) return; + + if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions + return; // g_projectiles_damage says to halt + self.health = self.health - damage; + if (self.health <= 0) - { - W_PrepareExplosionByDamage(attacker, self.think); - } + W_PrepareExplosionByDamage(attacker, self.use); } void W_Grenade_Think1 (void) @@ -81,23 +85,23 @@ void W_Grenade_Touch1 (void) float r; r = random() * 6; if(r < 1) - spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce1.wav", VOL_BASE, ATTN_NORM); + spamsound (self, CH_SHOTS, "weapons/grenade_bounce1.wav", VOL_BASE, ATTN_NORM); else if(r < 2) - spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce2.wav", VOL_BASE, ATTN_NORM); + spamsound (self, CH_SHOTS, "weapons/grenade_bounce2.wav", VOL_BASE, ATTN_NORM); else if(r < 3) - spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce3.wav", VOL_BASE, ATTN_NORM); + spamsound (self, CH_SHOTS, "weapons/grenade_bounce3.wav", VOL_BASE, ATTN_NORM); else if(r < 4) - spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce4.wav", VOL_BASE, ATTN_NORM); + spamsound (self, CH_SHOTS, "weapons/grenade_bounce4.wav", VOL_BASE, ATTN_NORM); else if(r < 5) - spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce5.wav", VOL_BASE, ATTN_NORM); + spamsound (self, CH_SHOTS, "weapons/grenade_bounce5.wav", VOL_BASE, ATTN_NORM); else - spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce6.wav", VOL_BASE, ATTN_NORM); + spamsound (self, CH_SHOTS, "weapons/grenade_bounce6.wav", VOL_BASE, ATTN_NORM); self.projectiledeathtype |= HITTYPE_BOUNCE; self.gl_bouncecnt += 1; } else if(autocvar_g_balance_grenadelauncher_primary_type == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick { - spamsound (self, CHAN_PROJECTILE, "weapons/grenade_stick.wav", VOL_BASE, ATTN_NORM); + spamsound (self, CH_SHOTS, "weapons/grenade_stick.wav", VOL_BASE, ATTN_NORM); // let it stick whereever it is self.oldvelocity = self.velocity; @@ -109,7 +113,7 @@ void W_Grenade_Touch1 (void) // do not respond to any more touches self.solid = SOLID_NOT; - self.nextthink = min(self.nextthink, time + autocvar_g_balance_grenadelauncher_primary_lifetime2); + self.nextthink = min(self.nextthink, time + autocvar_g_balance_grenadelauncher_primary_lifetime_stick); } } @@ -125,23 +129,27 @@ void W_Grenade_Touch2 (void) float r; r = random() * 6; if(r < 1) - spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce1.wav", VOL_BASE, ATTN_NORM); + spamsound (self, CH_SHOTS, "weapons/grenade_bounce1.wav", VOL_BASE, ATTN_NORM); else if(r < 2) - spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce2.wav", VOL_BASE, ATTN_NORM); + spamsound (self, CH_SHOTS, "weapons/grenade_bounce2.wav", VOL_BASE, ATTN_NORM); else if(r < 3) - spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce3.wav", VOL_BASE, ATTN_NORM); + spamsound (self, CH_SHOTS, "weapons/grenade_bounce3.wav", VOL_BASE, ATTN_NORM); else if(r < 4) - spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce4.wav", VOL_BASE, ATTN_NORM); + spamsound (self, CH_SHOTS, "weapons/grenade_bounce4.wav", VOL_BASE, ATTN_NORM); else if(r < 5) - spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce5.wav", VOL_BASE, ATTN_NORM); + spamsound (self, CH_SHOTS, "weapons/grenade_bounce5.wav", VOL_BASE, ATTN_NORM); else - spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce6.wav", VOL_BASE, ATTN_NORM); + spamsound (self, CH_SHOTS, "weapons/grenade_bounce6.wav", VOL_BASE, ATTN_NORM); self.projectiledeathtype |= HITTYPE_BOUNCE; self.gl_bouncecnt += 1; + + if (autocvar_g_balance_grenadelauncher_secondary_lifetime_bounce && self.gl_bouncecnt == 1) + self.nextthink = time + autocvar_g_balance_grenadelauncher_secondary_lifetime_bounce; + } else if(autocvar_g_balance_grenadelauncher_secondary_type == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick { - spamsound (self, CHAN_PROJECTILE, "weapons/grenade_stick.wav", VOL_BASE, ATTN_NORM); + spamsound (self, CH_SHOTS, "weapons/grenade_stick.wav", VOL_BASE, ATTN_NORM); // let it stick whereever it is self.oldvelocity = self.velocity; @@ -153,23 +161,23 @@ void W_Grenade_Touch2 (void) // do not respond to any more touches self.solid = SOLID_NOT; - self.nextthink = min(self.nextthink, time + autocvar_g_balance_grenadelauncher_secondary_lifetime2); + self.nextthink = min(self.nextthink, time + autocvar_g_balance_grenadelauncher_secondary_lifetime_stick); } } void W_Grenade_Attack (void) { - local entity gren; + entity gren; + + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_grenadelauncher_primary_ammo, autocvar_g_balance_grenadelauncher_reload_ammo); - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_rockets = self.ammo_rockets - autocvar_g_balance_grenadelauncher_primary_ammo; - W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CHAN_WEAPON, autocvar_g_balance_grenadelauncher_primary_damage); + W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CH_WEAPON_A, autocvar_g_balance_grenadelauncher_primary_damage); w_shotdir = v_forward; // no TrueAim for grenades please pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); gren = spawn (); - gren.owner = self; + gren.owner = gren.realowner = self; gren.classname = "grenade"; gren.bot_dodge = TRUE; gren.bot_dodgerating = autocvar_g_balance_grenadelauncher_primary_damage; @@ -191,6 +199,7 @@ void W_Grenade_Attack (void) gren.health = autocvar_g_balance_grenadelauncher_primary_health; gren.damageforcescale = autocvar_g_balance_grenadelauncher_primary_damageforcescale; gren.event_damage = W_Grenade_Damage; + gren.damagedbycontents = TRUE; W_SETUPPROJECTILEVELOCITY_UP(gren, g_balance_grenadelauncher_primary); gren.angles = vectoangles (gren.velocity); @@ -206,17 +215,17 @@ void W_Grenade_Attack (void) void W_Grenade_Attack2 (void) { - local entity gren; + entity gren; - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_rockets = self.ammo_rockets - autocvar_g_balance_grenadelauncher_secondary_ammo; - W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CHAN_WEAPON, autocvar_g_balance_grenadelauncher_secondary_damage); + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_grenadelauncher_secondary_ammo, autocvar_g_balance_grenadelauncher_reload_ammo); + + W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CH_WEAPON_A, autocvar_g_balance_grenadelauncher_secondary_damage); w_shotdir = v_forward; // no TrueAim for grenades please pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); gren = spawn (); - gren.owner = self; + gren.owner = gren.realowner = self; gren.classname = "grenade"; gren.bot_dodge = TRUE; gren.bot_dodgerating = autocvar_g_balance_grenadelauncher_secondary_damage; @@ -237,6 +246,7 @@ void W_Grenade_Attack2 (void) gren.health = autocvar_g_balance_grenadelauncher_secondary_health; gren.damageforcescale = autocvar_g_balance_grenadelauncher_secondary_damageforcescale; gren.event_damage = W_Grenade_Damage; + gren.damagedbycontents = TRUE; W_SETUPPROJECTILEVELOCITY_UP(gren, g_balance_grenadelauncher_secondary); gren.angles = vectoangles (gren.velocity); @@ -260,6 +270,7 @@ float w_glauncher(float req) { entity nade; float nadefound; + float ammo_amount; if (req == WR_AIM) { @@ -284,18 +295,22 @@ float w_glauncher(float req) } else if (req == WR_THINK) { - if (self.BUTTON_ATCK) - if (weapon_prepareattack(0, autocvar_g_balance_grenadelauncher_primary_refire)) + if(autocvar_g_balance_grenadelauncher_reload_ammo && self.clip_load < min(autocvar_g_balance_grenadelauncher_primary_ammo, autocvar_g_balance_grenadelauncher_secondary_ammo)) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else if (self.BUTTON_ATCK) { - W_Grenade_Attack(); - weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_grenadelauncher_primary_animtime, w_ready); + if (weapon_prepareattack(0, autocvar_g_balance_grenadelauncher_primary_refire)) + { + W_Grenade_Attack(); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_grenadelauncher_primary_animtime, w_ready); + } } - if (self.BUTTON_ATCK2) + else if (self.BUTTON_ATCK2) { if (cvar("g_balance_grenadelauncher_secondary_remote_detonateprimary")) { nadefound = 0; - for(nade = world; (nade = find(nade, classname, "grenade")); ) if(nade.owner == self) + for(nade = world; (nade = find(nade, classname, "grenade")); ) if(nade.realowner == self) { if(!nade.gl_detonate_later) { @@ -304,7 +319,7 @@ float w_glauncher(float req) } } if(nadefound) - sound (self, CHAN_WEAPON2, "weapons/rocket_det.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_WEAPON_B, "weapons/rocket_det.wav", VOL_BASE, ATTN_NORM); } else if (weapon_prepareattack(1, autocvar_g_balance_grenadelauncher_secondary_refire)) { @@ -326,15 +341,31 @@ float w_glauncher(float req) precache_sound ("weapons/grenade_bounce6.wav"); precache_sound ("weapons/grenade_stick.wav"); precache_sound ("weapons/grenade_fire.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else } else if (req == WR_SETUP) + { weapon_setup(WEP_GRENADE_LAUNCHER); + self.current_ammo = ammo_rockets; + } else if (req == WR_CHECKAMMO1) - return self.ammo_rockets >= autocvar_g_balance_grenadelauncher_primary_ammo; + { + ammo_amount = self.ammo_rockets >= autocvar_g_balance_grenadelauncher_primary_ammo; + ammo_amount += self.(weapon_load[WEP_GRENADE_LAUNCHER]) >= autocvar_g_balance_grenadelauncher_primary_ammo; + return ammo_amount; + } else if (req == WR_CHECKAMMO2) - return self.ammo_rockets >= autocvar_g_balance_grenadelauncher_secondary_ammo; + { + ammo_amount = self.ammo_rockets >= autocvar_g_balance_grenadelauncher_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_GRENADE_LAUNCHER]) >= autocvar_g_balance_grenadelauncher_secondary_ammo; + return ammo_amount; + } + else if (req == WR_RELOAD) + { + W_Reload(min(autocvar_g_balance_grenadelauncher_primary_ammo, autocvar_g_balance_grenadelauncher_secondary_ammo), autocvar_g_balance_grenadelauncher_reload_ammo, autocvar_g_balance_grenadelauncher_reload_time, "weapons/reload.wav"); + } return TRUE; -}; +} #endif #ifdef CSQC float w_glauncher(float req) @@ -345,7 +376,7 @@ float w_glauncher(float req) org2 = w_org + w_backoff * 12; pointparticles(particleeffectnum("grenade_explode"), org2, '0 0 0', 1); if(!w_issilent) - sound(self, CHAN_PROJECTILE, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM); } else if(req == WR_PRECACHE) { @@ -354,19 +385,19 @@ float w_glauncher(float req) else if (req == WR_SUICIDEMESSAGE) { if(w_deathtype & HITTYPE_SECONDARY) - w_deathtypestring = "%s tried out his own grenade"; + w_deathtypestring = _("%s didn't see their own grenade"); else - w_deathtypestring = "%s detonated"; + w_deathtypestring = _("%s blew themself up with their grenadelauncher"); } else if (req == WR_KILLMESSAGE) { if(w_deathtype & HITTYPE_SPLASH) if(w_deathtype & HITTYPE_BOUNCE) // (must be secondary then) - w_deathtypestring = "%s didn't see %s's grenade"; + w_deathtypestring = _("%s didn't see %s's grenade"); else // unchecked: SECONDARY - w_deathtypestring = "%s almost dodged %s's grenade"; + w_deathtypestring = _("%s almost dodged %s's grenade"); else // unchecked: SECONDARY, BOUNCE - w_deathtypestring = "%s ate %s's grenade"; + w_deathtypestring = _("%s ate %s's grenade"); } return TRUE; } diff --git a/qcsrc/server/w_hagar.qc b/qcsrc/server/w_hagar.qc index 472a1e0d51..76103f347e 100644 --- a/qcsrc/server/w_hagar.qc +++ b/qcsrc/server/w_hagar.qc @@ -1,8 +1,9 @@ #ifdef REGISTER_WEAPON -REGISTER_WEAPON(HAGAR, w_hagar, IT_ROCKETS, 8, WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_MID, "hagar", "hagar", "Hagar"); +REGISTER_WEAPON(HAGAR, w_hagar, IT_ROCKETS, 8, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_MID, "hagar", "hagar", _("Hagar")) #else #ifdef SVQC // NO bounce protection, as bounces are limited! + void W_Hagar_Explode (void) { self.event_damage = SUB_Null; @@ -19,6 +20,30 @@ void W_Hagar_Explode2 (void) remove (self); } +void W_Hagar_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) +{ + if (self.health <= 0) + return; + + float is_linkexplode = ( ((inflictor.owner != world) ? (inflictor.owner == self.owner) : TRUE) + && (inflictor.projectiledeathtype & HITTYPE_SECONDARY) + && (self.projectiledeathtype & HITTYPE_SECONDARY)); + + if(is_linkexplode) + is_linkexplode = (is_linkexplode && autocvar_g_balance_hagar_secondary_load_linkexplode); + else + is_linkexplode = -1; // not secondary load, so continue as normal without exception. + + if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, is_linkexplode)) + return; // g_projectiles_damage says to halt + + self.health = self.health - damage; + self.angles = vectoangles(self.velocity); + + if (self.health <= 0) + W_PrepareExplosionByDamage(attacker, self.think); +} + void W_Hagar_Touch (void) { PROJECTILE_TOUCH; @@ -42,11 +67,11 @@ void W_Hagar_Touch2 (void) void W_Hagar_Attack (void) { - local entity missile; + entity missile; - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_rockets = self.ammo_rockets - autocvar_g_balance_hagar_primary_ammo; - W_SetupShot (self, FALSE, 2, "weapons/hagar_fire.wav", CHAN_WEAPON, autocvar_g_balance_hagar_primary_damage); + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_hagar_primary_ammo, autocvar_g_balance_hagar_reload_ammo); + + W_SetupShot (self, FALSE, 2, "weapons/hagar_fire.wav", CH_WEAPON_A, autocvar_g_balance_hagar_primary_damage); pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); @@ -55,6 +80,13 @@ void W_Hagar_Attack (void) missile.classname = "missile"; missile.bot_dodge = TRUE; missile.bot_dodgerating = autocvar_g_balance_hagar_primary_damage; + + missile.takedamage = DAMAGE_YES; + missile.health = autocvar_g_balance_hagar_primary_health; + missile.damageforcescale = autocvar_g_balance_hagar_primary_damageforcescale; + missile.event_damage = W_Hagar_Damage; + missile.damagedbycontents = TRUE; + missile.touch = W_Hagar_Touch; missile.use = W_Hagar_Explode; missile.think = adaptor_think2use_hittype_splash; @@ -77,11 +109,11 @@ void W_Hagar_Attack (void) void W_Hagar_Attack2 (void) { - local entity missile; + entity missile; + + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_hagar_secondary_ammo, autocvar_g_balance_hagar_reload_ammo); - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_rockets = self.ammo_rockets - autocvar_g_balance_hagar_secondary_ammo; - W_SetupShot (self, FALSE, 2, "weapons/hagar_fire.wav", CHAN_WEAPON, autocvar_g_balance_hagar_secondary_damage); + W_SetupShot (self, FALSE, 2, "weapons/hagar_fire.wav", CH_WEAPON_A, autocvar_g_balance_hagar_secondary_damage); pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); @@ -90,6 +122,13 @@ void W_Hagar_Attack2 (void) missile.classname = "missile"; missile.bot_dodge = TRUE; missile.bot_dodgerating = autocvar_g_balance_hagar_secondary_damage; + + missile.takedamage = DAMAGE_YES; + missile.health = autocvar_g_balance_hagar_secondary_health; + missile.damageforcescale = autocvar_g_balance_hagar_secondary_damageforcescale; + missile.event_damage = W_Hagar_Damage; + missile.damagedbycontents = TRUE; + missile.touch = W_Hagar_Touch2; missile.cnt = 0; missile.use = W_Hagar_Explode2; @@ -111,6 +150,187 @@ void W_Hagar_Attack2 (void) other = missile; MUTATOR_CALLHOOK(EditProjectile); } +.float hagar_loadstep, hagar_loadblock, hagar_loadbeep, hagar_warning; +void W_Hagar_Attack2_Load_Release (void) +{ + // time to release the rockets we've loaded + + entity missile; + float counter, shots, spread_pershot; + vector s; + vector forward, right, up; + + if(!self.hagar_load) + return; + + weapon_prepareattack_do(1, autocvar_g_balance_hagar_secondary_refire); + + W_SetupShot (self, FALSE, 2, "weapons/hagar_fire.wav", CH_WEAPON_A, autocvar_g_balance_hagar_secondary_damage); + pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); + + forward = v_forward; + right = v_right; + up = v_up; + + shots = self.hagar_load; + missile = world; + while (counter < shots) + { + missile = spawn (); + missile.owner = missile.realowner = self; + missile.classname = "missile"; + missile.bot_dodge = TRUE; + missile.bot_dodgerating = autocvar_g_balance_hagar_secondary_damage; + + missile.takedamage = DAMAGE_YES; + missile.health = autocvar_g_balance_hagar_secondary_health; + missile.damageforcescale = autocvar_g_balance_hagar_secondary_damageforcescale; + missile.event_damage = W_Hagar_Damage; + missile.damagedbycontents = TRUE; + + missile.touch = W_Hagar_Touch; // not bouncy + missile.use = W_Hagar_Explode2; + missile.think = adaptor_think2use_hittype_splash; + missile.nextthink = time + autocvar_g_balance_hagar_secondary_lifetime_min + random() * autocvar_g_balance_hagar_secondary_lifetime_rand; + PROJECTILE_MAKETRIGGER(missile); + missile.projectiledeathtype = WEP_HAGAR | HITTYPE_SECONDARY; + setorigin (missile, w_shotorg); + setsize(missile, '0 0 0', '0 0 0'); + missile.movetype = MOVETYPE_FLY; + + // per-shot spread calculation: the more shots there are, the less spread is applied (based on the bias cvar) + spread_pershot = ((shots - 1) / (autocvar_g_balance_hagar_secondary_load_max - 1)); + spread_pershot = (1 - (spread_pershot * autocvar_g_balance_hagar_secondary_load_spread_bias)); + spread_pershot = (autocvar_g_balance_hagar_secondary_spread * spread_pershot * g_weaponspreadfactor); + + // pattern spread calculation + s = '0 0 0'; + if (counter == 0) + s = '0 0 0'; + else + { + makevectors('0 360 0' * (0.75 + (counter - 0.5) / (shots - 1))); + s_y = v_forward_x; + s_z = v_forward_y; + } + s = s * autocvar_g_balance_hagar_secondary_load_spread * g_weaponspreadfactor; + + W_SetupProjectileVelocityEx(missile, w_shotdir + right * s_y + up * s_z, v_up, autocvar_g_balance_hagar_secondary_speed, 0, 0, spread_pershot, FALSE); + + missile.angles = vectoangles (missile.velocity); + missile.flags = FL_PROJECTILE; + + CSQCProjectile(missile, TRUE, PROJECTILE_HAGAR, TRUE); + + other = missile; MUTATOR_CALLHOOK(EditProjectile); + + counter = counter + 1; + } + + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_hagar_secondary_load_animtime, w_ready); + self.hagar_loadstep = time + autocvar_g_balance_hagar_secondary_refire * W_WeaponRateFactor(); + self.hagar_load = 0; +} + +void W_Hagar_Attack2_Load (void) +{ + // loadable hagar secondary attack, must always run each frame + + float loaded, enough_ammo; + loaded = self.hagar_load >= autocvar_g_balance_hagar_secondary_load_max; + + // this is different than WR_CHECKAMMO when it comes to reloading + if(autocvar_g_balance_hagar_reload_ammo) + enough_ammo = self.(weapon_load[WEP_HAGAR]) >= autocvar_g_balance_hagar_secondary_ammo; + else + enough_ammo = self.ammo_rockets >= autocvar_g_balance_hagar_secondary_ammo; + + if(self.BUTTON_ATCK2) + { + if(self.BUTTON_ATCK && autocvar_g_balance_hagar_secondary_load_abort) + { + if(self.hagar_load) + { + // if we pressed primary fire while loading, unload all rockets and abort + self.weaponentity.state = WS_READY; + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_hagar_secondary_ammo * self.hagar_load * -1, autocvar_g_balance_hagar_reload_ammo); // give back ammo + self.hagar_load = 0; + sound(self, CH_WEAPON_A, "weapons/hagar_beep.wav", VOL_BASE, ATTN_NORM); + + // pause until we can load rockets again, once we re-press the alt fire button + self.hagar_loadstep = time + autocvar_g_balance_hagar_secondary_load_speed * W_WeaponRateFactor(); + + // require letting go of the alt fire button before we can load again + self.hagar_loadblock = TRUE; + } + } + else + { + // check if we can attempt to load another rocket + if(!loaded && enough_ammo) + { + if(!self.hagar_loadblock && self.hagar_loadstep < time) + { + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_hagar_secondary_ammo, autocvar_g_balance_hagar_reload_ammo); + self.weaponentity.state = WS_INUSE; + self.hagar_load += 1; + sound(self, CH_WEAPON_B, "weapons/hagar_load.wav", VOL_BASE * 0.8, ATTN_NORM); // sound is too loud according to most + + if (self.hagar_load >= autocvar_g_balance_hagar_secondary_load_max) + self.hagar_loadstep = time + autocvar_g_balance_hagar_secondary_load_hold * W_WeaponRateFactor(); + else + self.hagar_loadstep = time + autocvar_g_balance_hagar_secondary_load_speed * W_WeaponRateFactor(); + } + } + else if(!self.hagar_loadbeep && self.hagar_load) // prevents the beep from playing each frame + { + // if this is the last rocket we can load, play a beep sound to notify the player + sound(self, CH_WEAPON_A, "weapons/hagar_beep.wav", VOL_BASE, ATTN_NORM); + self.hagar_loadbeep = TRUE; + } + } + } + else if(self.hagar_loadblock) + { + // the alt fire button has been released, so re-enable loading if blocked + self.hagar_loadblock = FALSE; + } + + if(self.hagar_load) + { + // play warning sound if we're about to release + if((loaded || !enough_ammo) && self.hagar_loadstep - 0.5 < time && autocvar_g_balance_hagar_secondary_load_hold >= 0) + { + if(!self.hagar_warning && self.hagar_load) // prevents the beep from playing each frame + { + // we're about to automatically release after holding time, play a beep sound to notify the player + sound(self, CH_WEAPON_A, "weapons/hagar_beep.wav", VOL_BASE, ATTN_NORM); + self.hagar_warning = TRUE; + } + } + + // release if player let go of button or if they've held it in too long + if(!self.BUTTON_ATCK2 || ((loaded || !enough_ammo) && self.hagar_loadstep < time && autocvar_g_balance_hagar_secondary_load_hold >= 0)) + { + self.weaponentity.state = WS_READY; + W_Hagar_Attack2_Load_Release(); + } + } + else + { + self.hagar_loadbeep = FALSE; + self.hagar_warning = FALSE; + } + + // we aren't checking ammo during an attack, so we must do it here + if not(weapon_action(self.weapon, WR_CHECKAMMO1) + weapon_action(self.weapon, WR_CHECKAMMO2)) + { + // note: this doesn't force the switch + W_SwitchToOtherWeapon(self); + return; + } +} + void spawnfunc_weapon_hagar (void) { weapon_defaultspawnfunc(WEP_HAGAR); @@ -118,6 +338,7 @@ void spawnfunc_weapon_hagar (void) float w_hagar(float req) { + float ammo_amount; if (req == WR_AIM) if (random()>0.15) self.BUTTON_ATCK = bot_aim(autocvar_g_balance_hagar_primary_speed, 0, autocvar_g_balance_hagar_primary_lifetime, FALSE); @@ -128,17 +349,37 @@ float w_hagar(float req) } else if (req == WR_THINK) { - if (self.BUTTON_ATCK) - if (weapon_prepareattack(0, autocvar_g_balance_hagar_primary_refire)) + float loadable_secondary; + loadable_secondary = autocvar_g_balance_hagar_secondary_load && autocvar_g_balance_hagar_secondary; + + if (loadable_secondary) + W_Hagar_Attack2_Load(); // must always run each frame + if(autocvar_g_balance_hagar_reload_ammo && self.clip_load < min(autocvar_g_balance_hagar_primary_ammo, autocvar_g_balance_hagar_secondary_ammo)) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else if (self.BUTTON_ATCK && !self.hagar_load && !self.hagar_loadblock) // not while secondary is loaded or awaiting reset { - W_Hagar_Attack(); - weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hagar_primary_refire, w_ready); + if (weapon_prepareattack(0, autocvar_g_balance_hagar_primary_refire)) + { + W_Hagar_Attack(); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hagar_primary_refire, w_ready); + } } - if (self.BUTTON_ATCK2 && autocvar_g_balance_hagar_secondary) - if (weapon_prepareattack(1, autocvar_g_balance_hagar_secondary_refire)) + else if (self.BUTTON_ATCK2 && !loadable_secondary && autocvar_g_balance_hagar_secondary) { - W_Hagar_Attack2(); - weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_hagar_secondary_refire, w_ready); + if (weapon_prepareattack(1, autocvar_g_balance_hagar_secondary_refire)) + { + W_Hagar_Attack2(); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_hagar_secondary_refire, w_ready); + } + } + } + else if (req == WR_GONETHINK) + { + // we lost the weapon and want to prepare switching away + if(self.hagar_load) + { + self.weaponentity.state = WS_READY; + W_Hagar_Attack2_Load_Release(); } } else if (req == WR_PRECACHE) @@ -147,15 +388,51 @@ float w_hagar(float req) precache_model ("models/weapons/v_hagar.md3"); precache_model ("models/weapons/h_hagar.iqm"); precache_sound ("weapons/hagar_fire.wav"); + precache_sound ("weapons/hagar_load.wav"); + precache_sound ("weapons/hagar_beep.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else } else if (req == WR_SETUP) + { weapon_setup(WEP_HAGAR); + self.current_ammo = ammo_rockets; + self.hagar_loadblock = FALSE; + + if(self.hagar_load) + { + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_hagar_secondary_ammo * self.hagar_load * -1, autocvar_g_balance_hagar_reload_ammo); // give back ammo if necessary + self.hagar_load = 0; + } + } else if (req == WR_CHECKAMMO1) - return self.ammo_rockets >= autocvar_g_balance_hagar_primary_ammo; + { + ammo_amount = self.ammo_rockets >= autocvar_g_balance_hagar_primary_ammo; + ammo_amount += self.(weapon_load[WEP_HAGAR]) >= autocvar_g_balance_hagar_primary_ammo; + return ammo_amount; + } else if (req == WR_CHECKAMMO2) - return self.ammo_rockets >= autocvar_g_balance_hagar_secondary_ammo; + { + ammo_amount = self.ammo_rockets >= autocvar_g_balance_hagar_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_HAGAR]) >= autocvar_g_balance_hagar_secondary_ammo; + return ammo_amount; + } + else if (req == WR_RESETPLAYER) + { + self.hagar_load = 0; + } + else if (req == WR_PLAYERDEATH) + { + // if we have any rockets loaded when we die, release them + if(self.hagar_load && autocvar_g_balance_hagar_secondary_load_releasedeath) + W_Hagar_Attack2_Load_Release(); + } + else if (req == WR_RELOAD) + { + if not(self.hagar_load) // require releasing loaded rockets first + W_Reload(min(autocvar_g_balance_hagar_primary_ammo, autocvar_g_balance_hagar_secondary_ammo), autocvar_g_balance_hagar_reload_ammo, autocvar_g_balance_hagar_reload_time, "weapons/reload.wav"); + } return TRUE; -}; +} #endif #ifdef CSQC float w_hagar(float req) @@ -168,11 +445,11 @@ float w_hagar(float req) if(!w_issilent) { if (w_random<0.15) - sound(self, CHAN_PROJECTILE, "weapons/hagexp1.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/hagexp1.wav", VOL_BASE, ATTN_NORM); else if (w_random<0.7) - sound(self, CHAN_PROJECTILE, "weapons/hagexp2.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/hagexp2.wav", VOL_BASE, ATTN_NORM); else - sound(self, CHAN_PROJECTILE, "weapons/hagexp3.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/hagexp3.wav", VOL_BASE, ATTN_NORM); } } else if(req == WR_PRECACHE) @@ -182,13 +459,13 @@ float w_hagar(float req) precache_sound("weapons/hagexp3.wav"); } else if (req == WR_SUICIDEMESSAGE) - w_deathtypestring = "%s played with tiny rockets"; + w_deathtypestring = _("%s played with tiny hagar rockets"); else if (req == WR_KILLMESSAGE) { if(w_deathtype & HITTYPE_BOUNCE) // must be secondary; unchecked: SPLASH - w_deathtypestring = "%s hoped %s's missiles wouldn't bounce"; + w_deathtypestring = _("%s was pummeled with a burst of hagar rockets by %s"); else // unchecked: SPLASH, SECONDARY - w_deathtypestring = "%s was pummeled by %s"; + w_deathtypestring = _("%s was pummeled with hagar rockets by %s"); } return TRUE; } diff --git a/qcsrc/server/w_hlac.qc b/qcsrc/server/w_hlac.qc index e3d3cb9918..2eb2918ed6 100644 --- a/qcsrc/server/w_hlac.qc +++ b/qcsrc/server/w_hlac.qc @@ -1,46 +1,35 @@ #ifdef REGISTER_WEAPON -REGISTER_WEAPON(HLAC, w_hlac, IT_CELLS, 6, WEP_FLAG_NORMAL | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_MID, "hlac", "hlac", "Heavy Laser Assault Cannon"); +REGISTER_WEAPON(HLAC, w_hlac, IT_CELLS, 6, WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_MID, "hlac", "hlac", _("Heavy Laser Assault Cannon")) #else #ifdef SVQC -.float HLAC_bulletcounter; -void W_HLAC_Touch (void) -{ - PROJECTILE_TOUCH; - - self.event_damage = SUB_Null; - - RadiusDamage (self, self.owner, autocvar_g_balance_hlac_primary_damage, autocvar_g_balance_hlac_primary_edgedamage, autocvar_g_balance_hlac_primary_radius, world, autocvar_g_balance_hlac_primary_force, self.projectiledeathtype, other); - remove (self); -} - -void W_HLAC_Touch2 (void) +void W_HLAC_Touch (void) { PROJECTILE_TOUCH; self.event_damage = SUB_Null; - - RadiusDamage (self, self.owner, autocvar_g_balance_hlac_secondary_damage, autocvar_g_balance_hlac_secondary_edgedamage, autocvar_g_balance_hlac_secondary_radius, world, autocvar_g_balance_hlac_secondary_force, self.projectiledeathtype, other); + + if(self.projectiledeathtype & HITTYPE_SECONDARY) + RadiusDamage (self, self.realowner, autocvar_g_balance_hlac_secondary_damage, autocvar_g_balance_hlac_secondary_edgedamage, autocvar_g_balance_hlac_secondary_radius, world, autocvar_g_balance_hlac_secondary_force, self.projectiledeathtype, other); + else + RadiusDamage (self, self.realowner, autocvar_g_balance_hlac_primary_damage, autocvar_g_balance_hlac_primary_edgedamage, autocvar_g_balance_hlac_primary_radius, world, autocvar_g_balance_hlac_primary_force, self.projectiledeathtype, other); remove (self); } void W_HLAC_Attack (void) { - local entity missile; + entity missile; float spread; - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - { - self.ammo_cells = self.ammo_cells - autocvar_g_balance_hlac_primary_ammo; - } + W_DecreaseAmmo(ammo_cells, autocvar_g_balance_hlac_primary_ammo, autocvar_g_balance_hlac_reload_ammo); - spread = autocvar_g_balance_hlac_primary_spread_min + (autocvar_g_balance_hlac_primary_spread_add * self.HLAC_bulletcounter); + spread = autocvar_g_balance_hlac_primary_spread_min + (autocvar_g_balance_hlac_primary_spread_add * self.misc_bulletcounter); spread = min(spread,autocvar_g_balance_hlac_primary_spread_max); if(self.crouch) spread = spread * autocvar_g_balance_hlac_primary_spread_crouchmod; - W_SetupShot (self, FALSE, 3, "weapons/lasergun_fire.wav", CHAN_WEAPON, autocvar_g_balance_hlac_primary_damage); + W_SetupShot (self, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_A, autocvar_g_balance_hlac_primary_damage); pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); if (!g_norecoil) { @@ -49,9 +38,8 @@ void W_HLAC_Attack (void) } missile = spawn (); - missile.owner = self; + missile.owner = missile.realowner = self; missile.classname = "hlacbolt"; - // missile.dmg = issecondary; missile.bot_dodge = TRUE; missile.bot_dodgerating = autocvar_g_balance_hlac_primary_damage; @@ -63,7 +51,7 @@ void W_HLAC_Attack (void) setsize(missile, '0 0 0', '0 0 0'); W_SetupProjectileVelocity(missile, autocvar_g_balance_hlac_primary_speed, spread); - missile.angles = vectoangles (missile.velocity); + //missile.angles = vectoangles (missile.velocity); // csqc missile.touch = W_HLAC_Touch; missile.think = SUB_Remove; @@ -80,7 +68,7 @@ void W_HLAC_Attack (void) void W_HLAC_Attack2f (void) { - local entity missile; + entity missile; float spread; spread = autocvar_g_balance_hlac_secondary_spread; @@ -89,13 +77,12 @@ void W_HLAC_Attack2f (void) if(self.crouch) spread = spread * autocvar_g_balance_hlac_secondary_spread_crouchmod; - W_SetupShot (self, FALSE, 3, "weapons/lasergun_fire.wav", CHAN_WEAPON, autocvar_g_balance_hlac_secondary_damage); + W_SetupShot (self, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_A, autocvar_g_balance_hlac_secondary_damage); pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); missile = spawn (); - missile.owner = self; + missile.owner = missile.realowner = self; missile.classname = "hlacbolt"; - // missile.dmg = issecondary; missile.bot_dodge = TRUE; missile.bot_dodgerating = autocvar_g_balance_hlac_secondary_damage; @@ -107,9 +94,9 @@ void W_HLAC_Attack2f (void) setsize(missile, '0 0 0', '0 0 0'); W_SetupProjectileVelocity(missile, autocvar_g_balance_hlac_secondary_speed, spread); - missile.angles = vectoangles (missile.velocity); + //missile.angles = vectoangles (missile.velocity); // csqc - missile.touch = W_HLAC_Touch2; + missile.touch = W_HLAC_Touch; missile.think = SUB_Remove; missile.nextthink = time + autocvar_g_balance_hlac_secondary_lifetime; @@ -126,10 +113,7 @@ void W_HLAC_Attack2 (void) { float i; - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - { - self.ammo_cells = self.ammo_cells - autocvar_g_balance_hlac_secondary_ammo; - } + W_DecreaseAmmo(ammo_cells, autocvar_g_balance_hlac_secondary_ammo, autocvar_g_balance_hlac_reload_ammo); for(i=autocvar_g_balance_hlac_secondary_shots;i>0;--i) W_HLAC_Attack2f(); @@ -153,6 +137,7 @@ void HLAC_fire1_02() if (self.BUTTON_ATCK) { if (!weapon_action(self.weapon, WR_CHECKAMMO1)) + if not(self.items & IT_UNLIMITED_WEAPON_AMMO) { W_SwitchWeapon_Force(self, w_getbestweapon(self)); w_ready(); @@ -161,14 +146,14 @@ void HLAC_fire1_02() ATTACK_FINISHED(self) = time + autocvar_g_balance_hlac_primary_refire * W_WeaponRateFactor(); W_HLAC_Attack(); - self.HLAC_bulletcounter = self.HLAC_bulletcounter + 1; + self.misc_bulletcounter = self.misc_bulletcounter + 1; weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hlac_primary_refire, HLAC_fire1_02); } else { weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hlac_primary_animtime, w_ready); } -}; +} void spawnfunc_weapon_hlac (void) { @@ -177,25 +162,31 @@ void spawnfunc_weapon_hlac (void) float w_hlac(float req) { + float ammo_amount; if (req == WR_AIM) self.BUTTON_ATCK = bot_aim(autocvar_g_balance_hlac_primary_speed, 0, autocvar_g_balance_hlac_primary_lifetime, FALSE); else if (req == WR_THINK) { - if (self.BUTTON_ATCK) - if (weapon_prepareattack(0, autocvar_g_balance_hlac_primary_refire)) + if(autocvar_g_balance_hlac_reload_ammo && self.clip_load < min(autocvar_g_balance_hlac_primary_ammo, autocvar_g_balance_hlac_secondary_ammo)) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else if (self.BUTTON_ATCK) { - self.HLAC_bulletcounter = 0; - W_HLAC_Attack(); - weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hlac_primary_refire, HLAC_fire1_02); + if (weapon_prepareattack(0, autocvar_g_balance_hlac_primary_refire)) + { + self.misc_bulletcounter = 0; + W_HLAC_Attack(); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hlac_primary_refire, HLAC_fire1_02); + } } - if (self.BUTTON_ATCK2 && autocvar_g_balance_hlac_secondary) - if (weapon_prepareattack(1, autocvar_g_balance_hlac_secondary_refire)) + else if (self.BUTTON_ATCK2 && autocvar_g_balance_hlac_secondary) { - W_HLAC_Attack2(); - weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_hlac_secondary_animtime, w_ready); + if (weapon_prepareattack(1, autocvar_g_balance_hlac_secondary_refire)) + { + W_HLAC_Attack2(); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_hlac_secondary_animtime, w_ready); + } } - } else if (req == WR_PRECACHE) { @@ -203,16 +194,32 @@ float w_hlac(float req) precache_model ("models/weapons/v_hlac.md3"); precache_model ("models/weapons/h_hlac.iqm"); precache_sound ("weapons/lasergun_fire.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else } else if (req == WR_SETUP) + { weapon_setup(WEP_HLAC); + self.current_ammo = ammo_cells; + } else if (req == WR_CHECKAMMO1) - return self.ammo_cells >= autocvar_g_balance_hlac_primary_ammo; + { + ammo_amount = self.ammo_cells >= autocvar_g_balance_hlac_primary_ammo; + ammo_amount += self.(weapon_load[WEP_HLAC]) >= autocvar_g_balance_hlac_primary_ammo; + return ammo_amount; + } else if (req == WR_CHECKAMMO2) - return self.ammo_cells >= autocvar_g_balance_hlac_secondary_ammo; + { + ammo_amount = self.ammo_cells >= autocvar_g_balance_hlac_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_HLAC]) >= autocvar_g_balance_hlac_secondary_ammo; + return ammo_amount; + } + else if (req == WR_RELOAD) + { + W_Reload(min(autocvar_g_balance_hlac_primary_ammo, autocvar_g_balance_hlac_secondary_ammo), autocvar_g_balance_hlac_reload_ammo, autocvar_g_balance_hlac_reload_time, "weapons/reload.wav"); + } return TRUE; -}; +} #endif #ifdef CSQC float w_hlac(float req) @@ -223,16 +230,16 @@ float w_hlac(float req) org2 = w_org + w_backoff * 6; pointparticles(particleeffectnum("laser_impact"), org2, w_backoff * 1000, 1); if(!w_issilent) - sound(self, CHAN_PROJECTILE, "weapons/laserimpact.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_NORM); } else if(req == WR_PRECACHE) { precache_sound("weapons/laserimpact.wav"); } else if (req == WR_SUICIDEMESSAGE) - w_deathtypestring = "%s should have used a smaller gun"; + w_deathtypestring = _("%s should have used a smaller gun"); else if (req == WR_KILLMESSAGE) - w_deathtypestring = "%s was cut down by %s"; + w_deathtypestring = _("%s was cut down with a HLAC by %s"); return TRUE; } #endif diff --git a/qcsrc/server/w_hook.qc b/qcsrc/server/w_hook.qc index e191077b31..695ac381fe 100644 --- a/qcsrc/server/w_hook.qc +++ b/qcsrc/server/w_hook.qc @@ -1,5 +1,5 @@ #ifdef REGISTER_WEAPON -REGISTER_WEAPON(HOOK, w_hook, IT_CELLS|IT_FUEL, 0, WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, 0, "hookgun", "hook", "Grappling Hook"); +REGISTER_WEAPON(HOOK, w_hook, IT_CELLS|IT_FUEL, 0, WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, 0, "hookgun", "hook", _("Grappling Hook")) #else #ifdef SVQC .float dmg; @@ -23,7 +23,7 @@ void W_Hook_ExplodeThink (void) f = self.dmg_last - dmg_remaining_next; self.dmg_last = dmg_remaining_next; - RadiusDamage (self, self.owner, self.dmg * f, self.dmg_edge * f, self.dmg_radius, self.owner, self.dmg_force * f, self.projectiledeathtype, world); + RadiusDamage (self, self.realowner, self.dmg * f, self.dmg_edge * f, self.dmg_radius, self.realowner, self.dmg_force * f, self.projectiledeathtype, world); self.projectiledeathtype |= HITTYPE_BOUNCE; //RadiusDamage (self, world, self.dmg * f, self.dmg_edge * f, self.dmg_radius, world, self.dmg_force * f, self.projectiledeathtype, world); @@ -52,6 +52,20 @@ void W_Hook_Explode2 (void) self.movetype = MOVETYPE_NONE; } +void W_Hook_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) +{ + if (self.health <= 0) + return; + + if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions + return; // g_projectiles_damage says to halt + + self.health = self.health - damage; + + if (self.health <= 0) + W_PrepareExplosionByDamage(self.realowner, W_Hook_Explode2); +} + void W_Hook_Touch2 (void) { PROJECTILE_TOUCH; @@ -60,14 +74,13 @@ void W_Hook_Touch2 (void) void W_Hook_Attack2() { - local entity gren; + entity gren; - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_cells = self.ammo_cells - autocvar_g_balance_hook_secondary_ammo; - W_SetupShot (self, FALSE, 4, "weapons/hookbomb_fire.wav", CHAN_WEAPON, autocvar_g_balance_hook_secondary_damage); + W_DecreaseAmmo(ammo_cells, autocvar_g_balance_hook_secondary_ammo, FALSE); + W_SetupShot (self, FALSE, 4, "weapons/hookbomb_fire.wav", CH_WEAPON_A, autocvar_g_balance_hook_secondary_damage); gren = spawn (); - gren.owner = self; + gren.owner = gren.realowner = self; gren.classname = "hookbomb"; gren.bot_dodge = TRUE; gren.bot_dodgerating = autocvar_g_balance_hook_secondary_damage; @@ -81,6 +94,12 @@ void W_Hook_Attack2() gren.think = adaptor_think2use_hittype_splash; gren.use = W_Hook_Explode2; gren.touch = W_Hook_Touch2; + + gren.takedamage = DAMAGE_YES; + gren.health = autocvar_g_balance_hook_secondary_health; + gren.damageforcescale = autocvar_g_balance_hook_secondary_damageforcescale; + gren.event_damage = W_Hook_Damage; + gren.damagedbycontents = TRUE; gren.velocity = '0 0 1' * autocvar_g_balance_hook_secondary_speed; if(autocvar_g_projectiles_newton_style) @@ -126,8 +145,7 @@ float w_hook(float req) if (time > self.hook_refire) if (weapon_prepareattack(0, -1)) { - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_fuel = self.ammo_fuel - autocvar_g_balance_hook_primary_fuel; + W_DecreaseAmmo(ammo_fuel, autocvar_g_balance_hook_primary_fuel, FALSE); self.hook_state |= HOOK_FIRING; weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hook_primary_animtime, w_ready); } @@ -145,7 +163,7 @@ float w_hook(float req) if(self.hook) { // if hooked, no bombs, and increase the timer - self.hook_refire = max(self.hook_refire, time + autocvar_g_balance_hook_primary_refire); + self.hook_refire = max(self.hook_refire, time + autocvar_g_balance_hook_primary_refire * W_WeaponRateFactor()); // hook also inhibits health regeneration, but only for 1 second if not(self.items & IT_UNLIMITED_WEAPON_AMMO) @@ -170,7 +188,7 @@ float w_hook(float req) { if ( self.ammo_fuel >= (time - self.hook_time_fueldecrease) * hooked_fuel ) { - self.ammo_fuel -= (time - self.hook_time_fueldecrease) * hooked_fuel; + W_DecreaseAmmo(ammo_fuel, (time - self.hook_time_fueldecrease) * hooked_fuel, FALSE); self.hook_time_fueldecrease = time; // decrease next frame again } @@ -228,6 +246,7 @@ float w_hook(float req) else if (req == WR_SETUP) { weapon_setup(WEP_HOOK); + self.current_ammo = ammo_fuel; self.hook_state &~= HOOK_WAITING_FOR_RELEASE; } else if (req == WR_CHECKAMMO1) @@ -246,7 +265,7 @@ float w_hook(float req) self.hook_refire = time; } return TRUE; -}; +} #endif #ifdef CSQC float w_hook(float req) @@ -257,16 +276,16 @@ float w_hook(float req) org2 = w_org + w_backoff * 2; pointparticles(particleeffectnum("hookbomb_explode"), org2, '0 0 0', 1); if(!w_issilent) - sound(self, CHAN_PROJECTILE, "weapons/hookbomb_impact.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/hookbomb_impact.wav", VOL_BASE, ATTN_NORM); } else if(req == WR_PRECACHE) { precache_sound("weapons/hookbomb_impact.wav"); } else if (req == WR_SUICIDEMESSAGE) - w_deathtypestring = "%s did the impossible"; + w_deathtypestring = _("%s did the impossible"); else if (req == WR_KILLMESSAGE) - w_deathtypestring = "%s has run into %s's gravity bomb"; + w_deathtypestring = _("%s was caught in %s's hook gravity bomb"); return TRUE; } #endif diff --git a/qcsrc/server/w_laser.qc b/qcsrc/server/w_laser.qc index 5f680eb081..3da9e422b5 100644 --- a/qcsrc/server/w_laser.qc +++ b/qcsrc/server/w_laser.qc @@ -1,8 +1,9 @@ #ifdef REGISTER_WEAPON -REGISTER_WEAPON(LASER, w_laser, 0, 1, WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, 0, "laser", "laser", "Laser"); +REGISTER_WEAPON(LASER, w_laser, 0, 1, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, 0, "laser", "laser", _("Laser")) #else #ifdef SVQC void(float imp) W_SwitchWeapon; +void() W_LastWeapon; void W_Laser_Touch (void) { @@ -10,9 +11,9 @@ void W_Laser_Touch (void) self.event_damage = SUB_Null; if (self.dmg) - RadiusDamage (self, self.owner, autocvar_g_balance_laser_secondary_damage, autocvar_g_balance_laser_secondary_edgedamage, autocvar_g_balance_laser_secondary_radius, world, autocvar_g_balance_laser_secondary_force, self.projectiledeathtype, other); + RadiusDamage (self, self.realowner, autocvar_g_balance_laser_secondary_damage, autocvar_g_balance_laser_secondary_edgedamage, autocvar_g_balance_laser_secondary_radius, world, autocvar_g_balance_laser_secondary_force, self.projectiledeathtype, other); else - RadiusDamage (self, self.owner, autocvar_g_balance_laser_primary_damage, autocvar_g_balance_laser_primary_edgedamage, autocvar_g_balance_laser_primary_radius, world, autocvar_g_balance_laser_primary_force, self.projectiledeathtype, other); + RadiusDamage (self, self.realowner, autocvar_g_balance_laser_primary_damage, autocvar_g_balance_laser_primary_edgedamage, autocvar_g_balance_laser_primary_radius, world, autocvar_g_balance_laser_primary_force, self.projectiledeathtype, other); remove (self); } @@ -30,7 +31,7 @@ void W_Laser_Think() void W_Laser_Attack (float issecondary) { - local entity missile; + entity missile; vector s_forward; float a; float nodamage; @@ -44,15 +45,15 @@ void W_Laser_Attack (float issecondary) s_forward = v_forward * cos(a * DEG2RAD) + v_up * sin(a * DEG2RAD); if(nodamage) - W_SetupShot_Dir (self, s_forward, FALSE, 3, "weapons/lasergun_fire.wav", CHAN_WEAPON2, 0); + W_SetupShot_Dir (self, s_forward, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_B, 0); else if(issecondary == 1) - W_SetupShot_Dir (self, s_forward, FALSE, 3, "weapons/lasergun_fire.wav", CHAN_WEAPON2, autocvar_g_balance_laser_secondary_damage); + W_SetupShot_Dir (self, s_forward, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_B, autocvar_g_balance_laser_secondary_damage); else - W_SetupShot_Dir (self, s_forward, FALSE, 3, "weapons/lasergun_fire.wav", CHAN_WEAPON2, autocvar_g_balance_laser_primary_damage); + W_SetupShot_Dir (self, s_forward, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_B, autocvar_g_balance_laser_primary_damage); pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); missile = spawn (); - missile.owner = self; + missile.owner = missile.realowner = self; missile.classname = "laserbolt"; missile.dmg = 0; if(!nodamage) @@ -95,12 +96,12 @@ float gauntletbeam_send(entity to, float sf) { WriteByte(MSG_ENTITY, ENT_CLIENT_GAUNTLET); sf = sf & 0x7F; - if(sound_allowed(MSG_BROADCAST, self.owner)) + if(sound_allowed(MSG_BROADCAST, self.realowner)) sf |= 0x80; WriteByte(MSG_ENTITY, sf); if(sf & 1) { - WriteByte(MSG_ENTITY, num_for_edict(self.owner)); + WriteByte(MSG_ENTITY, num_for_edict(self.realowner)); } if(sf & 2) { @@ -118,6 +119,7 @@ float gauntletbeam_send(entity to, float sf) } .entity gauntletbeam; .float prevgauntletfire; +entity lgbeam_owner_ent; void gauntletbeam_think() { float damage, myforce, myradius; @@ -125,8 +127,8 @@ void gauntletbeam_think() myforce = autocvar_g_balance_laser_secondary_force; myradius = autocvar_g_balance_laser_secondary_radius; - self.owner.prevgauntletfire = time; - if (self.owner.weaponentity.state != WS_INUSE || self != self.owner.gauntletbeam || self.owner.deadflag != DEAD_NO || !self.owner.BUTTON_ATCK2) + self.realowner.prevgauntletfire = time; + if (self.realowner.weaponentity.state != WS_INUSE || self != self.realowner.gauntletbeam || self.realowner.deadflag != DEAD_NO || !self.realowner.BUTTON_ATCK2) { remove(self); return; @@ -134,13 +136,18 @@ void gauntletbeam_think() self.nextthink = time; - makevectors(self.owner.v_angle); + makevectors(self.realowner.v_angle); float dt; dt = frametime; - W_SetupShot_Range(self.owner, TRUE, 0, "", 0, damage * dt, myradius); - WarpZone_traceline_antilag(self.owner, w_shotorg, w_shotend, MOVE_NORMAL, self.owner, ANTILAG_LATENCY(self.owner)); + W_SetupShot_Range(self.realowner, TRUE, 0, "", 0, damage * dt, myradius); + if(!lgbeam_owner_ent) + { + lgbeam_owner_ent = spawn(); + lgbeam_owner_ent.classname = "lgbeam_owner_ent"; + } + WarpZone_traceline_antilag(lgbeam_owner_ent, w_shotorg, w_shotend, MOVE_NORMAL, lgbeam_owner_ent, ANTILAG_LATENCY(self.owner)); // apply the damage if(trace_ent) @@ -171,7 +178,7 @@ void W_Laser_Attack2 () // only play fire sound if 0.5 sec has passed since player let go the fire button if(time - self.prevgauntletfire > 0.5) { - sound (self, CHAN_WEAPON, "weapons/gauntlet_fire.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_WEAPON_A, "weapons/gauntlet_fire.wav", VOL_BASE, ATTN_NORM); } entity beam, oldself; @@ -208,8 +215,8 @@ void spawnfunc_weapon_laser (void) float w_laser(float req) { - local float r1; - local float r2; + float r1; + float r2; if (req == WR_AIM) { if(autocvar_g_balance_laser_secondary) @@ -226,16 +233,24 @@ float w_laser(float req) } else if (req == WR_THINK) { - if (self.BUTTON_ATCK) - if (weapon_prepareattack(0, autocvar_g_balance_laser_primary_refire)) + if(autocvar_g_balance_laser_reload_ammo && self.clip_load < 1) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else if (self.BUTTON_ATCK) { - W_Laser_Attack(0); - weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_laser_primary_animtime, w_ready); + if (weapon_prepareattack(0, autocvar_g_balance_laser_primary_refire)) + { + W_DecreaseAmmo(ammo_none, 1, TRUE); + + W_Laser_Attack(0); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_laser_primary_animtime, w_ready); + } } - if (self.BUTTON_ATCK2) + else if (self.BUTTON_ATCK2) { if(autocvar_g_balance_laser_secondary) { + W_DecreaseAmmo(ammo_none, 1, TRUE); + if (weapon_prepareattack(0, 0)) { W_Laser_Attack2(); @@ -245,7 +260,7 @@ float w_laser(float req) else { if(self.switchweapon == WEP_LASER) // don't do this if already switching - W_SwitchWeapon (self.cnt); + W_LastWeapon(); } } } @@ -256,15 +271,27 @@ float w_laser(float req) precache_model ("models/weapons/h_laser.iqm"); precache_sound ("weapons/lasergun_fire.wav"); precache_sound ("weapons/gauntlet_fire.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else } else if (req == WR_SETUP) + { weapon_setup(WEP_LASER); + self.current_ammo = ammo_none; + } else if (req == WR_CHECKAMMO1) + { return TRUE; + } else if (req == WR_CHECKAMMO2) + { return TRUE; + } + else if (req == WR_RELOAD) + { + W_Reload(0, autocvar_g_balance_laser_reload_ammo, autocvar_g_balance_laser_reload_time, "weapons/reload.wav"); + } return TRUE; -}; +} #endif #ifdef CSQC float w_laser(float req) @@ -275,20 +302,20 @@ float w_laser(float req) org2 = w_org + w_backoff * 6; pointparticles(particleeffectnum("laser_impact"), org2, w_backoff * 1000, 1); if(!w_issilent) - sound(self, CHAN_PROJECTILE, "weapons/laserimpact.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_NORM); } else if(req == WR_PRECACHE) { precache_sound("weapons/laserimpact.wav"); } else if (req == WR_SUICIDEMESSAGE) - w_deathtypestring = "%s lasered themself to hell"; + w_deathtypestring = _("%s lasered themself to hell"); else if (req == WR_KILLMESSAGE) { if(w_deathtype & HITTYPE_SECONDARY) - w_deathtypestring = "%s was cut in half by %s's gauntlet"; // unchecked: SPLASH + w_deathtypestring = _("%s was cut in half by %s's gauntlet"); // unchecked: SPLASH else - w_deathtypestring = "%s was lasered to death by %s"; // unchecked: SPLASH + w_deathtypestring = _("%s was lasered to death by %s"); // unchecked: SPLASH } return TRUE; } diff --git a/qcsrc/server/w_minelayer.qc b/qcsrc/server/w_minelayer.qc index 42c8ec3ece..3ec50da50d 100644 --- a/qcsrc/server/w_minelayer.qc +++ b/qcsrc/server/w_minelayer.qc @@ -1,9 +1,9 @@ #ifdef REGISTER_WEAPON -REGISTER_WEAPON(MINE_LAYER, w_minelayer, IT_ROCKETS, 4, WEP_FLAG_NORMAL | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_HIGH, "minelayer", "minelayer", "Mine Layer"); +REGISTER_WEAPON(MINE_LAYER, w_minelayer, IT_ROCKETS, 4, WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_HIGH, "minelayer", "minelayer", _("Mine Layer")) #else #ifdef SVQC void W_Mine_Think (void); -.float minelayer_detonate, minelayer_mines; +.float minelayer_detonate, mine_explodeanyway; .float mine_time; void spawnfunc_weapon_minelayer (void) @@ -11,9 +11,9 @@ void spawnfunc_weapon_minelayer (void) weapon_defaultspawnfunc(WEP_MINE_LAYER); } -void W_Mine_Stick () +void W_Mine_Stick (entity to) { - spamsound (self, CHAN_PROJECTILE, "weapons/mine_stick.wav", VOL_BASE, ATTN_NORM); + spamsound (self, CH_SHOTS, "weapons/mine_stick.wav", VOL_BASE, ATTN_NORM); // in order for mines to face properly when sticking to the ground, they must be a server side entity rather than a csqc projectile @@ -25,16 +25,20 @@ void W_Mine_Stick () newmine.bot_dodgerating = self.bot_dodgerating; newmine.owner = self.owner; + newmine.realowner = self.realowner; setsize(newmine, '-4 -4 -4', '4 4 4'); setorigin(newmine, self.origin); setmodel(newmine, "models/mine.md3"); newmine.angles = vectoangles(-trace_plane_normal); // face against the surface + newmine.oldvelocity = self.velocity; + newmine.takedamage = self.takedamage; newmine.damageforcescale = self.damageforcescale; newmine.health = self.health; newmine.event_damage = self.event_damage; newmine.spawnshieldtime = self.spawnshieldtime; + newmine.damagedbycontents = TRUE; newmine.movetype = MOVETYPE_NONE; // lock the mine in place newmine.projectiledeathtype = self.projectiledeathtype; @@ -49,30 +53,39 @@ void W_Mine_Stick () remove(self); self = newmine; + + if(to) + SetMovetypeFollow(self, to); } void W_Mine_Explode () { if(other.takedamage == DAMAGE_AIM) if(other.classname == "player") - if(IsDifferentTeam(self.owner, other)) - if(IsFlying(other)) - AnnounceTo(self.owner, "airshot"); + if(IsDifferentTeam(self.realowner, other)) + if(other.deadflag == DEAD_NO) + if(IsFlying(other)) + AnnounceTo(self.realowner, "airshot"); self.event_damage = SUB_Null; self.takedamage = DAMAGE_NO; - RadiusDamage (self, self.owner, autocvar_g_balance_minelayer_damage, autocvar_g_balance_minelayer_edgedamage, autocvar_g_balance_minelayer_radius, world, autocvar_g_balance_minelayer_force, self.projectiledeathtype, other); + RadiusDamage (self, self.realowner, autocvar_g_balance_minelayer_damage, autocvar_g_balance_minelayer_edgedamage, autocvar_g_balance_minelayer_radius, world, autocvar_g_balance_minelayer_force, self.projectiledeathtype, other); - if (self.owner.weapon == WEP_MINE_LAYER) + if (self.realowner.weapon == WEP_MINE_LAYER) { - if(self.owner.ammo_rockets < autocvar_g_balance_minelayer_ammo) + entity oldself; + oldself = self; + self = self.realowner; + if (!weapon_action(WEP_MINE_LAYER, WR_CHECKAMMO1)) { - self.owner.cnt = WEP_MINE_LAYER; - ATTACK_FINISHED(self.owner) = time; - self.owner.switchweapon = w_getbestweapon(self.owner); + self.cnt = WEP_MINE_LAYER; + ATTACK_FINISHED(self) = time; + self.switchweapon = w_getbestweapon(self); } + self = oldself; } + self.realowner.minelayer_mines -= 1; remove (self); } @@ -81,26 +94,34 @@ void W_Mine_DoRemoteExplode () self.event_damage = SUB_Null; self.takedamage = DAMAGE_NO; - RadiusDamage (self, self.owner, autocvar_g_balance_minelayer_remote_damage, autocvar_g_balance_minelayer_remote_edgedamage, autocvar_g_balance_minelayer_remote_radius, world, autocvar_g_balance_minelayer_remote_force, self.projectiledeathtype | HITTYPE_BOUNCE, world); + if(self.movetype == MOVETYPE_NONE || self.movetype == MOVETYPE_FOLLOW) + self.velocity = self.oldvelocity; - if (self.owner.weapon == WEP_MINE_LAYER) + RadiusDamage (self, self.realowner, autocvar_g_balance_minelayer_remote_damage, autocvar_g_balance_minelayer_remote_edgedamage, autocvar_g_balance_minelayer_remote_radius, world, autocvar_g_balance_minelayer_remote_force, self.projectiledeathtype | HITTYPE_BOUNCE, world); + + if (self.realowner.weapon == WEP_MINE_LAYER) { - if(self.owner.ammo_rockets < autocvar_g_balance_minelayer_ammo) + entity oldself; + oldself = self; + self = self.realowner; + if (!weapon_action(WEP_MINE_LAYER, WR_CHECKAMMO1)) { - self.owner.cnt = WEP_MINE_LAYER; - ATTACK_FINISHED(self.owner) = time; - self.owner.switchweapon = w_getbestweapon(self.owner); + self.cnt = WEP_MINE_LAYER; + ATTACK_FINISHED(self) = time; + self.switchweapon = w_getbestweapon(self); } + self = oldself; } + self.realowner.minelayer_mines -= 1; remove (self); } void W_Mine_RemoteExplode () { - if(self.owner.deadflag == DEAD_NO) + if(self.realowner.deadflag == DEAD_NO) if((self.spawnshieldtime >= 0) ? (time >= self.spawnshieldtime) // timer - : (vlen(NearestPointOnBox(self.owner, self.origin) - self.origin) > autocvar_g_balance_minelayer_remote_radius) // safety device + : (vlen(NearestPointOnBox(self.realowner, self.origin) - self.origin) > autocvar_g_balance_minelayer_remote_radius) // safety device ) { W_Mine_DoRemoteExplode(); @@ -110,13 +131,13 @@ void W_Mine_RemoteExplode () void W_Mine_ProximityExplode () { // make sure no friend is in the mine's radius. If there is any, explosion is delayed until he's at a safe distance - if(autocvar_g_balance_minelayer_protection) + if(autocvar_g_balance_minelayer_protection && self.mine_explodeanyway == 0) { entity head; head = findradius(self.origin, autocvar_g_balance_minelayer_radius); while(head) { - if(head == self.owner || !IsDifferentTeam(head, self.owner)) + if(head == self.realowner || !IsDifferentTeam(head, self.realowner)) return; head = head.chain; } @@ -126,22 +147,44 @@ void W_Mine_ProximityExplode () W_Mine_Explode(); } +float W_Mine_Count(entity e) +{ + float minecount; + entity mine; + for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.realowner == e) + minecount += 1; + + return minecount; +} + void W_Mine_Think (void) { entity head; self.nextthink = time; - if (time > self.cnt) + + if(self.movetype == MOVETYPE_FOLLOW) { - other = world; - self.projectiledeathtype |= HITTYPE_BOUNCE; - W_Mine_Explode(); - return; + if(LostMovetypeFollow(self)) + { + UnsetMovetypeFollow(self); + self.movetype = MOVETYPE_NONE; + } + } + + // our lifetime has expired, it's time to die - mine_time just allows us to play a sound for this + // TODO: replace this mine_trigger.wav sound with a real countdown + if ((time > self.cnt) && (!self.mine_time)) + { + if(autocvar_g_balance_minelayer_lifetime_countdown > 0) + spamsound (self, CH_SHOTS, "weapons/mine_trigger.wav", VOL_BASE, ATTN_NORM); + self.mine_time = time + autocvar_g_balance_minelayer_lifetime_countdown; + self.mine_explodeanyway = 1; // make the mine super aggressive -- Samual: Rather, make it not care if a team mate is near. } // a player's mines shall explode if he disconnects or dies - // TODO: Do this on team change too - if(self.owner.classname != "player" || self.owner.deadflag != DEAD_NO) + // TODO: Do this on team change too -- Samual: But isn't a player killed when they switch teams? + if(self.realowner.classname != "player" || self.realowner.deadflag != DEAD_NO) { other = world; self.projectiledeathtype |= HITTYPE_BOUNCE; @@ -154,10 +197,10 @@ void W_Mine_Think (void) while(head) { if(head.classname == "player" && head.deadflag == DEAD_NO) - if(head != self.owner && IsDifferentTeam(head, self.owner)) // don't trigger for team mates + if(head != self.realowner && IsDifferentTeam(head, self.realowner)) // don't trigger for team mates if(!self.mine_time) { - spamsound (self, CHAN_PROJECTILE, "weapons/mine_trigger.wav", VOL_BASE, ATTN_NORM); + spamsound (self, CH_SHOTS, "weapons/mine_trigger.wav", VOL_BASE, ATTN_NORM); self.mine_time = time + autocvar_g_balance_minelayer_time; } head = head.chain; @@ -165,30 +208,49 @@ void W_Mine_Think (void) // explode if it's time to if(self.mine_time && time >= self.mine_time) + { W_Mine_ProximityExplode(); + return; + } // remote detonation - if (self.owner.weapon == WEP_MINE_LAYER) - if (self.owner.deadflag == DEAD_NO) + if (self.realowner.weapon == WEP_MINE_LAYER) + if (self.realowner.deadflag == DEAD_NO) if (self.minelayer_detonate) W_Mine_RemoteExplode(); } void W_Mine_Touch (void) { + if(self.movetype == MOVETYPE_NONE || self.movetype == MOVETYPE_FOLLOW) + return; // we're already a stuck mine, why do we get called? TODO does this even happen? + PROJECTILE_TOUCH; - if(!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE)) - W_Mine_Stick(); - else if(self.movetype != MOVETYPE_NONE) // don't unstick a locked mine when someone touches it - self.velocity = '0 0 0'; + + if(other && other.classname == "player" && other.deadflag == DEAD_NO) + { + // hit a player + // don't stick + } + else + { + W_Mine_Stick(other); + } } void W_Mine_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) { if (self.health <= 0) return; + + float is_from_enemy = (inflictor.realowner != self.realowner); + + if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, (is_from_enemy ? 1 : -1))) + return; // g_projectiles_damage says to halt + self.health = self.health - damage; self.angles = vectoangles(self.velocity); + if (self.health <= 0) W_PrepareExplosionByDamage(attacker, W_Mine_Explode); } @@ -201,27 +263,23 @@ void W_Mine_Attack (void) // scan how many mines we placed, and return if we reached our limit if(autocvar_g_balance_minelayer_limit) { - self.minelayer_mines = 0; - for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self) - self.minelayer_mines += 1; - - if(self.minelayer_mines >= autocvar_g_balance_minelayer_limit) + + if(W_Mine_Count(self) >= autocvar_g_balance_minelayer_limit) { // the refire delay keeps this message from being spammed - sprint(self, strcat("You cannot place more than ^2", ftos(autocvar_g_balance_minelayer_limit), " ^7mines at a time\n") ); + sprint(self, strcat("minelayer: You cannot place more than ^2", ftos(autocvar_g_balance_minelayer_limit), " ^7mines at a time\n") ); play2(self, "weapons/unavailable.wav"); return; } } - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_rockets = self.ammo_rockets - autocvar_g_balance_minelayer_ammo; + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_minelayer_ammo, autocvar_g_balance_minelayer_reload_ammo); - W_SetupShot_ProjectileSize (self, '-4 -4 -4', '4 4 4', FALSE, 5, "weapons/mine_fire.wav", CHAN_WEAPON, autocvar_g_balance_minelayer_damage); + W_SetupShot_ProjectileSize (self, '-4 -4 -4', '4 4 4', FALSE, 5, "weapons/mine_fire.wav", CH_WEAPON_A, autocvar_g_balance_minelayer_damage); pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); mine = WarpZone_RefSys_SpawnSameRefSys(self); - mine.owner = self; + mine.owner = mine.realowner = self; if(autocvar_g_balance_minelayer_detonatedelay >= 0) mine.spawnshieldtime = time + autocvar_g_balance_minelayer_detonatedelay; else @@ -234,6 +292,7 @@ void W_Mine_Attack (void) mine.damageforcescale = autocvar_g_balance_minelayer_damageforcescale; mine.health = autocvar_g_balance_minelayer_health; mine.event_damage = W_Mine_Damage; + mine.damagedbycontents = TRUE; mine.movetype = MOVETYPE_TOSS; PROJECTILE_MAKETRIGGER(mine); @@ -247,7 +306,7 @@ void W_Mine_Attack (void) mine.touch = W_Mine_Touch; mine.think = W_Mine_Think; mine.nextthink = time; - mine.cnt = time + autocvar_g_balance_minelayer_lifetime; + mine.cnt = time + (autocvar_g_balance_minelayer_lifetime - autocvar_g_balance_minelayer_lifetime_countdown); mine.flags = FL_PROJECTILE; CSQCProjectile(mine, TRUE, PROJECTILE_MINE, TRUE); @@ -262,14 +321,38 @@ void W_Mine_Attack (void) // common properties other = mine; MUTATOR_CALLHOOK(EditProjectile); + + self.minelayer_mines = W_Mine_Count(self); } void spawnfunc_weapon_minelayer (void); // defined in t_items.qc -float w_minelayer(float req) +float W_PlacedMines(float detonate) { entity mine; float minfound; + + for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.realowner == self) + { + if(detonate) + { + if(!mine.minelayer_detonate) + { + mine.minelayer_detonate = TRUE; + minfound = 1; + } + } + else + minfound = 1; + } + return minfound; +} + +float w_minelayer(float req) +{ + entity mine; + float ammo_amount; + if (req == WR_AIM) { // aim and decide to fire if appropriate @@ -291,7 +374,7 @@ float w_minelayer(float req) mine = find(world, classname, "mine"); while (mine) { - if (mine.owner != self) + if (mine.realowner != self) { mine = find(mine, classname, "mine"); continue; @@ -304,7 +387,7 @@ float w_minelayer(float req) // count potential damage according to type of target if (targ == self) selfdamage = selfdamage + d; - else if (targ.team == self.team && teams_matter) + else if (targ.team == self.team && teamplay) teamdamage = teamdamage + d; else if (bot_shouldattack(targ)) enemydamage = enemydamage + d; @@ -316,13 +399,13 @@ float w_minelayer(float req) desirabledamage = enemydamage; if (time > self.invincible_finished && time > self.spawnshieldtime) desirabledamage = desirabledamage - selfdamage * autocvar_g_balance_selfdamagepercent; - if (teams_matter && self.team) + if (teamplay && self.team) desirabledamage = desirabledamage - teamdamage; mine = find(world, classname, "mine"); while (mine) { - if (mine.owner != self) + if (mine.realowner != self) { mine = find(mine, classname, "mine"); continue; @@ -367,7 +450,13 @@ float w_minelayer(float req) } else if (req == WR_THINK) { - if (self.BUTTON_ATCK) + if(autocvar_g_balance_minelayer_reload_ammo && self.clip_load < autocvar_g_balance_minelayer_ammo) // forced reload + { + // not if we're holding the minelayer without enough ammo, but can detonate existing mines + if not (W_PlacedMines(FALSE) && self.ammo_rockets < autocvar_g_balance_minelayer_ammo) + weapon_action(self.weapon, WR_RELOAD); + } + else if (self.BUTTON_ATCK) { if(weapon_prepareattack(0, autocvar_g_balance_minelayer_refire)) { @@ -378,17 +467,8 @@ float w_minelayer(float req) if (self.BUTTON_ATCK2) { - minfound = 0; - for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self) - { - if(!mine.minelayer_detonate) - { - mine.minelayer_detonate = TRUE; - minfound = 1; - } - } - if(minfound) - sound (self, CHAN_WEAPON2, "weapons/mine_det.wav", VOL_BASE, ATTN_NORM); + if(W_PlacedMines(TRUE)) + sound (self, CH_WEAPON_B, "weapons/mine_det.wav", VOL_BASE, ATTN_NORM); } } else if (req == WR_PRECACHE) @@ -402,22 +482,36 @@ float w_minelayer(float req) precache_sound ("weapons/mine_fire.wav"); precache_sound ("weapons/mine_stick.wav"); precache_sound ("weapons/mine_trigger.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else } else if (req == WR_SETUP) { weapon_setup(WEP_MINE_LAYER); + self.current_ammo = ammo_rockets; } else if (req == WR_CHECKAMMO1) { // don't switch while placing a mine - if ((ATTACK_FINISHED(self) <= time || self.weapon != WEP_MINE_LAYER) - && self.ammo_rockets < autocvar_g_balance_minelayer_ammo) - return FALSE; + if (ATTACK_FINISHED(self) <= time || self.weapon != WEP_MINE_LAYER) + { + ammo_amount = self.ammo_rockets >= autocvar_g_balance_minelayer_ammo; + ammo_amount += self.(weapon_load[WEP_MINE_LAYER]) >= autocvar_g_balance_minelayer_ammo; + return ammo_amount; + } } else if (req == WR_CHECKAMMO2) - return FALSE; + { + if (W_PlacedMines(FALSE)) + return TRUE; + else + return FALSE; + } + else if (req == WR_RELOAD) + { + W_Reload(autocvar_g_balance_minelayer_ammo, autocvar_g_balance_minelayer_reload_ammo, autocvar_g_balance_minelayer_reload_time, "weapons/reload.wav"); + } return TRUE; -}; +} #endif #ifdef CSQC float w_minelayer(float req) @@ -428,22 +522,25 @@ float w_minelayer(float req) org2 = w_org + w_backoff * 12; pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1); if(!w_issilent) - sound(self, CHAN_PROJECTILE, "weapons/mine_exp.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/mine_exp.wav", VOL_BASE, ATTN_NORM); } else if(req == WR_PRECACHE) { precache_sound("weapons/mine_exp.wav"); } else if (req == WR_SUICIDEMESSAGE) - w_deathtypestring = "%s exploded"; + if(w_deathtype & HITTYPE_BOUNCE) // (remote detonation) + w_deathtypestring = _("%s blew themself up with their minelayer"); + else + w_deathtypestring = _("%s forgot about their mine"); else if (req == WR_KILLMESSAGE) { if(w_deathtype & HITTYPE_BOUNCE) // (remote detonation) - w_deathtypestring = "%s got too close to %s's mine"; + w_deathtypestring = _("%s got too close to %s's mine"); else if(w_deathtype & HITTYPE_SPLASH) - w_deathtypestring = "%s almost dodged %s's mine"; + w_deathtypestring = _("%s almost dodged %s's mine"); else - w_deathtypestring = "%s stepped on %s's mine"; + w_deathtypestring = _("%s stepped on %s's mine"); } return TRUE; } diff --git a/qcsrc/server/w_minstanex.qc b/qcsrc/server/w_minstanex.qc index f515d98b5a..34c71cf509 100644 --- a/qcsrc/server/w_minstanex.qc +++ b/qcsrc/server/w_minstanex.qc @@ -1,15 +1,16 @@ #ifdef REGISTER_WEAPON -REGISTER_WEAPON(MINSTANEX, w_minstanex, IT_CELLS, 7, WEP_FLAG_HIDDEN | WEP_FLAG_CANCLIMB | WEP_TYPE_HITSCAN, BOT_PICKUP_RATING_HIGH, "minstanex", "minstanex", "MinstaNex"); +REGISTER_WEAPON(MINSTANEX, w_minstanex, IT_CELLS, 7, WEP_FLAG_HIDDEN | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_HITSCAN, BOT_PICKUP_RATING_HIGH, "minstanex", "minstanex", _("MinstaNex")) #else #ifdef SVQC .float minstanex_lasthit; +.float jump_interval; void W_MinstaNex_Attack (void) { float flying; flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last - W_SetupShot (self, TRUE, 0, "weapons/minstanexfire.wav", CHAN_WEAPON, 10000); + W_SetupShot (self, TRUE, 0, "weapons/minstanexfire.wav", CH_WEAPON_A, 10000); yoda = 0; damage_goodhits = 0; @@ -43,7 +44,7 @@ void W_MinstaNex_Attack (void) // teamcolor / hit beam effect vector v; v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos); - if(teams_matter) + if(teamplay) { switch(self.team) { @@ -80,87 +81,88 @@ void W_MinstaNex_Attack (void) if (trace_ent.solid == SOLID_BSP && !(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)) Damage_DamageInfo(trace_endpos, 10000, 0, 0, 800 * w_shotdir, WEP_MINSTANEX, self); - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - { - if (g_minstagib) - self.ammo_cells = self.ammo_cells - 1; - else - self.ammo_cells = self.ammo_cells - autocvar_g_balance_minstanex_ammo; - } + if (g_minstagib) + W_DecreaseAmmo(ammo_cells, 1, autocvar_g_balance_minstanex_reload_ammo); + else + W_DecreaseAmmo(ammo_cells, autocvar_g_balance_minstanex_ammo, autocvar_g_balance_minstanex_reload_ammo); } .float minstagib_nextthink; -void minstagib_ammocheck (void) +.float minstagib_needammo; +void minstagib_stop_countdown(void) { - if (time < self.minstagib_nextthink || self.deadflag || gameover) + if (self.minstagib_needammo) + { + self.health = 100; + Send_CSQC_Centerprint_Generic_Expire(self, CPID_MINSTA_FINDAMMO); + } + self.minstagib_needammo = FALSE; +} +void minstagib_ammocheck(void) +{ + if (time < self.minstagib_nextthink) return; - if (self.ammo_cells <= 0) + if (self.deadflag || gameover || self.ammo_cells > 0 || (self.items & IT_UNLIMITED_WEAPON_AMMO)) + minstagib_stop_countdown(); + else { + self.minstagib_needammo = TRUE; if (self.health == 5) { - centerprint(self, "you're dead now...\n"); Damage(self, self, self, 5, DEATH_NOAMMO, self.origin, '0 0 0'); AnnounceTo(self, "terminated"); } else if (self.health == 10) { - centerprint(self, "^11^7 second left to find some ammo\n"); Damage(self, self, self, 5, DEATH_NOAMMO, self.origin, '0 0 0'); AnnounceTo(self, "1"); } else if (self.health == 20) { - centerprint(self, "^12^7 seconds left to find some ammo\n"); Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0'); AnnounceTo(self, "2"); } else if (self.health == 30) { - centerprint(self, "^13^7 seconds left to find some ammo\n"); Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0'); AnnounceTo(self, "3"); } else if (self.health == 40) { - centerprint(self, "^14^7 seconds left to find some ammo\n"); Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0'); AnnounceTo(self, "4"); } else if (self.health == 50) { - centerprint(self, "^15^7 seconds left to find some ammo\n"); Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0'); AnnounceTo(self, "5"); } else if (self.health == 60) { - centerprint(self, "^36^7 seconds left to find some ammo\n"); Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0'); AnnounceTo(self, "6"); } else if (self.health == 70) { - centerprint(self, "^37^7 seconds left to find some ammo\n"); Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0'); AnnounceTo(self, "7"); } else if (self.health == 80) { - centerprint(self, "^38^7 seconds left to find some ammo\n"); Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0'); AnnounceTo(self, "8"); } else if (self.health == 90) { - centerprint(self, "^39^7 seconds left to find some ammo\n"); + Send_CSQC_Centerprint_Generic(self, CPID_MINSTA_FINDAMMO, "^1%d^7 seconds left to find some ammo", 1, 9); Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0'); AnnounceTo(self, "9"); } else if (self.health == 100) { - centerprint(self, "get some ammo or\nyou'll be dead in ^310^7 seconds..."); + Send_CSQC_Centerprint_Generic(self, CPID_MINSTA_FINDAMMO, "get some ammo or\nyou'll be dead in ^3%d^7 seconds...", 1, 10); Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0'); if not(self.flags & FL_GODMODE) AnnounceTo(self, "10"); @@ -173,16 +175,30 @@ void spawnfunc_weapon_minstanex (void); // defined in t_items.qc float w_minstanex(float req) { + float ammo_amount; + float minstanex_ammo; + + // now multiple WR_s use this + if(g_minstagib) + minstanex_ammo = 1; + else + minstanex_ammo = autocvar_g_balance_minstanex_ammo; + if (req == WR_AIM) { - if(self.ammo_cells>0) + if(self.ammo_cells > 0) self.BUTTON_ATCK = bot_aim(1000000, 0, 1, FALSE); else self.BUTTON_ATCK2 = bot_aim(autocvar_g_balance_laser_primary_speed, 0, autocvar_g_balance_laser_primary_lifetime, FALSE); } else if (req == WR_THINK) { - if (self.BUTTON_ATCK) + // if the laser uses load, we also consider its ammo for reloading + if(autocvar_g_balance_minstanex_reload_ammo && autocvar_g_balance_minstanex_laser_ammo && self.clip_load < min(minstanex_ammo, autocvar_g_balance_minstanex_laser_ammo)) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else if(autocvar_g_balance_minstanex_reload_ammo && self.clip_load < minstanex_ammo) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else if (self.BUTTON_ATCK) { if (weapon_prepareattack(0, autocvar_g_balance_minstanex_refire)) { @@ -193,8 +209,14 @@ float w_minstanex(float req) else if (self.BUTTON_ATCK2) { if (self.jump_interval <= time) + if (weapon_prepareattack(1, -1)) { - self.jump_interval = time + autocvar_g_balance_laser_primary_refire * W_WeaponRateFactor(); + // handle refire manually, so that primary and secondary can be fired without conflictions (important for minstagib) + self.jump_interval = time + autocvar_g_balance_minstanex_laser_refire * W_WeaponRateFactor(); + + // decrease ammo for the laser? + if(autocvar_g_balance_minstanex_laser_ammo) + W_DecreaseAmmo(ammo_cells, autocvar_g_balance_minstanex_laser_ammo, autocvar_g_balance_minstanex_reload_ammo); // ugly minstagib hack to reuse the fire mode of the laser float w; @@ -202,6 +224,9 @@ float w_minstanex(float req) self.weapon = WEP_LASER; W_Laser_Attack(2); self.weapon = w; + + // now do normal refire + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_minstanex_laser_animtime, w_ready); } } } @@ -215,28 +240,45 @@ float w_minstanex(float req) precache_sound ("weapons/nexwhoosh1.wav"); precache_sound ("weapons/nexwhoosh2.wav"); precache_sound ("weapons/nexwhoosh3.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else w_laser(WR_PRECACHE); } else if (req == WR_SETUP) { weapon_setup(WEP_MINSTANEX); + self.current_ammo = ammo_cells; self.minstanex_lasthit = 0; } else if (req == WR_CHECKAMMO1) { - if (g_minstagib) - return self.ammo_cells >= 1; - else - return self.ammo_cells >= autocvar_g_balance_minstanex_ammo; + ammo_amount = self.ammo_cells >= minstanex_ammo; + ammo_amount += self.(weapon_load[WEP_MINSTANEX]) >= minstanex_ammo; + return ammo_amount; } else if (req == WR_CHECKAMMO2) - return TRUE; + { + if(!autocvar_g_balance_minstanex_laser_ammo) + return TRUE; + ammo_amount = self.ammo_cells >= autocvar_g_balance_minstanex_laser_ammo; + ammo_amount += self.(weapon_load[WEP_MINSTANEX]) >= autocvar_g_balance_minstanex_laser_ammo; + return ammo_amount; + } else if (req == WR_RESETPLAYER) { self.minstanex_lasthit = 0; } + else if (req == WR_RELOAD) + { + float used_ammo; + if(autocvar_g_balance_minstanex_laser_ammo) + used_ammo = min(minstanex_ammo, autocvar_g_balance_minstanex_laser_ammo); + else + used_ammo = minstanex_ammo; + + W_Reload(used_ammo, autocvar_g_balance_minstanex_reload_ammo, autocvar_g_balance_minstanex_reload_time, "weapons/reload.wav"); + } return TRUE; -}; +} #endif #ifdef CSQC float w_minstanex(float req) @@ -247,16 +289,16 @@ float w_minstanex(float req) org2 = w_org + w_backoff * 6; pointparticles(particleeffectnum("nex_impact"), org2, '0 0 0', 1); if(!w_issilent) - sound(self, CHAN_PROJECTILE, "weapons/neximpact.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/neximpact.wav", VOL_BASE, ATTN_NORM); } else if(req == WR_PRECACHE) { precache_sound("weapons/neximpact.wav"); } else if (req == WR_SUICIDEMESSAGE) - w_deathtypestring = "%s did the impossible"; + w_deathtypestring = _("%s is now thinking with portals"); else if (req == WR_KILLMESSAGE) - w_deathtypestring = "%s has been vaporized by %s"; + w_deathtypestring = _("%s has been vaporized by %s's minstanex"); return TRUE; } #endif diff --git a/qcsrc/server/w_nex.qc b/qcsrc/server/w_nex.qc index 7b1239b898..cdcabc8668 100644 --- a/qcsrc/server/w_nex.qc +++ b/qcsrc/server/w_nex.qc @@ -1,7 +1,8 @@ #ifdef REGISTER_WEAPON -REGISTER_WEAPON(NEX, w_nex, IT_CELLS, 7, WEP_FLAG_NORMAL | WEP_TYPE_HITSCAN, BOT_PICKUP_RATING_HIGH, "nex", "nex", "Nex"); +REGISTER_WEAPON(NEX, w_nex, IT_CELLS, 7, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN, BOT_PICKUP_RATING_HIGH, "nex", "nex", _("Nex")) #else #ifdef SVQC + void SendCSQCNexBeamParticle(float charge) { vector v; v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos); @@ -47,19 +48,19 @@ void W_Nex_Attack (float issecondary) { charge = autocvar_g_balance_nex_charge_mindmg / mydmg + (1 - autocvar_g_balance_nex_charge_mindmg / mydmg) * self.nex_charge; self.nex_charge *= autocvar_g_balance_nex_charge_shot_multiplier; // do this AFTER setting mydmg/myforce - // O RLY? -- divVerent - // YA RLY -- FruitieX + // O RLY? -- divVerent + // YA RLY -- FruitieX } else charge = 1; mydmg *= charge; myforce *= charge; - W_SetupShot (self, TRUE, 5, "weapons/nexfire.wav", CHAN_WEAPON, mydmg); - if(charge > autocvar_g_balance_nex_charge_limit && autocvar_g_balance_nex_charge_limit) // if the Nex is overcharged, we play an extra sound - { - sound (self, CHAN_WEAPON2, "weapons/nexcharge.wav", VOL_BASE * (charge - 0.5 * autocvar_g_balance_nex_charge_limit) / (1 - 0.5 * autocvar_g_balance_nex_charge_limit), ATTN_NORM); - } + W_SetupShot (self, TRUE, 5, "weapons/nexfire.wav", CH_WEAPON_A, mydmg); + if(charge > autocvar_g_balance_nex_charge_animlimit && autocvar_g_balance_nex_charge_animlimit) // if the Nex is overcharged, we play an extra sound + { + sound (self, CH_WEAPON_B, "weapons/nexcharge.wav", VOL_BASE * (charge - 0.5 * autocvar_g_balance_nex_charge_animlimit) / (1 - 0.5 * autocvar_g_balance_nex_charge_animlimit), ATTN_NORM); + } yoda = 0; FireRailgunBullet (w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, WEP_NEX); @@ -69,13 +70,12 @@ void W_Nex_Attack (float issecondary) //beam and muzzle flash done on client SendCSQCNexBeamParticle(charge); - + // flash and burn the wall if (trace_ent.solid == SOLID_BSP && !(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)) Damage_DamageInfo(trace_endpos, mydmg, 0, 0, myforce * w_shotdir, WEP_NEX, self); - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_cells = self.ammo_cells - myammo; + W_DecreaseAmmo(ammo_cells, myammo, autocvar_g_balance_nex_reload_ammo); } void spawnfunc_weapon_nex (void); // defined in t_items.qc @@ -84,93 +84,113 @@ void spawnfunc_weapon_nex (void); // defined in t_items.qc float w_nex(float req) { float dt; + float ammo_amount; if (req == WR_AIM) { - self.BUTTON_ATCK = bot_aim(1000000, 0, 1, FALSE); - self.BUTTON_ATCK2 = bot_aim(1000000, 0, 1, FALSE); + if(bot_aim(1000000, 0, 1, FALSE)) + self.BUTTON_ATCK = TRUE; + else + { + if(autocvar_g_balance_nex_charge) + self.BUTTON_ATCK2 = TRUE; + } } else if (req == WR_THINK) { if(autocvar_g_balance_nex_charge && self.nex_charge < autocvar_g_balance_nex_charge_limit) self.nex_charge = min(1, self.nex_charge + autocvar_g_balance_nex_charge_rate * frametime / W_TICSPERFRAME); - if(autocvar_g_balance_nex_charge) - { - self.weaponentity_glowmod_x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_limit); - self.weaponentity_glowmod_y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_limit); - self.weaponentity_glowmod_z = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_limit); - - if(self.nex_charge > autocvar_g_balance_nex_charge_limit) - { - self.weaponentity_glowmod_x = self.weaponentity_glowmod_x + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_full * (self.nex_charge - autocvar_g_balance_nex_charge_limit) / (1 - autocvar_g_balance_nex_charge_limit); - self.weaponentity_glowmod_y = self.weaponentity_glowmod_y + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_full * (self.nex_charge - autocvar_g_balance_nex_charge_limit) / (1 - autocvar_g_balance_nex_charge_limit); - self.weaponentity_glowmod_z = self.weaponentity_glowmod_z + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_full * (self.nex_charge - autocvar_g_balance_nex_charge_limit) / (1 - autocvar_g_balance_nex_charge_limit); - } - } - if(autocvar_g_balance_nex_secondary_chargepool) - if(self.nex_chargepool_ammo < 1) - { - if(self.nex_chargepool_pauseregen_finished < time) - self.nex_chargepool_ammo = min(1, self.nex_chargepool_ammo + autocvar_g_balance_nex_secondary_chargepool_regen * frametime / W_TICSPERFRAME); - self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_nex_secondary_chargepool_pause_health_regen); - } + if(self.nex_chargepool_ammo < 1) + { + if(self.nex_chargepool_pauseregen_finished < time) + self.nex_chargepool_ammo = min(1, self.nex_chargepool_ammo + autocvar_g_balance_nex_secondary_chargepool_regen * frametime / W_TICSPERFRAME); + self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_nex_secondary_chargepool_pause_health_regen); + } - if (self.BUTTON_ATCK) + if(autocvar_g_balance_nex_reload_ammo && self.clip_load < min(autocvar_g_balance_nex_primary_ammo, autocvar_g_balance_nex_secondary_ammo)) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else { - if (weapon_prepareattack(0, autocvar_g_balance_nex_primary_refire)) + if (self.BUTTON_ATCK) { - W_Nex_Attack(0); - weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nex_primary_animtime, w_ready); + if (weapon_prepareattack(0, autocvar_g_balance_nex_primary_refire)) + { + W_Nex_Attack(0); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nex_primary_animtime, w_ready); + } } - } - if (self.BUTTON_ATCK2) - { - if(autocvar_g_balance_nex_secondary_charge) + if ((autocvar_g_balance_nex_secondary_charge && !autocvar_g_balance_nex_secondary) ? (self.BUTTON_ZOOM | self.BUTTON_ZOOMSCRIPT) : self.BUTTON_ATCK2) { - self.nex_charge_rottime = time + autocvar_g_balance_nex_charge_rot_pause; - dt = frametime / W_TICSPERFRAME; - - if(autocvar_g_balance_nex_secondary_chargepool) + if(autocvar_g_balance_nex_secondary_charge) { - if(autocvar_g_balance_nex_secondary_ammo) + self.nex_charge_rottime = time + autocvar_g_balance_nex_charge_rot_pause; + dt = frametime / W_TICSPERFRAME; + + if(self.nex_charge < 1) { - // always deplete if secondary is held - self.nex_chargepool_ammo = max(0, self.nex_chargepool_ammo - autocvar_g_balance_nex_secondary_ammo * dt); + if(autocvar_g_balance_nex_secondary_chargepool) + { + if(autocvar_g_balance_nex_secondary_ammo) + { + // always deplete if secondary is held + self.nex_chargepool_ammo = max(0, self.nex_chargepool_ammo - autocvar_g_balance_nex_secondary_ammo * dt); - dt = min(dt, (1 - self.nex_charge) / autocvar_g_balance_nex_secondary_charge_rate); - self.nex_chargepool_pauseregen_finished = time + autocvar_g_balance_nex_secondary_chargepool_pause_regen; - dt = min(dt, self.nex_chargepool_ammo); - dt = max(0, dt); + dt = min(dt, (1 - self.nex_charge) / autocvar_g_balance_nex_secondary_charge_rate); + self.nex_chargepool_pauseregen_finished = time + autocvar_g_balance_nex_secondary_chargepool_pause_regen; + dt = min(dt, self.nex_chargepool_ammo); + dt = max(0, dt); - self.nex_charge += dt * autocvar_g_balance_nex_secondary_charge_rate; - } - } + self.nex_charge += dt * autocvar_g_balance_nex_secondary_charge_rate; + } + } - else if(autocvar_g_balance_nex_secondary_ammo) - { - if(self.nex_charge < 1) - { - dt = min(dt, (1 - self.nex_charge) / autocvar_g_balance_nex_secondary_charge_rate); - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) + else if(autocvar_g_balance_nex_secondary_ammo) { - dt = min(dt, (self.ammo_cells - autocvar_g_balance_nex_primary_ammo) / autocvar_g_balance_nex_secondary_ammo); - dt = max(0, dt); - if(dt > 0) + if(self.BUTTON_ATCK2) // only eat ammo when the button is pressed { - self.ammo_cells = max(autocvar_g_balance_nex_secondary_ammo, self.ammo_cells - autocvar_g_balance_nex_secondary_ammo * dt); + dt = min(dt, (1 - self.nex_charge) / autocvar_g_balance_nex_secondary_charge_rate); + if not(self.items & IT_UNLIMITED_WEAPON_AMMO) + { + // if this weapon is reloadable, decrease its load. Else decrease the player's ammo + if(autocvar_g_balance_nex_reload_ammo) + { + dt = min(dt, (self.clip_load - autocvar_g_balance_nex_primary_ammo) / autocvar_g_balance_nex_secondary_ammo); + dt = max(0, dt); + if(dt > 0) + { + self.clip_load = max(autocvar_g_balance_nex_secondary_ammo, self.clip_load - autocvar_g_balance_nex_secondary_ammo * dt); + } + self.(weapon_load[WEP_NEX]) = self.clip_load; + } + else + { + dt = min(dt, (self.ammo_cells - autocvar_g_balance_nex_primary_ammo) / autocvar_g_balance_nex_secondary_ammo); + dt = max(0, dt); + if(dt > 0) + { + self.ammo_cells = max(autocvar_g_balance_nex_secondary_ammo, self.ammo_cells - autocvar_g_balance_nex_secondary_ammo * dt); + } + } + } + self.nex_charge += dt * autocvar_g_balance_nex_secondary_charge_rate; } } - self.nex_charge += dt * autocvar_g_balance_nex_secondary_charge_rate; + + else + { + dt = min(dt, (1 - self.nex_charge) / autocvar_g_balance_nex_secondary_charge_rate); + self.nex_charge += dt * autocvar_g_balance_nex_secondary_charge_rate; + } } } - } - else if(autocvar_g_balance_nex_secondary) - { - if (weapon_prepareattack(0, autocvar_g_balance_nex_secondary_refire)) + else if(autocvar_g_balance_nex_secondary) { - W_Nex_Attack(1); - weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nex_secondary_animtime, w_ready); + if (weapon_prepareattack(0, autocvar_g_balance_nex_secondary_refire)) + { + W_Nex_Attack(1); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nex_secondary_animtime, w_ready); + } } } } @@ -186,15 +206,40 @@ float w_nex(float req) precache_sound ("weapons/nexwhoosh1.wav"); precache_sound ("weapons/nexwhoosh2.wav"); precache_sound ("weapons/nexwhoosh3.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else } else if (req == WR_SETUP) + { weapon_setup(WEP_NEX); + self.current_ammo = ammo_cells; + } else if (req == WR_CHECKAMMO1) - return self.ammo_cells >= autocvar_g_balance_nex_primary_ammo; + { + ammo_amount = self.ammo_cells >= autocvar_g_balance_nex_primary_ammo; + ammo_amount += (autocvar_g_balance_nex_reload_ammo && self.(weapon_load[WEP_NEX]) >= autocvar_g_balance_nex_primary_ammo); + return ammo_amount; + } else if (req == WR_CHECKAMMO2) - return self.ammo_cells >= autocvar_g_balance_nex_primary_ammo; // don't allow charging if we don't have enough ammo + { + if(autocvar_g_balance_nex_secondary) + { + // don't allow charging if we don't have enough ammo + ammo_amount = self.ammo_cells >= autocvar_g_balance_nex_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_NEX]) >= autocvar_g_balance_nex_secondary_ammo; + return ammo_amount; + } + else + { + return FALSE; // zoom is not a fire mode + } + } + else if (req == WR_RELOAD) + { + W_Reload(min(autocvar_g_balance_nex_primary_ammo, autocvar_g_balance_nex_secondary_ammo), autocvar_g_balance_nex_reload_ammo, autocvar_g_balance_nex_reload_time, "weapons/reload.wav"); + } + return TRUE; -}; +} #endif #ifdef CSQC float w_nex(float req) @@ -205,16 +250,16 @@ float w_nex(float req) org2 = w_org + w_backoff * 6; pointparticles(particleeffectnum("nex_impact"), org2, '0 0 0', 1); if(!w_issilent) - sound(self, CHAN_PROJECTILE, "weapons/neximpact.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/neximpact.wav", VOL_BASE, ATTN_NORM); } else if(req == WR_PRECACHE) { precache_sound("weapons/neximpact.wav"); } else if (req == WR_SUICIDEMESSAGE) - w_deathtypestring = "%s did the impossible"; + w_deathtypestring = _("%s is now thinking with portals"); else if (req == WR_KILLMESSAGE) - w_deathtypestring = "%s has been vaporized by %s"; + w_deathtypestring = _("%s has been vaporized by %s's nex"); return TRUE; } #endif diff --git a/qcsrc/server/w_porto.qc b/qcsrc/server/w_porto.qc index 8083a79685..fb8e427cc1 100644 --- a/qcsrc/server/w_porto.qc +++ b/qcsrc/server/w_porto.qc @@ -1,5 +1,5 @@ #ifdef REGISTER_WEAPON -REGISTER_WEAPON(PORTO, w_porto, 0, 0, WEP_TYPE_OTHER, 0, "porto" , "porto", "Port-O-Launch"); +REGISTER_WEAPON(PORTO, w_porto, 0, 0, WEP_TYPE_OTHER, 0, "porto" , "porto", _("Port-O-Launch")) #else #ifdef SVQC .entity porto_current; @@ -9,42 +9,42 @@ REGISTER_WEAPON(PORTO, w_porto, 0, 0, WEP_TYPE_OTHER, 0, "porto" , "porto", "Por void W_Porto_Success (void) { - if(self.owner == world) + if(self.realowner == world) { objerror("Cannot succeed successfully: no owner\n"); return; } - self.owner.porto_current = world; + self.realowner.porto_current = world; remove(self); } string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo); void W_Porto_Fail (float failhard) { - if(self.owner == world) + if(self.realowner == world) { objerror("Cannot fail successfully: no owner\n"); return; } // no portals here! - Portal_ClearWithID(self.owner, self.portal_id); - self.owner.porto_current = world; + Portal_ClearWithID(self.realowner, self.portal_id); + self.realowner.porto_current = world; - if(!failhard && self.owner.playerid == self.playerid && self.owner.deadflag == DEAD_NO && !(self.owner.weapons & WEPBIT_PORTO)) + if(!failhard && self.realowner.playerid == self.playerid && self.realowner.deadflag == DEAD_NO && !(self.realowner.weapons & WEPBIT_PORTO)) { setsize (self, '-16 -16 0', '16 16 32'); setorigin(self, self.origin + trace_plane_normal); if(move_out_of_solid(self)) { self.flags = FL_ITEM; - self.velocity = trigger_push_calculatevelocity(self.origin, self.owner, 128); + self.velocity = trigger_push_calculatevelocity(self.origin, self.realowner, 128); tracetoss(self, self); - if(vlen(trace_endpos - self.owner.origin) < 128) + if(vlen(trace_endpos - self.realowner.origin) < 128) { - W_ThrowNewWeapon(self.owner, WEP_PORTO, 0, self.origin, self.velocity); - centerprint(self.owner, "^1Portal deployment failed.\n\n^2Catch it to try again!"); + W_ThrowNewWeapon(self.realowner, WEP_PORTO, 0, self.origin, self.velocity); + centerprint(self.realowner, "^1Portal deployment failed.\n\n^2Catch it to try again!"); } } } @@ -53,7 +53,7 @@ void W_Porto_Fail (float failhard) void W_Porto_Remove (entity p) { - if(p.porto_current) + if(p.porto_current.realowner == p && p.porto_current.classname == "porto") { entity oldself; oldself = self; @@ -66,7 +66,7 @@ void W_Porto_Remove (entity p) void W_Porto_Think (void) { trace_plane_normal = '0 0 0'; - if(self.owner.playerid != self.playerid) + if(self.realowner.playerid != self.playerid) remove(self); else W_Porto_Fail(0); @@ -93,62 +93,62 @@ void W_Porto_Touch (void) return; } - if(self.owner.playerid != self.playerid) + if(self.realowner.playerid != self.playerid) { - sound(self, CHAN_PROJECTILE, "porto/unsupported.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTN_NORM); remove(self); } else if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP) { - spamsound(self, CHAN_PROJECTILE, "porto/bounce.wav", VOL_BASE, ATTN_NORM); + spamsound(self, CH_SHOTS, "porto/bounce.wav", VOL_BASE, ATTN_NORM); // just reflect self.right_vector = self.right_vector - 2 * trace_plane_normal * (self.right_vector * trace_plane_normal); self.angles = vectoangles(self.velocity - 2 * trace_plane_normal * (self.velocity * trace_plane_normal)); } else if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT) { - sound(self, CHAN_PROJECTILE, "porto/unsupported.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTN_NORM); W_Porto_Fail(0); } else if(self.effects & EF_RED) { self.effects += EF_BLUE - EF_RED; - if(Portal_SpawnInPortalAtTrace(self.owner, self.right_vector, self.portal_id)) + if(Portal_SpawnInPortalAtTrace(self.realowner, self.right_vector, self.portal_id)) { - sound(self, CHAN_PROJECTILE, "porto/create.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTN_NORM); trace_plane_normal = norm; - centerprint(self.owner, "^1In^7-portal created."); + centerprint(self.realowner, "^1In^7-portal created."); self.right_vector = self.right_vector - 2 * trace_plane_normal * (self.right_vector * norm); self.angles = vectoangles(self.velocity - 2 * trace_plane_normal * (self.velocity * norm)); CSQCProjectile(self, TRUE, PROJECTILE_PORTO_BLUE, TRUE); // change type } else { - sound(self, CHAN_PROJECTILE, "porto/unsupported.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTN_NORM); trace_plane_normal = norm; W_Porto_Fail(0); } } else { - if(self.owner.portal_in.portal_id == self.portal_id) + if(self.realowner.portal_in.portal_id == self.portal_id) { - if(Portal_SpawnOutPortalAtTrace(self.owner, self.right_vector, self.portal_id)) + if(Portal_SpawnOutPortalAtTrace(self.realowner, self.right_vector, self.portal_id)) { - sound(self, CHAN_PROJECTILE, "porto/create.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTN_NORM); trace_plane_normal = norm; - centerprint(self.owner, "^4Out^7-portal created."); + centerprint(self.realowner, "^4Out^7-portal created."); W_Porto_Success(); } else { - sound(self, CHAN_PROJECTILE, "porto/unsupported.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTN_NORM); W_Porto_Fail(0); } } else { - sound(self, CHAN_PROJECTILE, "porto/unsupported.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTN_NORM); W_Porto_Fail(0); } } @@ -156,11 +156,11 @@ void W_Porto_Touch (void) void W_Porto_Attack (void) { - local entity gren; + entity gren; if not(self.items & IT_UNLIMITED_SUPERWEAPONS) self.weapons = self.weapons - (self.weapons & WEPBIT_PORTO); - W_SetupShot (self, FALSE, 4, "porto/fire.wav", CHAN_WEAPON, 0); + W_SetupShot (self, FALSE, 4, "porto/fire.wav", CH_WEAPON_A, 0); // always shoot from the eye w_shotdir = v_forward; w_shotorg = self.origin + self.view_ofs + ((w_shotorg - self.origin - self.view_ofs) * v_forward) * v_forward; @@ -168,7 +168,7 @@ void W_Porto_Attack (void) //pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); gren = spawn (); - gren.owner = self; + gren.owner = gren.realowner = self; gren.playerid = self.playerid; gren.classname = "porto"; gren.bot_dodge = TRUE; @@ -270,13 +270,16 @@ float w_porto(float req) precache_sound ("porto/unsupported.wav"); } else if (req == WR_SETUP) + { weapon_setup(WEP_PORTO); + self.current_ammo = ammo_none; + } else if (req == WR_RESETPLAYER) { self.porto_current = world; } return TRUE; -}; +} #endif #ifdef CSQC float w_porto(float req) @@ -290,9 +293,9 @@ float w_porto(float req) // nothing to do } else if (req == WR_SUICIDEMESSAGE) - w_deathtypestring = "%s did the impossible"; + w_deathtypestring = _("%s did the impossible"); else if (req == WR_KILLMESSAGE) - w_deathtypestring = "%s felt %s doing the impossible to him"; + w_deathtypestring = _("%s felt %s doing the impossible to him"); return TRUE; } #endif diff --git a/qcsrc/server/w_rifle.qc b/qcsrc/server/w_rifle.qc new file mode 100644 index 0000000000..89cb37257d --- /dev/null +++ b/qcsrc/server/w_rifle.qc @@ -0,0 +1,262 @@ +#ifdef REGISTER_WEAPON +REGISTER_WEAPON(RIFLE, w_rifle, IT_NAILS, 7, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN, BOT_PICKUP_RATING_MID, "campingrifle", "rifle", _("Rifle")) +#else +#ifdef SVQC + +.float rifle_accumulator; + +void W_Rifle_FireBullet(float pSpread, float pDamage, float pHeadshotAddedDamage, float pForce, float pSpeed, float pLifetime, float pAmmo, float deathtype, float pBulletConstant, float pTracer, float pShots, string pSound) +{ + float i; + + W_DecreaseAmmo(ammo_nails, pAmmo, autocvar_g_balance_rifle_reload_ammo); + + W_SetupShot (self, autocvar_g_antilag_bullets && pSpeed >= autocvar_g_antilag_bullets, 2, pSound, CH_WEAPON_A, (pDamage + pHeadshotAddedDamage) * pShots); + + pointparticles(particleeffectnum("rifle_muzzleflash"), w_shotorg, w_shotdir * 2000, 1); + + if(self.BUTTON_ZOOM | self.BUTTON_ZOOMSCRIPT) // if zoomed, shoot from the eye + { + w_shotdir = v_forward; + w_shotorg = self.origin + self.view_ofs + ((w_shotorg - self.origin - self.view_ofs) * v_forward) * v_forward; + } + + for(i = 0; i < pShots; ++i) + fireBallisticBullet(w_shotorg, w_shotdir, pSpread, pSpeed, pLifetime, pDamage, pHeadshotAddedDamage / pDamage, pForce, deathtype, (pTracer ? EF_RED : EF_BLUE), 1, pBulletConstant); + endFireBallisticBullet(); + + if (autocvar_g_casings >= 2) + SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self); +} + +void W_Rifle_Attack() +{ + W_Rifle_FireBullet(autocvar_g_balance_rifle_primary_spread, autocvar_g_balance_rifle_primary_damage, autocvar_g_balance_rifle_primary_headshotaddeddamage, autocvar_g_balance_rifle_primary_force, autocvar_g_balance_rifle_primary_speed, autocvar_g_balance_rifle_primary_lifetime, autocvar_g_balance_rifle_primary_ammo, WEP_RIFLE, autocvar_g_balance_rifle_primary_bulletconstant, autocvar_g_balance_rifle_primary_tracer, autocvar_g_balance_rifle_primary_shots, "weapons/campingrifle_fire.wav"); +} + +void W_Rifle_Attack2() +{ + W_Rifle_FireBullet(autocvar_g_balance_rifle_secondary_spread, autocvar_g_balance_rifle_secondary_damage, autocvar_g_balance_rifle_secondary_headshotaddeddamage, autocvar_g_balance_rifle_secondary_force, autocvar_g_balance_rifle_secondary_speed, autocvar_g_balance_rifle_secondary_lifetime, autocvar_g_balance_rifle_secondary_ammo, WEP_RIFLE | HITTYPE_SECONDARY, autocvar_g_balance_rifle_secondary_bulletconstant, autocvar_g_balance_rifle_secondary_tracer, autocvar_g_balance_rifle_secondary_shots, "weapons/campingrifle_fire2.wav"); +} + +void spawnfunc_weapon_rifle (void) +{ + weapon_defaultspawnfunc(WEP_RIFLE); +} + +// compatibility alias +void spawnfunc_weapon_campingrifle (void) +{ + spawnfunc_weapon_rifle(); +} +void spawnfunc_weapon_sniperrifle (void) +{ + spawnfunc_weapon_rifle(); +} + +.void(void) rifle_bullethail_attackfunc; +.float rifle_bullethail_frame; +.float rifle_bullethail_animtime; +.float rifle_bullethail_refire; +void W_Rifle_BulletHail_Continue() +{ + float r, sw, af; + + sw = self.switchweapon; // make it not detect weapon changes as reason to abort firing + af = ATTACK_FINISHED(self); + self.switchweapon = self.weapon; + ATTACK_FINISHED(self) = time; + print(ftos(self.ammo_nails), "\n"); + r = weapon_prepareattack(self.rifle_bullethail_frame == WFRAME_FIRE2, self.rifle_bullethail_refire); + if(self.switchweapon == self.weapon) + self.switchweapon = sw; + if(r) + { + self.rifle_bullethail_attackfunc(); + weapon_thinkf(self.rifle_bullethail_frame, self.rifle_bullethail_animtime, W_Rifle_BulletHail_Continue); + print("thinkf set\n"); + } + else + { + ATTACK_FINISHED(self) = af; // reset attack_finished if we didn't fire, so the last shot enforces the refire time + print("out of ammo... ", ftos(self.weaponentity.state), "\n"); + } +} + +void W_Rifle_BulletHail(float mode, void(void) AttackFunc, float fr, float animtime, float refire) +{ + // if we get here, we have at least one bullet to fire + AttackFunc(); + if(mode) + { + // continue hail + self.rifle_bullethail_attackfunc = AttackFunc; + self.rifle_bullethail_frame = fr; + self.rifle_bullethail_animtime = animtime; + self.rifle_bullethail_refire = refire; + weapon_thinkf(fr, animtime, W_Rifle_BulletHail_Continue); + } + else + { + // just one shot + weapon_thinkf(fr, animtime, w_ready); + } +} + +.float bot_secondary_riflemooth; +float w_rifle(float req) +{ + float ammo_amount; + + if (req == WR_AIM) + { + self.BUTTON_ATCK=FALSE; + self.BUTTON_ATCK2=FALSE; + if(vlen(self.origin-self.enemy.origin) > 1000) + self.bot_secondary_riflemooth = 0; + if(self.bot_secondary_riflemooth == 0) + { + if(bot_aim(autocvar_g_balance_rifle_primary_speed, 0, autocvar_g_balance_rifle_primary_lifetime, FALSE)) + { + self.BUTTON_ATCK = TRUE; + if(random() < 0.01) self.bot_secondary_riflemooth = 1; + } + } + else + { + if(bot_aim(autocvar_g_balance_rifle_secondary_speed, 0, autocvar_g_balance_rifle_secondary_lifetime, FALSE)) + { + self.BUTTON_ATCK2 = TRUE; + if(random() < 0.03) self.bot_secondary_riflemooth = 0; + } + } + } + else if (req == WR_THINK) + { + if(autocvar_g_balance_rifle_reload_ammo && self.clip_load < min(autocvar_g_balance_rifle_primary_ammo, autocvar_g_balance_rifle_secondary_ammo)) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else + { + self.rifle_accumulator = bound(time - autocvar_g_balance_rifle_bursttime, self.rifle_accumulator, time); + if (self.BUTTON_ATCK) + if (weapon_prepareattack_check(0, autocvar_g_balance_rifle_primary_refire)) + if (time >= self.rifle_accumulator + autocvar_g_balance_rifle_primary_burstcost) + { + weapon_prepareattack_do(0, autocvar_g_balance_rifle_primary_refire); + W_Rifle_BulletHail(autocvar_g_balance_rifle_primary_bullethail, W_Rifle_Attack, WFRAME_FIRE1, autocvar_g_balance_rifle_primary_animtime, autocvar_g_balance_rifle_primary_refire); + self.rifle_accumulator += autocvar_g_balance_rifle_primary_burstcost; + } + if (self.BUTTON_ATCK2) + { + if (autocvar_g_balance_rifle_secondary) + { + if(autocvar_g_balance_rifle_secondary_reload) + weapon_action(self.weapon, WR_RELOAD); + else + { + if (weapon_prepareattack_check(1, autocvar_g_balance_rifle_secondary_refire)) + if (time >= self.rifle_accumulator + autocvar_g_balance_rifle_secondary_burstcost) + { + weapon_prepareattack_do(1, autocvar_g_balance_rifle_secondary_refire); + W_Rifle_BulletHail(autocvar_g_balance_rifle_secondary_bullethail, W_Rifle_Attack2, WFRAME_FIRE2, autocvar_g_balance_rifle_secondary_animtime, autocvar_g_balance_rifle_primary_refire); + self.rifle_accumulator += autocvar_g_balance_rifle_secondary_burstcost; + } + } + } + } + } + } + else if (req == WR_PRECACHE) + { + precache_model ("models/weapons/g_campingrifle.md3"); + precache_model ("models/weapons/v_campingrifle.md3"); + precache_model ("models/weapons/h_campingrifle.iqm"); + precache_sound ("weapons/campingrifle_fire.wav"); + precache_sound ("weapons/campingrifle_fire2.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else + } + else if (req == WR_SETUP) + { + weapon_setup(WEP_RIFLE); + self.current_ammo = ammo_nails; + } + else if (req == WR_CHECKAMMO1) + { + ammo_amount = self.ammo_nails >= autocvar_g_balance_rifle_primary_ammo; + ammo_amount += self.(weapon_load[WEP_RIFLE]) >= autocvar_g_balance_rifle_primary_ammo; + return ammo_amount; + } + else if (req == WR_CHECKAMMO2) + { + ammo_amount = self.ammo_nails >= autocvar_g_balance_rifle_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_RIFLE]) >= autocvar_g_balance_rifle_secondary_ammo; + return ammo_amount; + } + else if (req == WR_RESETPLAYER) + { + self.rifle_accumulator = time - autocvar_g_balance_rifle_bursttime; + } + else if (req == WR_RELOAD) + { + W_Reload(min(autocvar_g_balance_rifle_primary_ammo, autocvar_g_balance_rifle_secondary_ammo), autocvar_g_balance_rifle_reload_ammo, autocvar_g_balance_rifle_reload_time, "weapons/reload.wav"); + } + return TRUE; +} +#endif +#ifdef CSQC +float w_rifle(float req) +{ + if(req == WR_IMPACTEFFECT) + { + vector org2; + org2 = w_org + w_backoff * 2; + pointparticles(particleeffectnum("machinegun_impact"), org2, w_backoff * 1000, 1); + if(!w_issilent) + { + if(w_random < 0.2) + sound(self, CH_SHOTS, "weapons/ric1.wav", VOL_BASE, ATTN_NORM); + else if(w_random < 0.4) + sound(self, CH_SHOTS, "weapons/ric2.wav", VOL_BASE, ATTN_NORM); + else if(w_random < 0.5) + sound(self, CH_SHOTS, "weapons/ric3.wav", VOL_BASE, ATTN_NORM); + } + } + else if(req == WR_PRECACHE) + { + precache_sound("weapons/ric1.wav"); + precache_sound("weapons/ric2.wav"); + precache_sound("weapons/ric3.wav"); + } + else if (req == WR_SUICIDEMESSAGE) + { + w_deathtypestring = _("%s is now thinking with portals"); + } + else if (req == WR_KILLMESSAGE) + { + if(w_deathtype & HITTYPE_SECONDARY) + { + if(w_deathtype & HITTYPE_BOUNCE) + w_deathtypestring = _("%s failed to hide from %s's rifle bullet hail"); + else + w_deathtypestring = _("%s died in %s's rifle bullet hail"); + } + else + { + if(w_deathtype & HITTYPE_BOUNCE) + { + // TODO special headshot message here too? + w_deathtypestring = _("%s failed to hide from %s's rifle"); + } + else + { + if(w_deathtype & HITTYPE_HEADSHOT) + w_deathtypestring = _("%s got shot in the head with a rifle by %s"); + else + w_deathtypestring = _("%s was sniped with a rifle by %s"); + } + } + } + return TRUE; +} +#endif +#endif diff --git a/qcsrc/server/w_rocketlauncher.qc b/qcsrc/server/w_rocketlauncher.qc index a5b64c4bf0..723389e712 100644 --- a/qcsrc/server/w_rocketlauncher.qc +++ b/qcsrc/server/w_rocketlauncher.qc @@ -1,5 +1,5 @@ #ifdef REGISTER_WEAPON -REGISTER_WEAPON(ROCKET_LAUNCHER, w_rlauncher, IT_ROCKETS, 9, WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_HIGH, "rl", "rocketlauncher", "Rocket Launcher"); +REGISTER_WEAPON(ROCKET_LAUNCHER, w_rlauncher, IT_ROCKETS, 9, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_HIGH, "rl", "rocketlauncher", _("Rocket Launcher")) #else #ifdef SVQC .float rl_release; @@ -7,10 +7,10 @@ REGISTER_WEAPON(ROCKET_LAUNCHER, w_rlauncher, IT_ROCKETS, 9, WEP_FLAG_NORMAL | W void W_Rocket_Unregister() { - if(self.owner && self.owner.lastrocket == self) + if(self.realowner && self.realowner.lastrocket == self) { - self.owner.lastrocket = world; - // self.owner.rl_release = 1; + self.realowner.lastrocket = world; + // self.realowner.rl_release = 1; } } @@ -20,22 +20,23 @@ void W_Rocket_Explode () if(other.takedamage == DAMAGE_AIM) if(other.classname == "player") - if(IsDifferentTeam(self.owner, other)) - if(IsFlying(other)) - AnnounceTo(self.owner, "airshot"); + if(IsDifferentTeam(self.realowner, other)) + if(other.deadflag == DEAD_NO) + if(IsFlying(other)) + AnnounceTo(self.realowner, "airshot"); self.event_damage = SUB_Null; self.takedamage = DAMAGE_NO; - RadiusDamage (self, self.owner, autocvar_g_balance_rocketlauncher_damage, autocvar_g_balance_rocketlauncher_edgedamage, autocvar_g_balance_rocketlauncher_radius, world, autocvar_g_balance_rocketlauncher_force, self.projectiledeathtype, other); + RadiusDamage (self, self.realowner, autocvar_g_balance_rocketlauncher_damage, autocvar_g_balance_rocketlauncher_edgedamage, autocvar_g_balance_rocketlauncher_radius, world, autocvar_g_balance_rocketlauncher_force, self.projectiledeathtype, other); - if (self.owner.weapon == WEP_ROCKET_LAUNCHER) + if (self.realowner.weapon == WEP_ROCKET_LAUNCHER) { - if(self.owner.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo) + if(self.realowner.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo) { - self.owner.cnt = WEP_ROCKET_LAUNCHER; - ATTACK_FINISHED(self.owner) = time; - self.owner.switchweapon = w_getbestweapon(self.owner); + self.realowner.cnt = WEP_ROCKET_LAUNCHER; + ATTACK_FINISHED(self.realowner) = time; + self.realowner.switchweapon = w_getbestweapon(self.realowner); } } remove (self); @@ -48,15 +49,15 @@ void W_Rocket_DoRemoteExplode () self.event_damage = SUB_Null; self.takedamage = DAMAGE_NO; - RadiusDamage (self, self.owner, autocvar_g_balance_rocketlauncher_remote_damage, autocvar_g_balance_rocketlauncher_remote_edgedamage, autocvar_g_balance_rocketlauncher_remote_radius, world, autocvar_g_balance_rocketlauncher_remote_force, self.projectiledeathtype | HITTYPE_BOUNCE, world); + RadiusDamage (self, self.realowner, autocvar_g_balance_rocketlauncher_remote_damage, autocvar_g_balance_rocketlauncher_remote_edgedamage, autocvar_g_balance_rocketlauncher_remote_radius, world, autocvar_g_balance_rocketlauncher_remote_force, self.projectiledeathtype | HITTYPE_BOUNCE, world); - if (self.owner.weapon == WEP_ROCKET_LAUNCHER) + if (self.realowner.weapon == WEP_ROCKET_LAUNCHER) { - if(self.owner.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo) + if(self.realowner.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo) { - self.owner.cnt = WEP_ROCKET_LAUNCHER; - ATTACK_FINISHED(self.owner) = time; - self.owner.switchweapon = w_getbestweapon(self.owner); + self.realowner.cnt = WEP_ROCKET_LAUNCHER; + ATTACK_FINISHED(self.realowner) = time; + self.realowner.switchweapon = w_getbestweapon(self.realowner); } } remove (self); @@ -109,19 +110,19 @@ entity FindLaserTarget(entity e, float dist_variance, float dot_variance) head = find(head, classname, "laser_target"); } - //bprint(selected.owner.netname); + //bprint(selected.realowner.netname); //bprint("\n"); return selected; } void W_Rocket_RemoteExplode() { - if(self.owner.deadflag == DEAD_NO) - if(self.owner.lastrocket) + if(self.realowner.deadflag == DEAD_NO) + if(self.realowner.lastrocket) { if((self.spawnshieldtime >= 0) ? (time >= self.spawnshieldtime) // timer - : (vlen(NearestPointOnBox(self.owner, self.origin) - self.origin) > autocvar_g_balance_rocketlauncher_remote_radius) // safety device + : (vlen(NearestPointOnBox(self.realowner, self.origin) - self.origin) > autocvar_g_balance_rocketlauncher_remote_radius) // safety device ) { W_Rocket_DoRemoteExplode(); @@ -174,14 +175,14 @@ void W_Rocket_Think (void) self.velocity = self.velocity + v_forward * min(autocvar_g_balance_rocketlauncher_speedaccel * g_weaponspeedfactor * frametime, velspeed); // laser guided, or remote detonation - if (self.owner.weapon == WEP_ROCKET_LAUNCHER) + if (self.realowner.weapon == WEP_ROCKET_LAUNCHER) { - if(self == self.owner.lastrocket) - if not(self.owner.rl_release) + if(self == self.realowner.lastrocket) + if not(self.realowner.rl_release) if not(self.BUTTON_ATCK2) if(autocvar_g_balance_rocketlauncher_guiderate) if(time > self.pushltime) - if(self.owner.deadflag == DEAD_NO) + if(self.realowner.deadflag == DEAD_NO) { f = autocvar_g_balance_rocketlauncher_guideratedelay; if(f) @@ -191,9 +192,9 @@ void W_Rocket_Think (void) velspeed = vlen(self.velocity); - makevectors(self.owner.v_angle); - desireddir = WarpZone_RefSys_TransformVelocity(self.owner, self, v_forward); - desiredorigin = WarpZone_RefSys_TransformOrigin(self.owner, self, self.owner.origin + self.owner.view_ofs); + makevectors(self.realowner.v_angle); + desireddir = WarpZone_RefSys_TransformVelocity(self.realowner, self, v_forward); + desiredorigin = WarpZone_RefSys_TransformOrigin(self.realowner, self, self.realowner.origin + self.realowner.view_ofs); olddir = normalize(self.velocity); // now it gets tricky... we want to move like some curve to approximate the target direction @@ -208,7 +209,7 @@ void W_Rocket_Think (void) { pointparticles(particleeffectnum("rocket_guide"), self.origin, self.velocity, 1); // TODO add a better sound here - sound (self.owner, CHAN_WEAPON2, "weapons/rocket_mode.wav", VOL_BASE, ATTN_NORM); + sound (self.realowner, CH_WEAPON_B, "weapons/rocket_mode.wav", VOL_BASE, ATTN_NORM); self.count = 1; } } @@ -237,25 +238,29 @@ void W_Rocket_Damage (entity inflictor, entity attacker, float damage, float dea { if (self.health <= 0) return; + + if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions + return; // g_projectiles_damage says to halt + self.health = self.health - damage; self.angles = vectoangles(self.velocity); + if (self.health <= 0) W_PrepareExplosionByDamage(attacker, W_Rocket_Explode); } void W_Rocket_Attack (void) { - local entity missile; - local entity flash; + entity missile; + entity flash; - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_rockets = self.ammo_rockets - autocvar_g_balance_rocketlauncher_ammo; + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_rocketlauncher_ammo, autocvar_g_balance_rocketlauncher_reload_ammo); - W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 5, "weapons/rocket_fire.wav", CHAN_WEAPON, autocvar_g_balance_rocketlauncher_damage); + W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 5, "weapons/rocket_fire.wav", CH_WEAPON_A, autocvar_g_balance_rocketlauncher_damage); pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); missile = WarpZone_RefSys_SpawnSameRefSys(self); - missile.owner = self; + missile.owner = missile.realowner = self; self.lastrocket = missile; if(autocvar_g_balance_rocketlauncher_detonatedelay >= 0) missile.spawnshieldtime = time + autocvar_g_balance_rocketlauncher_detonatedelay; @@ -270,6 +275,7 @@ void W_Rocket_Attack (void) missile.damageforcescale = autocvar_g_balance_rocketlauncher_damageforcescale; missile.health = autocvar_g_balance_rocketlauncher_health; missile.event_damage = W_Rocket_Damage; + missile.damagedbycontents = TRUE; missile.movetype = MOVETYPE_FLY; PROJECTILE_MAKETRIGGER(missile); @@ -305,6 +311,8 @@ float w_rlauncher(float req) { entity rock; float rockfound; + float ammo_amount; + if (req == WR_AIM) { // aim and decide to fire if appropriate @@ -312,9 +320,9 @@ float w_rlauncher(float req) if(skill >= 2) // skill 0 and 1 bots won't detonate rockets! { // decide whether to detonate rockets - local entity missile, targetlist, targ; - local float edgedamage, coredamage, edgeradius, recipricoledgeradius, d; - local float selfdamage, teamdamage, enemydamage; + entity missile, targetlist, targ; + float edgedamage, coredamage, edgeradius, recipricoledgeradius, d; + float selfdamage, teamdamage, enemydamage; edgedamage = autocvar_g_balance_rocketlauncher_edgedamage; coredamage = autocvar_g_balance_rocketlauncher_damage; edgeradius = autocvar_g_balance_rocketlauncher_radius; @@ -326,7 +334,7 @@ float w_rlauncher(float req) missile = find(world, classname, "rocket"); while (missile) { - if (missile.owner != self) + if (missile.realowner != self) { missile = find(missile, classname, "rocket"); continue; @@ -339,7 +347,7 @@ float w_rlauncher(float req) // count potential damage according to type of target if (targ == self) selfdamage = selfdamage + d; - else if (targ.team == self.team && teams_matter) + else if (targ.team == self.team && teamplay) teamdamage = teamdamage + d; else if (bot_shouldattack(targ)) enemydamage = enemydamage + d; @@ -347,17 +355,17 @@ float w_rlauncher(float req) } missile = find(missile, classname, "rocket"); } - local float desirabledamage; + float desirabledamage; desirabledamage = enemydamage; if (time > self.invincible_finished && time > self.spawnshieldtime) desirabledamage = desirabledamage - selfdamage * autocvar_g_balance_selfdamagepercent; - if (teams_matter && self.team) + if (teamplay && self.team) desirabledamage = desirabledamage - teamdamage; missile = find(world, classname, "rocket"); while (missile) { - if (missile.owner != self) + if (missile.realowner != self) { missile = find(missile, classname, "rocket"); continue; @@ -376,7 +384,7 @@ float w_rlauncher(float req) targ = targ.chain; } }else{ - local float distance; distance= bound(300,vlen(self.origin-self.enemy.origin),30000); + float distance; distance= bound(300,vlen(self.origin-self.enemy.origin),30000); //As the distance gets larger, a correct detonation gets near imposible //Bots are assumed to use the rocket spawnfunc_light to see if the rocket gets near a player if(v_forward * normalize(missile.origin - self.enemy.origin)< 0.1) @@ -402,32 +410,37 @@ float w_rlauncher(float req) } else if (req == WR_THINK) { - if (self.BUTTON_ATCK) + if(autocvar_g_balance_rocketlauncher_reload_ammo && self.clip_load < autocvar_g_balance_rocketlauncher_ammo) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else { - if(self.rl_release || autocvar_g_balance_rocketlauncher_guidestop) - if(weapon_prepareattack(0, autocvar_g_balance_rocketlauncher_refire)) + if (self.BUTTON_ATCK) { - W_Rocket_Attack(); - weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_rocketlauncher_animtime, w_ready); - self.rl_release = 0; + if(self.rl_release || autocvar_g_balance_rocketlauncher_guidestop) + if(weapon_prepareattack(0, autocvar_g_balance_rocketlauncher_refire)) + { + W_Rocket_Attack(); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_rocketlauncher_animtime, w_ready); + self.rl_release = 0; + } } - } - else - self.rl_release = 1; + else + self.rl_release = 1; - if (self.BUTTON_ATCK2) - { - rockfound = 0; - for(rock = world; (rock = find(rock, classname, "rocket")); ) if(rock.owner == self) + if (self.BUTTON_ATCK2) { - if(!rock.rl_detonate_later) + rockfound = 0; + for(rock = world; (rock = find(rock, classname, "rocket")); ) if(rock.realowner == self) { - rock.rl_detonate_later = TRUE; - rockfound = 1; + if(!rock.rl_detonate_later) + { + rock.rl_detonate_later = TRUE; + rockfound = 1; + } } + if(rockfound) + sound (self, CH_WEAPON_B, "weapons/rocket_det.wav", VOL_BASE, ATTN_NORM); } - if(rockfound) - sound (self, CHAN_WEAPON2, "weapons/rocket_det.wav", VOL_BASE, ATTN_NORM); } } else if (req == WR_PRECACHE) @@ -439,18 +452,28 @@ float w_rlauncher(float req) precache_sound ("weapons/rocket_det.wav"); precache_sound ("weapons/rocket_fire.wav"); precache_sound ("weapons/rocket_mode.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else } else if (req == WR_SETUP) { weapon_setup(WEP_ROCKET_LAUNCHER); + self.current_ammo = ammo_rockets; self.rl_release = 1; } else if (req == WR_CHECKAMMO1) { // don't switch while guiding a missile - if ((ATTACK_FINISHED(self) <= time || self.weapon != WEP_ROCKET_LAUNCHER) - && self.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo) - return FALSE; + if (ATTACK_FINISHED(self) <= time || self.weapon != WEP_ROCKET_LAUNCHER) + { + if(autocvar_g_balance_rocketlauncher_reload_ammo) + { + if(self.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo && self.(weapon_load[WEP_ROCKET_LAUNCHER]) < autocvar_g_balance_rocketlauncher_ammo) + ammo_amount = TRUE; + } + else if(self.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo) + ammo_amount = TRUE; + return !ammo_amount; + } } else if (req == WR_CHECKAMMO2) return FALSE; @@ -458,8 +481,12 @@ float w_rlauncher(float req) { self.rl_release = 0; } + else if (req == WR_RELOAD) + { + W_Reload(autocvar_g_balance_rocketlauncher_ammo, autocvar_g_balance_rocketlauncher_reload_ammo, autocvar_g_balance_rocketlauncher_reload_time, "weapons/reload.wav"); + } return TRUE; -}; +} #endif #ifdef CSQC float w_rlauncher(float req) @@ -470,22 +497,22 @@ float w_rlauncher(float req) org2 = w_org + w_backoff * 12; pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1); if(!w_issilent) - sound(self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); } else if(req == WR_PRECACHE) { precache_sound("weapons/rocket_impact.wav"); } else if (req == WR_SUICIDEMESSAGE) - w_deathtypestring = "%s exploded"; + w_deathtypestring = _("%s blew themself up with their rocketlauncher"); else if (req == WR_KILLMESSAGE) { if(w_deathtype & HITTYPE_BOUNCE) // (remote detonation) - w_deathtypestring = "%s got too close to %s's rocket"; + w_deathtypestring = _("%s got too close to %s's rocket"); else if(w_deathtype & HITTYPE_SPLASH) - w_deathtypestring = "%s almost dodged %s's rocket"; + w_deathtypestring = _("%s almost dodged %s's rocket"); else - w_deathtypestring = "%s ate %s's rocket"; + w_deathtypestring = _("%s ate %s's rocket"); } return TRUE; } diff --git a/qcsrc/server/w_seeker.qc b/qcsrc/server/w_seeker.qc index eb64dddd80..c4c08bb512 100644 --- a/qcsrc/server/w_seeker.qc +++ b/qcsrc/server/w_seeker.qc @@ -1,14 +1,19 @@ #ifdef REGISTER_WEAPON -REGISTER_WEAPON(SEEKER, w_seeker, IT_ROCKETS, 9, WEP_FLAG_NORMAL | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_MID, "seeker", "seeker", "T.A.G. Seeker"); +REGISTER_WEAPON(SEEKER, w_seeker, IT_ROCKETS, 8, WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_MID, "seeker", "seeker", _("T.A.G. Seeker")) #else #ifdef SVQC //.float proxytime; = autoswitch //.float tl; = wait +.entity tag_target, wps_tag_tracker; +.float tag_time; +// ============================ +// Begin: Missile functions, these are general functions to be manipulated by other code +// ============================ void Seeker_Missile_Explode () { self.event_damage = SUB_Null; - RadiusDamage (self, self.owner, autocvar_g_balance_seeker_missile_damage, autocvar_g_balance_seeker_missile_edgedamage, autocvar_g_balance_seeker_missile_radius, world, autocvar_g_balance_seeker_missile_force, self.projectiledeathtype, other); + RadiusDamage (self, self.realowner, autocvar_g_balance_seeker_missile_damage, autocvar_g_balance_seeker_missile_edgedamage, autocvar_g_balance_seeker_missile_radius, world, autocvar_g_balance_seeker_missile_force, self.projectiledeathtype, other); remove (self); } @@ -119,8 +124,11 @@ void Seeker_Missile_Damage (entity inflictor, entity attacker, float damage, flo { if (self.health <= 0) return; + + if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions + return; // g_projectiles_damage says to halt - if (self.owner == attacker) + if (self.realowner == attacker) self.health = self.health - (damage * 0.25); else self.health = self.health - damage; @@ -154,22 +162,21 @@ void Seeker_Missile_Animate() } */ -void Seeker_Fire_Missile(vector f_diff) +void Seeker_Fire_Missile(vector f_diff, entity m_target) { - local entity missile; + entity missile; - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_rockets = self.ammo_rockets - autocvar_g_balance_seeker_missile_ammo; + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_seeker_missile_ammo, autocvar_g_balance_seeker_reload_ammo); makevectors(self.v_angle); - W_SetupShot_ProjectileSize (self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/seeker_fire.wav", CHAN_WEAPON, 0); + W_SetupShot_ProjectileSize (self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/seeker_fire.wav", CH_WEAPON_A, 0); w_shotorg += f_diff; pointparticles(particleeffectnum("seeker_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); //self.detornator = FALSE; missile = spawn(); - missile.owner = self; + missile.owner = missile.realowner = self; missile.classname = "seeker_missile"; missile.bot_dodge = TRUE; missile.bot_dodgerating = autocvar_g_balance_seeker_missile_damage; @@ -179,14 +186,19 @@ void Seeker_Fire_Missile(vector f_diff) missile.event_damage = Seeker_Missile_Damage; missile.nextthink = time;// + 0.2;// + cvar("g_balance_seeker_missile_activate_delay"); missile.cnt = time + autocvar_g_balance_seeker_missile_lifetime; - missile.enemy = self.enemy; + missile.enemy = m_target; missile.solid = SOLID_BBOX; missile.scale = 2; missile.takedamage = DAMAGE_YES; missile.health = autocvar_g_balance_seeker_missile_health; missile.damageforcescale = autocvar_g_balance_seeker_missile_damageforcescale; - missile.projectiledeathtype = WEP_SEEKER; + missile.damagedbycontents = TRUE; //missile.think = Seeker_Missile_Animate; // csqc projectiles. + + if (missile.enemy != world) + missile.projectiledeathtype = WEP_SEEKER | HITTYPE_SECONDARY; + else + missile.projectiledeathtype = WEP_SEEKER; setorigin (missile, w_shotorg); @@ -202,41 +214,153 @@ void Seeker_Fire_Missile(vector f_diff) other = missile; MUTATOR_CALLHOOK(EditProjectile); } -void Seeker_Vollycontroler_Think() +// ============================ +// Begin: FLAC, close range attack meant for defeating rockets which are coming at you. +// ============================ +void Seeker_Flac_Explode () +{ + self.event_damage = SUB_Null; + + RadiusDamage (self, self.realowner, autocvar_g_balance_seeker_flac_damage, autocvar_g_balance_seeker_flac_edgedamage, autocvar_g_balance_seeker_flac_radius, world, autocvar_g_balance_seeker_flac_force, self.projectiledeathtype, other); + + remove (self); +} + +void Seeker_Flac_Touch() +{ + PROJECTILE_TOUCH; + + Seeker_Flac_Explode(); +} + +void Seeker_Fire_Flac() +{ + entity missile; + vector f_diff; + float c; + + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_seeker_flac_ammo, autocvar_g_balance_seeker_reload_ammo); + + c = mod(self.bulletcounter, 4); + switch(c) + { + case 0: + f_diff = '-1.25 -3.75 0'; + break; + case 1: + f_diff = '+1.25 -3.75 0'; + break; + case 2: + f_diff = '-1.25 +3.75 0'; + break; + case 3: + default: + f_diff = '+1.25 +3.75 0'; + break; + } + W_SetupShot_ProjectileSize (self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/flac_fire.wav", CH_WEAPON_A, autocvar_g_balance_seeker_flac_damage); + w_shotorg += f_diff; + + pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); + + missile = spawn (); + missile.owner = missile.realowner = self; + missile.classname = "missile"; + missile.bot_dodge = TRUE; + missile.bot_dodgerating = autocvar_g_balance_seeker_flac_damage; + missile.touch = Seeker_Flac_Explode; + missile.use = Seeker_Flac_Explode; + missile.think = adaptor_think2use_hittype_splash; + missile.nextthink = time + autocvar_g_balance_seeker_flac_lifetime + autocvar_g_balance_seeker_flac_lifetime_rand; + missile.solid = SOLID_BBOX; + missile.movetype = MOVETYPE_FLY; + missile.projectiledeathtype = WEP_SEEKER; + missile.projectiledeathtype = WEP_SEEKER | HITTYPE_SECONDARY; + missile.flags = FL_PROJECTILE; + + // csqc projectiles + //missile.angles = vectoangles (missile.velocity); + //missile.scale = 0.4; // BUG: the model is too big + + setorigin (missile, w_shotorg); + setsize (missile, '-2 -2 -2', '2 2 2'); + + W_SETUPPROJECTILEVELOCITY_UP(missile, g_balance_seeker_flac); + CSQCProjectile(missile, TRUE, PROJECTILE_FLAC, TRUE); + + other = missile; MUTATOR_CALLHOOK(EditProjectile); +} + +// ============================ +// Begin: Tag and rocket controllers +// ============================ +entity Seeker_Tagged_Info(entity isowner, entity istarget) +{ + entity tag; + for(tag = world; (tag = find(tag, classname, "tag_tracker")); ) + if ((tag.realowner == isowner) && (tag.tag_target == istarget)) + return tag; + + return world; +} + +void Seeker_Attack() +{ + entity tracker, closest_target; + + for(tracker = world; (tracker = find(tracker, classname, "tag_tracker")); ) if (tracker.realowner == self) + { + if (closest_target) + { + if (vlen(self.origin - tracker.tag_target.origin) < vlen(self.origin - closest_target.origin)) + closest_target = tracker.tag_target; + } + else + closest_target = tracker.tag_target; + } + + traceline(self.origin + self.view_ofs, closest_target.origin, MOVE_NOMONSTERS, self); + if ((!closest_target) || ((trace_fraction < 1) && (trace_ent != closest_target))) + closest_target = world; + + Seeker_Fire_Missile('0 0 0', closest_target); +} + +void Seeker_Vollycontroller_Think() // TODO: Merge this with Seeker_Attack { float c; entity oldself,oldenemy; self.cnt = self.cnt - 1; - if((!(self.owner.items & IT_UNLIMITED_AMMO) && self.owner.ammo_rockets < autocvar_g_balance_seeker_missile_ammo) || (self.cnt <= -1) || (self.owner.deadflag != DEAD_NO) || (self.owner.switchweapon != WEP_SEEKER)) + if((!(self.realowner.items & IT_UNLIMITED_AMMO) && self.realowner.ammo_rockets < autocvar_g_balance_seeker_missile_ammo) || (self.cnt <= -1) || (self.realowner.deadflag != DEAD_NO) || (self.realowner.switchweapon != WEP_SEEKER)) { remove(self); return; } - self.nextthink = time + autocvar_g_balance_seeker_missile_delay; - + self.nextthink = time + autocvar_g_balance_seeker_missile_delay * W_WeaponRateFactor(); + oldself = self; - self = self.owner; - + self = self.realowner; + oldenemy = self.enemy; self.enemy = oldself.enemy; - - c = mod(oldself.cnt, 4); + + c = mod(self.cnt, 4); switch(c) { case 0: - Seeker_Fire_Missile('-1.25 -3.75 0'); + Seeker_Fire_Missile('-1.25 -3.75 0', self.enemy); break; case 1: - Seeker_Fire_Missile('+1.25 -3.75 0'); + Seeker_Fire_Missile('+1.25 -3.75 0', self.enemy); break; case 2: - Seeker_Fire_Missile('-1.25 +3.75 0'); + Seeker_Fire_Missile('-1.25 +3.75 0', self.enemy); break; case 3: default: - Seeker_Fire_Missile('+1.25 +3.75 0'); + Seeker_Fire_Missile('+1.25 +3.75 0', self.enemy); break; } @@ -244,9 +368,30 @@ void Seeker_Vollycontroler_Think() self = oldself; } +void Seeker_Tracker_Think() +{ + // commit suicide if: You die OR target dies OR you switch away from the seeker OR commit suicide if lifetime is up + if ((self.realowner.deadflag != DEAD_NO) || (self.tag_target.deadflag != DEAD_NO) || (self.realowner.switchweapon != WEP_SEEKER) + || (time > self.tag_time + autocvar_g_balance_seeker_tag_tracker_lifetime)) + { + if (self) + { + WaypointSprite_Kill(self.tag_target.wps_tag_tracker); + remove(self); + } + return; + } + + // Update the think method information + self.nextthink = time; +} + +// ============================ +// Begin: Tag projectile +// ============================ void Seeker_Tag_Explode () { - //if(other==self.owner) + //if(other==self.realowner) // return; Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER | HITTYPE_BOUNCE, self); @@ -262,14 +407,15 @@ void Seeker_Tag_Damage (entity inflictor, entity attacker, float damage, float d Seeker_Tag_Explode(); } - void Seeker_Tag_Touch() { vector dir; vector org2; entity e; - dir = normalize (self.owner.origin - self.origin); + PROJECTILE_TOUCH; + + dir = normalize (self.realowner.origin - self.origin); org2 = findbetterlocation (self.origin, 8); te_knightspike(org2); @@ -278,13 +424,46 @@ void Seeker_Tag_Touch() Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER | HITTYPE_HEADSHOT, self); if (other.takedamage == DAMAGE_AIM && other.deadflag == DEAD_NO) - { - e = spawn(); - e.cnt = autocvar_g_balance_seeker_missile_count; - e.owner = self.owner; - e.enemy = other; - e.think = Seeker_Vollycontroler_Think; - e.nextthink = time; + { + // check to see if this person is already tagged by me + entity tag = Seeker_Tagged_Info(self.realowner, other); + + if (tag != world) + { + if (other.wps_tag_tracker && (autocvar_g_balance_seeker_type == 1)) // don't attach another waypointsprite without killing the old one first + WaypointSprite_Kill(other.wps_tag_tracker); + + tag.tag_time = time; + } + else + { + //sprint(self.realowner, strcat("You just tagged ^2", other.netname, "^7 with a tracking device!\n")); + e = spawn(); + e.cnt = autocvar_g_balance_seeker_missile_count; + e.classname = "tag_tracker"; + e.owner = self.owner; + e.realowner = self.realowner; + + if (autocvar_g_balance_seeker_type == 1) + { + e.tag_target = other; + e.tag_time = time; + e.think = Seeker_Tracker_Think; + } + else + { + e.enemy = other; + e.think = Seeker_Vollycontroller_Think; + } + + e.nextthink = time; + } + + if (autocvar_g_balance_seeker_type == 1) + { + WaypointSprite_Spawn("tagged-target", autocvar_g_balance_seeker_tag_tracker_lifetime, 0, other, '0 0 64', self.realowner, 0, other, wps_tag_tracker, TRUE, RADARICON_TAGGED, '0.5 1 0'); + WaypointSprite_UpdateRule(other.wps_tag_tracker, 0, SPRITERULE_DEFAULT); + } } remove(self); @@ -293,14 +472,13 @@ void Seeker_Tag_Touch() void Seeker_Fire_Tag() { - local entity missile; - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_rockets = self.ammo_rockets - autocvar_g_balance_seeker_tag_ammo; + entity missile; + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_seeker_tag_ammo, autocvar_g_balance_seeker_reload_ammo); - W_SetupShot_ProjectileSize (self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/tag_fire.wav", CHAN_WEAPON, autocvar_g_balance_seeker_missile_damage * autocvar_g_balance_seeker_missile_count); + W_SetupShot_ProjectileSize (self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/tag_fire.wav", CH_WEAPON_A, autocvar_g_balance_seeker_missile_damage * autocvar_g_balance_seeker_missile_count); missile = spawn(); - missile.owner = self; + missile.owner = missile.realowner = self; missile.classname = "seeker_tag"; missile.bot_dodge = TRUE; missile.bot_dodgerating = 50; @@ -309,7 +487,6 @@ void Seeker_Fire_Tag() missile.nextthink = time + autocvar_g_balance_seeker_tag_lifetime; missile.movetype = MOVETYPE_FLY; missile.solid = SOLID_BBOX; - missile.owner = self; missile.takedamage = DAMAGE_YES; missile.event_damage = Seeker_Tag_Explode; @@ -330,82 +507,9 @@ void Seeker_Fire_Tag() other = missile; MUTATOR_CALLHOOK(EditProjectile); } - -void Seeker_Flac_Explode () -{ - self.event_damage = SUB_Null; - - RadiusDamage (self, self.owner, autocvar_g_balance_seeker_flac_damage, autocvar_g_balance_seeker_flac_edgedamage, autocvar_g_balance_seeker_flac_radius, world, autocvar_g_balance_seeker_flac_force, self.projectiledeathtype, other); - - remove (self); -} - -void Seeker_Flac_Touch() -{ - PROJECTILE_TOUCH; - - Seeker_Flac_Explode(); -} - -void Seeker_Fire_Flac() -{ - local entity missile; - vector f_diff; - float c; - - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_rockets = self.ammo_rockets - autocvar_g_balance_seeker_flac_ammo; - - c = mod(self.bulletcounter, 4); - switch(c) - { - case 0: - f_diff = '-1.25 -3.75 0'; - break; - case 1: - f_diff = '+1.25 -3.75 0'; - break; - case 2: - f_diff = '-1.25 +3.75 0'; - break; - case 3: - default: - f_diff = '+1.25 +3.75 0'; - break; - } - W_SetupShot_ProjectileSize (self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/flac_fire.wav", CHAN_WEAPON, autocvar_g_balance_seeker_flac_damage); - w_shotorg += f_diff; - - pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - missile = spawn (); - missile.owner = missile.realowner = self; - missile.classname = "missile"; - missile.bot_dodge = TRUE; - missile.bot_dodgerating = autocvar_g_balance_seeker_flac_damage; - missile.touch = Seeker_Flac_Explode; - missile.use = Seeker_Flac_Explode; - missile.think = adaptor_think2use_hittype_splash; - missile.nextthink = time + autocvar_g_balance_seeker_flac_lifetime + autocvar_g_balance_seeker_flac_lifetime_rand; - missile.solid = SOLID_BBOX; - missile.movetype = MOVETYPE_FLY; - missile.projectiledeathtype = WEP_SEEKER; - missile.projectiledeathtype = WEP_SEEKER | HITTYPE_SECONDARY; - missile.flags = FL_PROJECTILE; - - // csqc projectiles - //missile.angles = vectoangles (missile.velocity); - //missile.scale = 0.4; // BUG: the model is too big - - setorigin (missile, w_shotorg); - setsize (missile, '-2 -2 -2', '2 2 2'); - - W_SETUPPROJECTILEVELOCITY_UP(missile, g_balance_seeker_flac); - CSQCProjectile(missile, TRUE, PROJECTILE_FLAC, TRUE); - - other = missile; MUTATOR_CALLHOOK(EditProjectile); -} - +// ============================ +// Begin: Genereal weapon functions +// ============================ void spawnfunc_weapon_seeker (void) { weapon_defaultspawnfunc(WEP_SEEKER); @@ -413,25 +517,62 @@ void spawnfunc_weapon_seeker (void) float w_seeker(float req) { - if (req == WR_AIM) - self.BUTTON_ATCK = bot_aim(autocvar_g_balance_seeker_tag_speed, 0, 20, FALSE); + float ammo_amount; + if (req == WR_AIM) + { + if (autocvar_g_balance_seeker_type == 1) + if (Seeker_Tagged_Info(self, self.enemy) != world) + self.BUTTON_ATCK = bot_aim(autocvar_g_balance_seeker_missile_speed_max, 0, autocvar_g_balance_seeker_missile_lifetime, FALSE); + else + self.BUTTON_ATCK2 = bot_aim(autocvar_g_balance_seeker_tag_speed, 0, autocvar_g_balance_seeker_tag_lifetime, FALSE); + else + self.BUTTON_ATCK = bot_aim(autocvar_g_balance_seeker_tag_speed, 0, autocvar_g_balance_seeker_tag_lifetime, FALSE); + } else if (req == WR_THINK) { - if (self.BUTTON_ATCK) - if (weapon_prepareattack(0, autocvar_g_balance_seeker_tag_refire)) + if(autocvar_g_balance_seeker_reload_ammo && self.clip_load < min(autocvar_g_balance_seeker_missile_ammo, autocvar_g_balance_seeker_tag_ammo)) // forced reload + weapon_action(self.weapon, WR_RELOAD); + + else if (self.BUTTON_ATCK) + { + if (autocvar_g_balance_seeker_type == 1) { - Seeker_Fire_Tag(); - weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_seeker_tag_animtime, w_ready); + if (weapon_prepareattack(0, autocvar_g_balance_seeker_missile_refire)) + { + Seeker_Attack(); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_seeker_missile_animtime, w_ready); + } } - - if (self.BUTTON_ATCK2) - if (weapon_prepareattack(1, autocvar_g_balance_seeker_flac_refire)) + else { - Seeker_Fire_Flac(); - weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_seeker_flac_animtime, w_ready); + if (weapon_prepareattack(0, autocvar_g_balance_seeker_tag_refire)) + { + Seeker_Fire_Tag(); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_seeker_tag_animtime, w_ready); + } } + } + else if (self.BUTTON_ATCK2) + { + if (autocvar_g_balance_seeker_type == 1) + { + if (weapon_prepareattack(0, autocvar_g_balance_seeker_tag_refire)) + { + Seeker_Fire_Tag(); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_seeker_tag_animtime, w_ready); + } + } + else + { + if (weapon_prepareattack(0, autocvar_g_balance_seeker_flac_refire)) + { + Seeker_Fire_Flac(); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_seeker_flac_animtime, w_ready); + } + } + } } else if (req == WR_PRECACHE) { @@ -441,15 +582,31 @@ float w_seeker(float req) precache_sound ("weapons/tag_fire.wav"); precache_sound ("weapons/flac_fire.wav"); precache_sound ("weapons/seeker_fire.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else } else if (req == WR_SETUP) + { weapon_setup(WEP_SEEKER); + self.current_ammo = ammo_rockets; + } else if (req == WR_CHECKAMMO1) - return self.ammo_rockets >= autocvar_g_balance_seeker_tag_ammo + autocvar_g_balance_seeker_missile_ammo; + { + ammo_amount = self.ammo_rockets >= autocvar_g_balance_seeker_missile_ammo; + ammo_amount += self.(weapon_load[WEP_SEEKER]) >= autocvar_g_balance_seeker_missile_ammo; + return ammo_amount; + } else if (req == WR_CHECKAMMO2) - return self.ammo_rockets >= autocvar_g_balance_seeker_flac_ammo; + { + ammo_amount = self.ammo_rockets >= autocvar_g_balance_seeker_tag_ammo; + ammo_amount += self.(weapon_load[WEP_SEEKER]) >= autocvar_g_balance_seeker_tag_ammo; + return ammo_amount; + } + else if (req == WR_RELOAD) + { + W_Reload(min(autocvar_g_balance_seeker_missile_ammo, autocvar_g_balance_seeker_tag_ammo), autocvar_g_balance_seeker_reload_ammo, autocvar_g_balance_seeker_reload_time, "weapons/reload.wav"); + } return TRUE; -}; +} #endif #ifdef CSQC float w_seeker(float req) @@ -458,59 +615,40 @@ float w_seeker(float req) { vector org2; org2 = w_org + w_backoff * 6; - if(w_deathtype & HITTYPE_SECONDARY) + if(w_deathtype & HITTYPE_BOUNCE) { - pointparticles(particleeffectnum("flac_explode"), org2, '0 0 0', 1); + pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1); if(!w_issilent) { if (w_random<0.15) - sound(self, CHAN_PROJECTILE, "weapons/flacexp1.wav", 1, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/tagexp1.wav", 1, ATTN_NORM); else if (w_random<0.7) - sound(self, CHAN_PROJECTILE, "weapons/flacexp2.wav", 1, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/tagexp2.wav", 1, ATTN_NORM); else - sound(self, CHAN_PROJECTILE, "weapons/flacexp3.wav", 1, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/tagexp3.wav", 1, ATTN_NORM); } } + else if(w_deathtype & HITTYPE_HEADSHOT) + { + if(!w_issilent) + sound(self, CH_SHOTS, "weapons/tag_impact.wav", 1, ATTN_NORM); + } else { - if(w_deathtype & HITTYPE_BOUNCE) - { - pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1); - if(!w_issilent) - { - if (w_random<0.15) - sound(self, CHAN_PROJECTILE, "weapons/tagexp1.wav", 1, ATTN_NORM); - else if (w_random<0.7) - sound(self, CHAN_PROJECTILE, "weapons/tagexp2.wav", 1, ATTN_NORM); - else - sound(self, CHAN_PROJECTILE, "weapons/tagexp3.wav", 1, ATTN_NORM); - } - } - else if(w_deathtype & HITTYPE_HEADSHOT) - { - if(!w_issilent) - sound(self, CHAN_PROJECTILE, "weapons/tag_impact.wav", 1, ATTN_NORM); - } - else + pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1); + if(!w_issilent) { - pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1); - if(!w_issilent) - { - if (w_random<0.15) - sound(self, CHAN_PROJECTILE, "weapons/seekerexp1.wav", 1, ATTN_NORM); - else if (w_random<0.7) - sound(self, CHAN_PROJECTILE, "weapons/seekerexp2.wav", 1, ATTN_NORM); - else - sound(self, CHAN_PROJECTILE, "weapons/seekerexp3.wav", 1, ATTN_NORM); - } + if (w_random<0.15) + sound(self, CH_SHOTS, "weapons/seekerexp1.wav", 1, ATTN_NORM); + else if (w_random<0.7) + sound(self, CH_SHOTS, "weapons/seekerexp2.wav", 1, ATTN_NORM); + else + sound(self, CH_SHOTS, "weapons/seekerexp3.wav", 1, ATTN_NORM); } } } else if(req == WR_PRECACHE) { - precache_sound("weapons/flacexp1.wav"); - precache_sound("weapons/flacexp2.wav"); - precache_sound("weapons/flacexp3.wav"); precache_sound("weapons/seekerexp1.wav"); precache_sound("weapons/seekerexp2.wav"); precache_sound("weapons/seekerexp3.wav"); @@ -520,13 +658,13 @@ float w_seeker(float req) precache_sound("weapons/tag_impact.wav"); } else if (req == WR_SUICIDEMESSAGE) - w_deathtypestring = "%s played with tiny rockets"; + w_deathtypestring = _("%s played with tiny seeker rockets"); else if (req == WR_KILLMESSAGE) { if(w_deathtype & HITTYPE_SECONDARY) - w_deathtypestring = "%s ran into %s's flac"; + w_deathtypestring = _("%s was tagged with a seeker by %s"); else - w_deathtypestring = "%s was tagged by %s"; + w_deathtypestring = _("%s was pummeled with seeker rockets by %s"); } return TRUE; } diff --git a/qcsrc/server/w_shotgun.qc b/qcsrc/server/w_shotgun.qc index 08c4a901e1..fcf9a27c27 100644 --- a/qcsrc/server/w_shotgun.qc +++ b/qcsrc/server/w_shotgun.qc @@ -1,7 +1,8 @@ #ifdef REGISTER_WEAPON -REGISTER_WEAPON(SHOTGUN, w_shotgun, IT_SHELLS, 2, WEP_FLAG_NORMAL | WEP_TYPE_HITSCAN, BOT_PICKUP_RATING_LOW, "shotgun", "shotgun", "Shotgun"); +REGISTER_WEAPON(SHOTGUN, w_shotgun, IT_SHELLS, 2, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN, BOT_PICKUP_RATING_LOW, "shotgun", "shotgun", _("Shotgun")) #else #ifdef SVQC + void W_Shotgun_Attack (void) { float sc; @@ -12,7 +13,7 @@ void W_Shotgun_Attack (void) float spread; float bulletspeed; float bulletconstant; - local entity flash; + entity flash; ammoamount = autocvar_g_balance_shotgun_primary_ammo; bullets = autocvar_g_balance_shotgun_primary_bullets; @@ -22,12 +23,12 @@ void W_Shotgun_Attack (void) bulletspeed = autocvar_g_balance_shotgun_primary_speed; bulletconstant = autocvar_g_balance_shotgun_primary_bulletconstant; - W_SetupShot (self, autocvar_g_antilag_bullets && bulletspeed >= autocvar_g_antilag_bullets, 5, "weapons/shotgun_fire.wav", CHAN_WEAPON, d * bullets); + W_DecreaseAmmo(ammo_shells, ammoamount, autocvar_g_balance_shotgun_reload_ammo); + + W_SetupShot (self, autocvar_g_antilag_bullets && bulletspeed >= autocvar_g_antilag_bullets, 5, "weapons/shotgun_fire.wav", CH_WEAPON_A, d * bullets); for (sc = 0;sc < bullets;sc = sc + 1) fireBallisticBullet(w_shotorg, w_shotdir, spread, bulletspeed, 5, d, 0, f, WEP_SHOTGUN, 0, 1, bulletconstant); endFireBallisticBullet(); - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_shells = self.ammo_shells - ammoamount; pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 1000, autocvar_g_balance_shotgun_primary_ammo); @@ -43,53 +44,116 @@ void W_Shotgun_Attack (void) flash.nextthink = time + 0.06; flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION; W_AttachToShotorg(flash, '5 0 0'); - } +.float swing_prev; +.entity swing_alreadyhit; void shotgun_meleethink (void) { - // store time when we started swinging down inside self.cnt - if(!self.cnt) - self.cnt = time; - - makevectors(self.owner.v_angle); - vector angle; - angle = v_forward; - - // perform trace - float f; - f = (self.cnt + autocvar_g_balance_shotgun_secondary_melee_time - time) / autocvar_g_balance_shotgun_secondary_melee_time * 2 - 1; + // declarations + float i, f, swing, swing_factor, swing_damage, meleetime, is_player; + entity target_victim; vector targpos; - targpos = self.owner.origin + self.owner.view_ofs + angle * autocvar_g_balance_shotgun_secondary_melee_range + v_right * f * autocvar_g_balance_shotgun_secondary_melee_swing + v_up * f * autocvar_g_balance_shotgun_secondary_melee_swing; - WarpZone_traceline_antilag(self.owner, self.owner.origin + self.owner.view_ofs, targpos, FALSE, self.owner, ANTILAG_LATENCY(self.owner)); + if(!self.cnt) // set start time of melee + { + self.cnt = time; + W_PlayStrengthSound(self.realowner); + } - // apply the damage, also remove self - if(trace_fraction < 1 && trace_ent.takedamage == DAMAGE_AIM && (trace_ent.classname == "player" || trace_ent.classname == "body")) + makevectors(self.realowner.v_angle); // update values for v_* vectors + + // calculate swing percentage based on time + meleetime = autocvar_g_balance_shotgun_secondary_melee_time * W_WeaponRateFactor(); + swing = bound(0, (self.cnt + meleetime - time) / meleetime, 10); + f = ((1 - swing) * autocvar_g_balance_shotgun_secondary_melee_traces); + + // check to see if we can still continue, otherwise give up now + if((self.realowner.deadflag != DEAD_NO) && autocvar_g_balance_shotgun_secondary_melee_no_doubleslap) { - vector force; - force = angle * autocvar_g_balance_shotgun_secondary_force; - if(accuracy_isgooddamage(self.owner, trace_ent)) - accuracy_add(self.owner, WEP_SHOTGUN, 0, autocvar_g_balance_shotgun_secondary_damage * min(1, f + 1)); - Damage (trace_ent, self.owner, self.owner, autocvar_g_balance_shotgun_secondary_damage * min(1, f + 1), WEP_SHOTGUN | HITTYPE_SECONDARY , self.owner.origin + self.owner.view_ofs, force); remove(self); + return; + } + + // if okay, perform the traces needed for this frame + for(i=self.swing_prev; i < f; ++i) + { + swing_factor = ((1 - (i / autocvar_g_balance_shotgun_secondary_melee_traces)) * 2 - 1); + + targpos = (self.realowner.origin + self.realowner.view_ofs + + (v_forward * autocvar_g_balance_shotgun_secondary_melee_range) + + (v_up * swing_factor * autocvar_g_balance_shotgun_secondary_melee_swing_up) + + (v_right * swing_factor * autocvar_g_balance_shotgun_secondary_melee_swing_side)); + + WarpZone_traceline_antilag(self.realowner, self.realowner.origin + self.realowner.view_ofs, targpos, FALSE, self.realowner, ANTILAG_LATENCY(self.realowner)); + + // draw lightning beams for debugging + //te_lightning2(world, targpos, self.realowner.origin + self.realowner.view_ofs + v_forward * 5 - v_up * 5); + //te_customflash(targpos, 40, 2, '1 1 1'); + + is_player = (trace_ent.classname == "player" || trace_ent.classname == "body"); + + if((trace_fraction < 1) // if trace is good, apply the damage and remove self + && (trace_ent.takedamage == DAMAGE_AIM) + && (trace_ent != self.swing_alreadyhit) + && (is_player || autocvar_g_balance_shotgun_secondary_melee_nonplayerdamage)) + { + target_victim = trace_ent; // so it persists through other calls + + if(is_player) // this allows us to be able to nerf the non-player damage done in e.g. assault or onslaught. + swing_damage = (autocvar_g_balance_shotgun_secondary_damage * min(1, swing_factor + 1)); + else + swing_damage = (autocvar_g_balance_shotgun_secondary_melee_nonplayerdamage * min(1, swing_factor + 1)); + + //print(strcat(self.realowner.netname, " hitting ", target_victim.netname, " with ", strcat(ftos(swing_damage), " damage (factor: ", ftos(swing_factor), ") at "), ftos(time), " seconds.\n")); + + Damage(target_victim, self.realowner, self.realowner, + swing_damage, WEP_SHOTGUN | HITTYPE_SECONDARY, + self.realowner.origin + self.realowner.view_ofs, + v_forward * autocvar_g_balance_shotgun_secondary_force); + + if(accuracy_isgooddamage(self.realowner, target_victim)) { accuracy_add(self.realowner, WEP_SHOTGUN, 0, swing_damage); } + + // draw large red flash for debugging + //te_customflash(targpos, 200, 2, '15 0 0'); + + if(autocvar_g_balance_shotgun_secondary_melee_multihit) // allow multiple hits with one swing, but not against the same player twice. + { + self.swing_alreadyhit = target_victim; + continue; // move along to next trace + } + else + { + remove(self); + return; + } + } } - else if(time >= self.cnt + autocvar_g_balance_shotgun_secondary_melee_time) // missed, remove ent + + if(time >= self.cnt + meleetime) + { + // melee is finished remove(self); - else // continue swinging the weapon in hope of hitting someone :) + return; + } + else + { + // set up next frame + self.swing_prev = i; self.nextthink = time; + } } void W_Shotgun_Attack2 (void) { - sound (self, CHAN_PROJECTILE, "weapons/shotgun_melee.wav", VOL_BASE, ATTN_NORM); + sound (self, CH_WEAPON_A, "weapons/shotgun_melee.wav", VOL_BASE, ATTN_NORM); weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_shotgun_secondary_animtime, w_ready); entity meleetemp; meleetemp = spawn(); - meleetemp.owner = self; + meleetemp.owner = meleetemp.realowner = self; meleetemp.think = shotgun_meleethink; - meleetemp.nextthink = time + autocvar_g_balance_shotgun_secondary_melee_delay; + meleetemp.nextthink = time + autocvar_g_balance_shotgun_secondary_melee_delay * W_WeaponRateFactor(); W_SetupShot_Range(self, TRUE, 0, "", 0, autocvar_g_balance_shotgun_secondary_damage, autocvar_g_balance_shotgun_secondary_melee_range); } @@ -99,25 +163,43 @@ void spawnfunc_weapon_shotgun(); // defined in t_items.qc float w_shotgun(float req) { + float ammo_amount; if (req == WR_AIM) if(vlen(self.origin-self.enemy.origin) <= autocvar_g_balance_shotgun_secondary_melee_range) self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, FALSE); else - self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, FALSE); + { + if(autocvar_g_antilag_bullets) + self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, FALSE); + else + self.BUTTON_ATCK = bot_aim(autocvar_g_balance_shotgun_primary_speed, 0, 0.001, FALSE); + } + else if (req == WR_THINK) { - if (self.BUTTON_ATCK) + if(autocvar_g_balance_shotgun_reload_ammo && self.clip_load < autocvar_g_balance_shotgun_primary_ammo) // forced reload { - if (time >= self.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary + // don't force reload an empty shotgun if its melee attack is active + if not(autocvar_g_balance_shotgun_secondary && self.ammo_shells < autocvar_g_balance_shotgun_primary_ammo) + weapon_action(self.weapon, WR_RELOAD); + } + else + { + if (self.BUTTON_ATCK) { - if(weapon_prepareattack(0, autocvar_g_balance_shotgun_primary_animtime)) + if (time >= self.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary { - W_Shotgun_Attack(); - self.shotgun_primarytime = time + autocvar_g_balance_shotgun_primary_refire; - weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_shotgun_primary_animtime, w_ready); + if(weapon_prepareattack(0, autocvar_g_balance_shotgun_primary_animtime)) + { + W_Shotgun_Attack(); + self.shotgun_primarytime = time + autocvar_g_balance_shotgun_primary_refire * W_WeaponRateFactor(); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_shotgun_primary_animtime, w_ready); + } } } } + if (self.clip_load >= 0) // we are not currently reloading + if (!self.crouch) // we are not currently crouching; this fixes an exploit where your melee anim is not visible, and besides wouldn't make much sense if (self.BUTTON_ATCK2 && autocvar_g_balance_shotgun_secondary) if (weapon_prepareattack(1, autocvar_g_balance_shotgun_secondary_refire)) { @@ -134,17 +216,30 @@ float w_shotgun(float req) precache_sound ("misc/itempickup.wav"); precache_sound ("weapons/shotgun_fire.wav"); precache_sound ("weapons/shotgun_melee.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else } else if (req == WR_SETUP) + { weapon_setup(WEP_SHOTGUN); + self.current_ammo = ammo_shells; + } else if (req == WR_CHECKAMMO1) - return self.ammo_shells >= autocvar_g_balance_shotgun_primary_ammo; + { + ammo_amount = self.ammo_shells >= autocvar_g_balance_shotgun_primary_ammo; + ammo_amount += self.(weapon_load[WEP_SHOTGUN]) >= autocvar_g_balance_shotgun_primary_ammo; + return ammo_amount; + } else if (req == WR_CHECKAMMO2) { + // melee attack is always available return TRUE; } + else if (req == WR_RELOAD) + { + W_Reload(autocvar_g_balance_shotgun_primary_ammo, autocvar_g_balance_shotgun_reload_ammo, autocvar_g_balance_shotgun_reload_time, "weapons/reload.wav"); + } return TRUE; -}; +} #endif #ifdef CSQC .float prevric; @@ -158,11 +253,11 @@ float w_shotgun(float req) if(!w_issilent && time - self.prevric > 0.25) { if(w_random < 0.0165) - sound(self, CHAN_PROJECTILE, "weapons/ric1.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/ric1.wav", VOL_BASE, ATTN_NORM); else if(w_random < 0.033) - sound(self, CHAN_PROJECTILE, "weapons/ric2.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/ric2.wav", VOL_BASE, ATTN_NORM); else if(w_random < 0.05) - sound(self, CHAN_PROJECTILE, "weapons/ric3.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/ric3.wav", VOL_BASE, ATTN_NORM); self.prevric = time; } } @@ -173,13 +268,13 @@ float w_shotgun(float req) precache_sound("weapons/ric3.wav"); } else if (req == WR_SUICIDEMESSAGE) - w_deathtypestring = "%s did the impossible"; + w_deathtypestring = _("%s is now thinking with portals"); else if (req == WR_KILLMESSAGE) { if(w_deathtype & HITTYPE_SECONDARY) - w_deathtypestring = "%2$s ^7slapped %1$s ^7around a bit with a large ^2shotgun"; + w_deathtypestring = _("%2$s slapped %1$s around a bit with a large shotgun"); else - w_deathtypestring = "%s was gunned by %s"; + w_deathtypestring = _("%s was gunned down with a shotgun by %s"); } return TRUE; } diff --git a/qcsrc/server/w_tuba.qc b/qcsrc/server/w_tuba.qc index 1ea9cec973..a02061e8b8 100644 --- a/qcsrc/server/w_tuba.qc +++ b/qcsrc/server/w_tuba.qc @@ -1,11 +1,140 @@ #ifdef REGISTER_WEAPON -REGISTER_WEAPON(TUBA, w_tuba, 0, 1, WEP_FLAG_HIDDEN | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_MID, "tuba", "tuba", "@!#%'n Tuba"); +REGISTER_WEAPON(TUBA, w_tuba, 0, 1, WEP_FLAG_HIDDEN | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_MID, "tuba", "tuba", _("@!#%'n Tuba")) #else #ifdef SVQC //#define TUBA_NOTE(n) strcat("weapons/tuba_note", ftos(n), ".wav") -.float tuba_notecount; .entity tuba_note; .float tuba_smoketime; +.float tuba_instrument; + +#define MAX_TUBANOTES 32 +.float tuba_lastnotes_last; +.float tuba_lastnotes_cnt; // over +.vector tuba_lastnotes[MAX_TUBANOTES]; + +float W_Tuba_HasPlayed(entity pl, string melody, float instrument, float ignorepitch, float mintempo, float maxtempo) +{ + float i, j, mmin, mmax, nolength; + float n = tokenize_console(melody); + if(n > pl.tuba_lastnotes_cnt) + return FALSE; + float pitchshift = 0; + + if(instrument >= 0) + if(pl.tuba_instrument != instrument) + return FALSE; + + // verify notes... + nolength = FALSE; + for(i = 0; i < n; ++i) + { + vector v = pl.(tuba_lastnotes[mod(pl.tuba_lastnotes_last - i + MAX_TUBANOTES, MAX_TUBANOTES)]); + float ai = stof(argv(n - i - 1)); + float np = floor(ai); + if(ai == np) + nolength = TRUE; + // n counts the last played notes BACKWARDS + // _x is start + // _y is end + // _z is note pitch + if(ignorepitch && i == 0) + { + pitchshift = np - v_z; + } + else + { + if(v_z + pitchshift != np) + return FALSE; + } + } + + // now we know the right NOTES were played + if(!nolength) + { + // verify rhythm... + float ti = 0; + if(maxtempo > 0) + mmin = 240 / maxtempo; // 60 = "0.25 means 1 sec", at 120 0.5 means 1 sec, at 240 1 means 1 sec + else + mmin = 0; + if(mintempo > 0) + mmax = 240 / mintempo; // 60 = "0.25 means 1 sec", at 120 0.5 means 1 sec, at 240 1 means 1 sec + else + mmax = 240; // you won't try THAT hard... (tempo 1) + //print(sprintf("initial tempo rules: %f %f\n", mmin, mmax)); + + for(i = 0; i < n; ++i) + { + vector vi = pl.(tuba_lastnotes[mod(pl.tuba_lastnotes_last - i + MAX_TUBANOTES, MAX_TUBANOTES)]); + float ai = stof(argv(n - i - 1)); + ti -= 1 / (ai - floor(ai)); + float tj = ti; + for(j = i+1; j < n; ++j) + { + vector vj = pl.(tuba_lastnotes[mod(pl.tuba_lastnotes_last - j + MAX_TUBANOTES, MAX_TUBANOTES)]); + float aj = stof(argv(n - j - 1)); + tj -= (aj - floor(aj)); + + // note i should be at m*ti+b + // note j should be at m*tj+b + // so: + // we have a LINE l, so that + // vi_x <= l(ti) <= vi_y + // vj_x <= l(tj) <= vj_y + // what is m? + + // vi_x <= vi_y <= vj_x <= vj_y + // ti <= tj + //print(sprintf("first note: %f to %f, should be %f\n", vi_x, vi_y, ti)); + //print(sprintf("second note: %f to %f, should be %f\n", vj_x, vj_y, tj)); + //print(sprintf("m1 = %f\n", (vi_x - vj_y) / (ti - tj))); + //print(sprintf("m2 = %f\n", (vi_y - vj_x) / (ti - tj))); + mmin = max(mmin, (vi_x - vj_y) / (ti - tj)); // lower bound + mmax = min(mmax, (vi_y - vj_x) / (ti - tj)); // upper bound + } + } + + if(mmin > mmax) // rhythm fail + return FALSE; + } + + pl.tuba_lastnotes_cnt = 0; + + return TRUE; +} + +void W_Tuba_NoteOff() +{ + // we have a note: + // on: self.spawnshieldtime + // off: time + // note: self.cnt + if(self.owner.tuba_note == self) + { + self.owner.tuba_lastnotes_last = mod(self.owner.tuba_lastnotes_last + 1, MAX_TUBANOTES); + self.owner.(tuba_lastnotes[self.owner.tuba_lastnotes_last]) = eX * self.spawnshieldtime + eY * time + eZ * self.cnt; + self.owner.tuba_note = world; + self.owner.tuba_lastnotes_cnt = bound(0, self.owner.tuba_lastnotes_cnt + 1, MAX_TUBANOTES); + + string s; + s = trigger_magicear_processmessage_forallears(self.owner, 0, world, string_null); + if(s != "") + { + // simulate a server message + switch(self.tuba_instrument) + { + default: + case 0: // Tuba + bprint(strcat("\{1}\{13}* ^3", self.owner.netname, "^3 played on the @!#%'n Tuba: ^7", s, "\n")); + break; + case 1: + bprint(strcat("\{1}\{13}* ^3", self.owner.netname, "^3 played on the @!#%'n Accordeon: ^7", s, "\n")); + break; + } + } + } + remove(self); +} float Tuba_GetNote(entity pl, float hittype) { @@ -48,7 +177,7 @@ float Tuba_GetNote(entity pl, float hittype) // kind of tuba currently is player slot number, or team number if in // teamplay // that way, holes in the range of notes are "plugged" - if(teams_matter) + if(teamplay) { if(pl.team == COLOR_TEAM2 || pl.team == COLOR_TEAM4) note += 3; @@ -76,14 +205,28 @@ float Tuba_GetNote(entity pl, float hittype) float W_Tuba_NoteSendEntity(entity to, float sf) { + float f; + + msg_entity = to; + if(!sound_allowed(MSG_ONE, self.realowner)) + return FALSE; + WriteByte(MSG_ENTITY, ENT_CLIENT_TUBANOTE); - WriteByte(MSG_ENTITY, (sf & 1) | ((self.cnt + 42) * 2)); + WriteByte(MSG_ENTITY, sf); if(sf & 1) + { + WriteChar(MSG_ENTITY, self.cnt); + f = 0; + if(self.realowner != to) + f |= 1; + f |= 2 * self.tuba_instrument; + WriteByte(MSG_ENTITY, f); + } + if(sf & 2) { WriteCoord(MSG_ENTITY, self.origin_x); WriteCoord(MSG_ENTITY, self.origin_y); WriteCoord(MSG_ENTITY, self.origin_z); - WriteByte(MSG_ENTITY, self.owner != to); } return TRUE; } @@ -97,78 +240,76 @@ void W_Tuba_NoteThink() entity e; if(time > self.teleport_time) { - self.owner.tuba_note = world; - remove(self); + W_Tuba_NoteOff(); return; } self.nextthink = time; dist_mult = autocvar_g_balance_tuba_attenuation / autocvar_snd_soundradius; FOR_EACH_REALCLIENT(e) - if(e != self.owner) + if(e != self.realowner) { v = self.origin - (e.origin + e.view_ofs); vol0 = max(0, 1 - vlen(v) * dist_mult); dir0 = normalize(v); - v = self.owner.origin - (e.origin + e.view_ofs); + v = self.realowner.origin - (e.origin + e.view_ofs); vol1 = max(0, 1 - vlen(v) * dist_mult); dir1 = normalize(v); if(fabs(vol0 - vol1) > 0.005) // 0.5 percent change in volume { - setorigin(self, self.owner.origin); - self.SendFlags |= 1; + setorigin(self, self.realowner.origin); + self.SendFlags |= 2; break; } if(dir0 * dir1 < 0.9994) // 2 degrees change in angle { - setorigin(self, self.owner.origin); - self.SendFlags |= 1; + setorigin(self, self.realowner.origin); + self.SendFlags |= 2; break; } } } -void W_Tuba_Attack(float hittype) +void W_Tuba_NoteOn(float hittype) { vector o; - float c, n; + float n; + W_SetupShot(self, FALSE, 2, "", 0, autocvar_g_balance_tuba_damage); - if(self.tuba_notecount) - { - self.tuba_notecount = FALSE; - c = CHAN_WEAPON; - } - else - { - self.tuba_notecount = TRUE; - c = CHAN_WEAPON2; - } n = Tuba_GetNote(self, hittype); + hittype = 0; + if(self.tuba_instrument & 1) + hittype |= HITTYPE_SECONDARY; + if(self.tuba_instrument & 2) + hittype |= HITTYPE_BOUNCE; + if(self.tuba_instrument & 4) + hittype |= HITTYPE_HEADSHOT; + if(self.tuba_note) { - if(self.tuba_note.cnt != n) + if(self.tuba_note.cnt != n || self.tuba_note.tuba_instrument != self.tuba_instrument) { - /* - self.tuba_note.cnt = n; - self.tuba_note.SendFlags |= 2; - */ - remove(self.tuba_note); - self.tuba_note = world; + entity oldself = self; + self = self.tuba_note; + W_Tuba_NoteOff(); + self = oldself; } } if not(self.tuba_note) { self.tuba_note = spawn(); - self.tuba_note.owner = self; + self.tuba_note.owner = self.tuba_note.realowner = self; self.tuba_note.cnt = n; + self.tuba_note.tuba_instrument = self.tuba_instrument; self.tuba_note.think = W_Tuba_NoteThink; self.tuba_note.nextthink = time; + self.tuba_note.spawnshieldtime = time; Net_LinkEntity(self.tuba_note, FALSE, 0, W_Tuba_NoteSendEntity); } - self.tuba_note.teleport_time = time + autocvar_g_balance_tuba_refire * 2; // so it can get prolonged safely + self.tuba_note.teleport_time = time + autocvar_g_balance_tuba_refire * 2 * W_WeaponRateFactor(); // so it can get prolonged safely //sound(self, c, TUBA_NOTE(n), bound(0, VOL_BASE * cvar("g_balance_tuba_volume"), 1), autocvar_g_balance_tuba_attenuation); RadiusDamage(self, self, autocvar_g_balance_tuba_damage, autocvar_g_balance_tuba_edgedamage, autocvar_g_balance_tuba_radius, world, autocvar_g_balance_tuba_force, hittype | WEP_TUBA, world); @@ -205,14 +346,14 @@ float w_tuba(float req) if (self.BUTTON_ATCK) if (weapon_prepareattack(0, autocvar_g_balance_tuba_refire)) { - W_Tuba_Attack(0); + W_Tuba_NoteOn(0); //weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_tuba_animtime, w_ready); weapon_thinkf(WFRAME_IDLE, autocvar_g_balance_tuba_animtime, w_ready); } if (self.BUTTON_ATCK2) if (weapon_prepareattack(1, autocvar_g_balance_tuba_refire)) { - W_Tuba_Attack(HITTYPE_SECONDARY); + W_Tuba_NoteOn(HITTYPE_SECONDARY); //weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_tuba_animtime, w_ready); weapon_thinkf(WFRAME_IDLE, autocvar_g_balance_tuba_animtime, w_ready); } @@ -220,8 +361,10 @@ float w_tuba(float req) { if(!self.BUTTON_ATCK && !self.BUTTON_ATCK2) { - remove(self.tuba_note); - self.tuba_note = world; + entity oldself = self; + self = self.tuba_note; + W_Tuba_NoteOff(); + self = oldself; } } } @@ -230,19 +373,48 @@ float w_tuba(float req) precache_model ("models/weapons/g_tuba.md3"); precache_model ("models/weapons/v_tuba.md3"); precache_model ("models/weapons/h_tuba.iqm"); + precache_model ("models/weapons/g_akordeon.md3"); + precache_model ("models/weapons/v_akordeon.md3"); + precache_model ("models/weapons/h_akordeon.iqm"); //float i; //for(i = -18; i <= +27; ++i) // precache_sound(TUBA_NOTE(i)); } else if (req == WR_SETUP) + { weapon_setup(WEP_TUBA); + self.current_ammo = ammo_none; + self.tuba_instrument = 0; + } + else if (req == WR_RELOAD) + { + // switch to alternate instruments :) + if(self.weaponentity.state == WS_READY) + { + switch(self.tuba_instrument) + { + case 0: + self.tuba_instrument = 1; + self.weaponname = "akordeon"; + break; + case 1: + self.tuba_instrument = 0; + self.weaponname = "tuba"; + break; + } + W_SetupShot(self, FALSE, 0, "", 0, 0); + pointparticles(particleeffectnum("teleport"), w_shotorg, '0 0 0', 1); + self.weaponentity.state = WS_INUSE; + weapon_thinkf(WFRAME_RELOAD, 0.5, w_ready); + } + } else if (req == WR_CHECKAMMO1) return TRUE; // TODO use fuel? else if (req == WR_CHECKAMMO2) return TRUE; // TODO use fuel? return TRUE; -}; +} #endif #ifdef CSQC float w_tuba(float req) @@ -257,11 +429,45 @@ float w_tuba(float req) } else if (req == WR_SUICIDEMESSAGE) { - w_deathtypestring = "%s hurt his own ears with the @!#%%'n Tuba"; + float instr; + instr = 0; + if(w_deathtype & HITTYPE_SECONDARY) + instr |= 1; + if(w_deathtype & HITTYPE_BOUNCE) + instr |= 2; + if(w_deathtype & HITTYPE_HEADSHOT) + instr |= 4; + switch(instr) + { + default: + case 0: // Tuba + w_deathtypestring = _("%s hurt his own ears with the @!#%%'n Tuba"); + break; + case 1: // Accordeon + w_deathtypestring = _("%s hurt his own ears with the @!#%%'n Accordeon"); + break; + } } else if (req == WR_KILLMESSAGE) { - w_deathtypestring = "%s died of %s's great playing on the @!#%%'n Tuba"; + float instr; + instr = 0; + if(w_deathtype & HITTYPE_SECONDARY) + instr |= 1; + if(w_deathtype & HITTYPE_BOUNCE) + instr |= 2; + if(w_deathtype & HITTYPE_HEADSHOT) + instr |= 4; + switch(instr) + { + default: + case 0: // Tuba + w_deathtypestring = _("%s died of %s's great playing on the @!#%%'n Tuba"); + break; + case 1: // Accordeon + w_deathtypestring = _("%s died of %s's great playing on the @!#%%'n Accordeon"); + break; + } } return TRUE; } diff --git a/qcsrc/server/w_uzi.qc b/qcsrc/server/w_uzi.qc index 2d50143dee..77d8b4aee5 100644 --- a/qcsrc/server/w_uzi.qc +++ b/qcsrc/server/w_uzi.qc @@ -1,12 +1,11 @@ #ifdef REGISTER_WEAPON -REGISTER_WEAPON(UZI, w_uzi, IT_NAILS, 3, WEP_FLAG_NORMAL | WEP_TYPE_HITSCAN, BOT_PICKUP_RATING_MID, "uzi", "uzi", "Machine Gun"); +REGISTER_WEAPON(UZI, w_uzi, IT_NAILS, 3, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN, BOT_PICKUP_RATING_MID, "uzi", "uzi", _("Machine Gun")) #else #ifdef SVQC -.entity muzzle_flash; // leilei's fancy muzzleflash stuff -void Uzi_Flash_Go() -{ +void UZI_Flash_Go() +{ self.frame = self.frame + 2; self.scale = self.scale * 0.5; self.alpha = self.alpha - 0.25; @@ -16,41 +15,33 @@ void Uzi_Flash_Go() { self.think = SUB_Remove; self.nextthink = time; - self.owner.muzzle_flash = world; + self.realowner.muzzle_flash = world; return; } - + } void UziFlash() -{ +{ if (self.muzzle_flash == world) - self.muzzle_flash = spawn(); - + self.muzzle_flash = spawn(); + // muzzle flash for 1st person view setmodel(self.muzzle_flash, "models/uziflash.md3"); // precision set below - + self.muzzle_flash.scale = 0.75; - self.muzzle_flash.think = Uzi_Flash_Go; + self.muzzle_flash.think = UZI_Flash_Go; self.muzzle_flash.nextthink = time + 0.02; self.muzzle_flash.frame = 2; self.muzzle_flash.alpha = 0.75; self.muzzle_flash.angles_z = random() * 180; self.muzzle_flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION; - self.muzzle_flash.owner = self; + self.muzzle_flash.owner = self.muzzle_flash.realowner = self; } -.float uzi_bulletcounter; -void W_Uzi_Attack (float deathtype) +void W_UZI_Attack (float deathtype) { - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - { - if (self.uzi_bulletcounter == 1) - self.ammo_nails = self.ammo_nails - autocvar_g_balance_uzi_first_ammo; - else - self.ammo_nails = self.ammo_nails - autocvar_g_balance_uzi_sustained_ammo; - } - W_SetupShot (self, autocvar_g_antilag_bullets && autocvar_g_balance_uzi_speed >= autocvar_g_antilag_bullets, 0, "weapons/uzi_fire.wav", CHAN_WEAPON, ((self.uzi_bulletcounter == 1) ? autocvar_g_balance_uzi_first_damage : autocvar_g_balance_uzi_sustained_damage)); + W_SetupShot (self, autocvar_g_antilag_bullets && autocvar_g_balance_uzi_speed >= autocvar_g_antilag_bullets, 0, "weapons/uzi_fire.wav", CH_WEAPON_A, ((self.misc_bulletcounter == 1) ? autocvar_g_balance_uzi_first_damage : autocvar_g_balance_uzi_sustained_damage)); if (!g_norecoil) { self.punchangle_x = random () - 0.5; @@ -60,10 +51,10 @@ void W_Uzi_Attack (float deathtype) // this attack_finished just enforces a cooldown at the end of a burst ATTACK_FINISHED(self) = time + autocvar_g_balance_uzi_first_refire * W_WeaponRateFactor(); - if (self.uzi_bulletcounter == 1) - fireBallisticBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_first_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_first_damage, 0, autocvar_g_balance_uzi_first_force, deathtype, 0, 1, autocvar_g_balance_uzi_bulletconstant); + if (self.misc_bulletcounter == 1) + fireBallisticBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_first_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_first_damage, autocvar_g_balance_uzi_first_headshotaddeddamage, autocvar_g_balance_uzi_first_force, deathtype, 0, 1, autocvar_g_balance_uzi_bulletconstant); else - fireBallisticBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_sustained_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_sustained_damage, 0, autocvar_g_balance_uzi_sustained_force, deathtype, 0, 1, autocvar_g_balance_uzi_bulletconstant); + fireBallisticBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_sustained_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_sustained_damage, autocvar_g_balance_uzi_sustained_headshotaddeddamage, autocvar_g_balance_uzi_sustained_force, deathtype, 0, 1, autocvar_g_balance_uzi_bulletconstant); endFireBallisticBullet(); pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); @@ -74,6 +65,11 @@ void W_Uzi_Attack (float deathtype) // casing code if (autocvar_g_casings >= 2) SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self); + + if (self.misc_bulletcounter == 1) + W_DecreaseAmmo(ammo_nails, autocvar_g_balance_uzi_first_ammo, autocvar_g_balance_uzi_reload_ammo); + else + W_DecreaseAmmo(ammo_nails, autocvar_g_balance_uzi_sustained_ammo, autocvar_g_balance_uzi_reload_ammo); } // weapon frames @@ -87,13 +83,14 @@ void uzi_fire1_02() if (self.BUTTON_ATCK) { if (!weapon_action(self.weapon, WR_CHECKAMMO2)) + if not(self.items & IT_UNLIMITED_WEAPON_AMMO) { W_SwitchWeapon_Force(self, w_getbestweapon(self)); w_ready(); return; } - self.uzi_bulletcounter = self.uzi_bulletcounter + 1; - W_Uzi_Attack(WEP_UZI); + self.misc_bulletcounter = self.misc_bulletcounter + 1; + W_UZI_Attack(WEP_UZI); weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, uzi_fire1_02); } else @@ -104,85 +101,87 @@ void uzi_fire1_02() void uzi_mode1_fire_auto() { float uzi_spread; - - if (self.BUTTON_ATCK) - weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, uzi_mode1_fire_auto); - else + + if (!self.BUTTON_ATCK) { - ATTACK_FINISHED(self) = time + autocvar_g_balance_uzi_first_refire * W_WeaponRateFactor(); - weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, w_ready); + w_ready(); return; } if (!weapon_action(self.weapon, WR_CHECKAMMO1)) + if not(self.items & IT_UNLIMITED_WEAPON_AMMO) { W_SwitchWeapon_Force(self, w_getbestweapon(self)); w_ready(); return; } - - W_SetupShot (self, autocvar_g_antilag_bullets && autocvar_g_balance_uzi_speed >= autocvar_g_antilag_bullets, 0, "weapons/uzi_fire.wav", CHAN_WEAPON, autocvar_g_balance_uzi_sustained_damage); + + W_DecreaseAmmo(ammo_nails, autocvar_g_balance_uzi_sustained_ammo, autocvar_g_balance_uzi_reload_ammo); + + W_SetupShot (self, autocvar_g_antilag_bullets && autocvar_g_balance_uzi_speed >= autocvar_g_antilag_bullets, 0, "weapons/uzi_fire.wav", CH_WEAPON_A, autocvar_g_balance_uzi_sustained_damage); if (!g_norecoil) { self.punchangle_x = random () - 0.5; self.punchangle_y = random () - 0.5; } - - uzi_spread = bound(autocvar_g_balance_uzi_spread_min, autocvar_g_balance_uzi_spread_min + (autocvar_g_balance_uzi_spread_add * self.uzi_bulletcounter), autocvar_g_balance_uzi_spread_max); - fireBallisticBullet(w_shotorg, w_shotdir, uzi_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_sustained_damage, 0, autocvar_g_balance_uzi_sustained_force, WEP_UZI, 0, 1, autocvar_g_balance_uzi_bulletconstant); + + uzi_spread = bound(autocvar_g_balance_uzi_spread_min, autocvar_g_balance_uzi_spread_min + (autocvar_g_balance_uzi_spread_add * self.misc_bulletcounter), autocvar_g_balance_uzi_spread_max); + fireBallisticBullet(w_shotorg, w_shotdir, uzi_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_sustained_damage, autocvar_g_balance_uzi_sustained_headshotaddeddamage, autocvar_g_balance_uzi_sustained_force, WEP_UZI, 0, 1, autocvar_g_balance_uzi_bulletconstant); endFireBallisticBullet(); - - self.uzi_bulletcounter = self.uzi_bulletcounter + 1; - + + self.misc_bulletcounter = self.misc_bulletcounter + 1; + pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); UziFlash(); W_AttachToShotorg(self.muzzle_flash, '5 0 0'); - + if (autocvar_g_casings >= 2) // casing code SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self); - - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_nails = self.ammo_nails - autocvar_g_balance_uzi_sustained_ammo; - + + ATTACK_FINISHED(self) = time + autocvar_g_balance_uzi_first_refire * W_WeaponRateFactor(); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, uzi_mode1_fire_auto); } void uzi_mode1_fire_burst() { - W_SetupShot (self, autocvar_g_antilag_bullets && autocvar_g_balance_uzi_speed >= autocvar_g_antilag_bullets, 0, "weapons/uzi_fire.wav", CHAN_WEAPON, autocvar_g_balance_uzi_sustained_damage); + W_SetupShot (self, autocvar_g_antilag_bullets && autocvar_g_balance_uzi_speed >= autocvar_g_antilag_bullets, 0, "weapons/uzi_fire.wav", CH_WEAPON_A, autocvar_g_balance_uzi_sustained_damage); if (!g_norecoil) { self.punchangle_x = random () - 0.5; self.punchangle_y = random () - 0.5; } - - fireBallisticBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_burst_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_sustained_damage, 0, autocvar_g_balance_uzi_sustained_force, WEP_UZI, 0, 1, autocvar_g_balance_uzi_bulletconstant); + + fireBallisticBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_burst_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_sustained_damage, autocvar_g_balance_uzi_sustained_headshotaddeddamage, autocvar_g_balance_uzi_sustained_force, WEP_UZI, 0, 1, autocvar_g_balance_uzi_bulletconstant); endFireBallisticBullet(); - - + + pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); UziFlash(); W_AttachToShotorg(self.muzzle_flash, '5 0 0'); - + if (autocvar_g_casings >= 2) // casing code SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self); - self.uzi_bulletcounter = self.uzi_bulletcounter + 1; - if (self.uzi_bulletcounter == 0) - weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_uzi_burst_refire2, w_ready); + self.misc_bulletcounter = self.misc_bulletcounter + 1; + if (self.misc_bulletcounter == 0) + { + ATTACK_FINISHED(self) = time + autocvar_g_balance_uzi_burst_refire2 * W_WeaponRateFactor(); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_uzi_burst_animtime, w_ready); + } else { weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_uzi_burst_refire, uzi_mode1_fire_burst); - dprint("bullets:", ftos(self.uzi_bulletcounter),"\n"); } - + } void spawnfunc_weapon_machinegun(); // defined in t_items.qc float w_uzi(float req) { + float ammo_amount; if (req == WR_AIM) if(vlen(self.origin-self.enemy.origin) < 3000 - bound(0, skill, 10) * 200) self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, FALSE); @@ -192,48 +191,50 @@ float w_uzi(float req) } else if (req == WR_THINK) { - if(autocvar_g_balance_uzi_mode == 1) + if(autocvar_g_balance_uzi_reload_ammo && self.clip_load < min(max(autocvar_g_balance_uzi_sustained_ammo, autocvar_g_balance_uzi_first_ammo), autocvar_g_balance_uzi_burst_ammo)) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else if(autocvar_g_balance_uzi_mode == 1) { if (self.BUTTON_ATCK) if (weapon_prepareattack(0, 0)) - { - self.uzi_bulletcounter = 0; + { + self.misc_bulletcounter = 0; uzi_mode1_fire_auto(); } - + if(self.BUTTON_ATCK2) if(weapon_prepareattack(1, 0)) { if (!weapon_action(self.weapon, WR_CHECKAMMO2)) + if not(self.items & IT_UNLIMITED_WEAPON_AMMO) { W_SwitchWeapon_Force(self, w_getbestweapon(self)); w_ready(); return FALSE; } - - if not(self.items & IT_UNLIMITED_WEAPON_AMMO) - self.ammo_nails = self.ammo_nails - autocvar_g_balance_uzi_burst_ammo; - self.uzi_bulletcounter = autocvar_g_balance_uzi_burst * -1; + W_DecreaseAmmo(ammo_nails, autocvar_g_balance_uzi_burst_ammo, autocvar_g_balance_uzi_reload_ammo); + + self.misc_bulletcounter = autocvar_g_balance_uzi_burst * -1; uzi_mode1_fire_burst(); } } else { - + if (self.BUTTON_ATCK) if (weapon_prepareattack(0, 0)) { - self.uzi_bulletcounter = 1; - W_Uzi_Attack(WEP_UZI); // sets attack_finished + self.misc_bulletcounter = 1; + W_UZI_Attack(WEP_UZI); // sets attack_finished weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, uzi_fire1_02); } if (self.BUTTON_ATCK2 && autocvar_g_balance_uzi_first) if (weapon_prepareattack(1, 0)) { - self.uzi_bulletcounter = 1; - W_Uzi_Attack(WEP_UZI | HITTYPE_SECONDARY); // sets attack_finished + self.misc_bulletcounter = 1; + W_UZI_Attack(WEP_UZI | HITTYPE_SECONDARY); // sets attack_finished weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_uzi_first_refire, w_ready); } } @@ -245,21 +246,51 @@ float w_uzi(float req) precache_model ("models/weapons/v_uzi.md3"); precache_model ("models/weapons/h_uzi.iqm"); precache_sound ("weapons/uzi_fire.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else } else if (req == WR_SETUP) + { weapon_setup(WEP_UZI); + self.current_ammo = ammo_nails; + } else if (req == WR_CHECKAMMO1) + { if(autocvar_g_balance_uzi_mode == 1) - return self.ammo_nails >= autocvar_g_balance_uzi_sustained_ammo; + ammo_amount = self.ammo_nails >= autocvar_g_balance_uzi_sustained_ammo; else - return self.ammo_nails >= autocvar_g_balance_uzi_first_ammo; + ammo_amount = self.ammo_nails >= autocvar_g_balance_uzi_first_ammo; + + if(autocvar_g_balance_uzi_reload_ammo) + { + if(autocvar_g_balance_uzi_mode == 1) + ammo_amount += self.(weapon_load[WEP_UZI]) >= autocvar_g_balance_uzi_sustained_ammo; + else + ammo_amount += self.(weapon_load[WEP_UZI]) >= autocvar_g_balance_uzi_first_ammo; + } + return ammo_amount; + } else if (req == WR_CHECKAMMO2) + { if(autocvar_g_balance_uzi_mode == 1) - return self.ammo_nails >= autocvar_g_balance_uzi_burst_ammo; + ammo_amount = self.ammo_nails >= autocvar_g_balance_uzi_burst_ammo; else - return self.ammo_nails >= autocvar_g_balance_uzi_first_ammo; + ammo_amount = self.ammo_nails >= autocvar_g_balance_uzi_first_ammo; + + if(autocvar_g_balance_uzi_reload_ammo) + { + if(autocvar_g_balance_uzi_mode == 1) + ammo_amount += self.(weapon_load[WEP_UZI]) >= autocvar_g_balance_uzi_burst_ammo; + else + ammo_amount += self.(weapon_load[WEP_UZI]) >= autocvar_g_balance_uzi_first_ammo; + } + return ammo_amount; + } + else if (req == WR_RELOAD) + { + W_Reload(min(max(autocvar_g_balance_uzi_sustained_ammo, autocvar_g_balance_uzi_first_ammo), autocvar_g_balance_uzi_burst_ammo), autocvar_g_balance_uzi_reload_ammo, autocvar_g_balance_uzi_reload_time, "weapons/reload.wav"); + } return TRUE; -}; +} #endif #ifdef CSQC float w_uzi(float req) @@ -271,11 +302,11 @@ float w_uzi(float req) pointparticles(particleeffectnum("machinegun_impact"), org2, w_backoff * 1000, 1); if(!w_issilent) if(w_random < 0.05) - sound(self, CHAN_PROJECTILE, "weapons/ric1.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/ric1.wav", VOL_BASE, ATTN_NORM); else if(w_random < 0.1) - sound(self, CHAN_PROJECTILE, "weapons/ric2.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/ric2.wav", VOL_BASE, ATTN_NORM); else if(w_random < 0.2) - sound(self, CHAN_PROJECTILE, "weapons/ric3.wav", VOL_BASE, ATTN_NORM); + sound(self, CH_SHOTS, "weapons/ric3.wav", VOL_BASE, ATTN_NORM); } else if(req == WR_PRECACHE) { @@ -284,13 +315,13 @@ float w_uzi(float req) precache_sound("weapons/ric3.wav"); } else if (req == WR_SUICIDEMESSAGE) - w_deathtypestring = "%s did the impossible"; + w_deathtypestring = _("%s is now thinking with portals"); else if (req == WR_KILLMESSAGE) { if(w_deathtype & HITTYPE_SECONDARY) - w_deathtypestring = "%s was sniped by %s"; + w_deathtypestring = _("%s was sniped by %s's machine gun"); else - w_deathtypestring = "%s was riddled full of holes by %s"; + w_deathtypestring = _("%s was riddled full of holes by %s's machine gun"); } return TRUE; } diff --git a/qcsrc/server/waypointsprites.qc b/qcsrc/server/waypointsprites.qc index 5bbf02676f..0e6f2168b8 100644 --- a/qcsrc/server/waypointsprites.qc +++ b/qcsrc/server/waypointsprites.qc @@ -81,13 +81,28 @@ void WaypointSprite_UpdateTeamRadar(entity e, float icon, vector col) e.SendFlags |= 32; } +.float waypointsprite_pingtime; +.float waypointsprite_helpmetime; void WaypointSprite_Ping(entity e) { + // anti spam + if(time < e.waypointsprite_pingtime) + return; + e.waypointsprite_pingtime = time + 0.3; // ALWAYS sends (this causes a radar circle), thus no check e.cnt |= 0x80; e.SendFlags |= 32; } +float waypointsprite_limitedrange, waypointsprite_deployed_lifetime, waypointsprite_deadlifetime; + +void WaypointSprite_HelpMePing(entity e) +{ + WaypointSprite_Ping(e); + e.waypointsprite_helpmetime = time + waypointsprite_deployed_lifetime; + e.SendFlags |= 32; +} + void WaypointSprite_FadeOutIn(entity e, float t) { if(!e.fade_time) @@ -110,12 +125,11 @@ void WaypointSprite_FadeOutIn(entity e, float t) e.SendFlags |= 16; } -float waypointsprite_limitedrange, waypointsprite_deployed_lifetime, waypointsprite_deadlifetime; void WaypointSprite_Init() { - waypointsprite_limitedrange = autocvar_g_waypointsprite_limitedrange; - waypointsprite_deployed_lifetime = autocvar_g_waypointsprite_deployed_lifetime; - waypointsprite_deadlifetime = autocvar_g_waypointsprite_deadlifetime; + waypointsprite_limitedrange = autocvar_sv_waypointsprite_limitedrange; + waypointsprite_deployed_lifetime = autocvar_sv_waypointsprite_deployed_lifetime; + waypointsprite_deadlifetime = autocvar_sv_waypointsprite_deadlifetime; } void WaypointSprite_InitClient(entity e) { @@ -175,30 +189,63 @@ float WaypointSprite_visible_for_player(entity e) { // personal waypoints if(self.enemy) - if(self.enemy != other) + if(self.enemy != e) return FALSE; // team waypoints if(self.team && self.rule == SPRITERULE_DEFAULT) { - if(self.team != other.team) + if(self.team != e.team) return FALSE; - if(other.classname != "player") + if(e.classname != "player") return FALSE; } return TRUE; } +entity WaypointSprite_getviewentity(entity e) +{ + if(e.classname == "spectator") + e = e.enemy; + /* TODO idea (check this breaks nothing) + else if(e.classname == "observer") + e = world; + */ + return e; +} + +float WaypointSprite_isteammate(entity e, entity e2) +{ + if(teamplay) + { + if(e2.team != e.team) + return FALSE; + } + else + { + if(e2 != e) + return FALSE; + } + return TRUE; +} + float WaypointSprite_Customize() { // this is not in SendEntity because it shall run every frame, not just every update // make spectators see what the player would see entity e; - e = other; - if(e.classname == "spectator") - e = e.enemy; + e = WaypointSprite_getviewentity(other); + + // as a GENERAL rule: + // if you have the invisibility powerup, sprites ALWAYS are restricted to your team + // but only apply this to real players, not to spectators + if(g_minstagib && (self.owner.flags & FL_CLIENT) && (self.owner.items & IT_STRENGTH) && (e == other)) + { + if(!WaypointSprite_isteammate(self.owner, e)) + return FALSE; + } return self.waypointsprite_visible_for_player(e); } @@ -275,6 +322,18 @@ float WaypointSprite_SendEntity(entity to, float sendflags) WriteByte(MSG_ENTITY, self.colormod_x * 255.0); WriteByte(MSG_ENTITY, self.colormod_y * 255.0); WriteByte(MSG_ENTITY, self.colormod_z * 255.0); + + if(WaypointSprite_isteammate(self.owner, WaypointSprite_getviewentity(to))) + { + dt = (self.waypointsprite_helpmetime - time) / 0.1; + if(dt < 0) + dt = 0; + if(dt > 255) + dt = 255; + WriteByte(MSG_ENTITY, dt); + } + else + WriteByte(MSG_ENTITY, 0); } return TRUE; @@ -294,7 +353,8 @@ entity WaypointSprite_Spawn( entity ref, vector ofs, // position entity showto, float t, // show to whom? Use a flag to indicate a team entity own, .entity ownfield, // remove when own gets killed - float hideable // true when it should be controlled by cl_hidewaypoints + float hideable, // true when it should be controlled by cl_hidewaypoints + float icon, vector rgb // initial icon and color ) { entity wp; @@ -328,6 +388,8 @@ entity WaypointSprite_Spawn( wp.customizeentityforclient = WaypointSprite_Customize; wp.waypointsprite_visible_for_player = WaypointSprite_visible_for_player; wp.reset2 = WaypointSprite_Reset; + wp.cnt = icon; + wp.colormod = rgb; Net_LinkEntity(wp, FALSE, 0, WaypointSprite_SendEntity); return wp; } @@ -336,21 +398,23 @@ entity WaypointSprite_SpawnFixed( string spr, vector ofs, entity own, - .entity ownfield + .entity ownfield, + float icon, vector rgb // initial icon and color ) { - return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, own, ownfield, TRUE); + return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, own, ownfield, TRUE, icon, rgb); } .entity waypointsprite_deployed_fixed; entity WaypointSprite_DeployFixed( string spr, float limited_range, - vector ofs + vector ofs, + float icon, vector rgb // initial icon and color ) { float t, maxdistance; - if(teams_matter) + if(teamplay) t = self.team; else t = 0; @@ -358,29 +422,31 @@ entity WaypointSprite_DeployFixed( maxdistance = waypointsprite_limitedrange; else maxdistance = 0; - return WaypointSprite_Spawn(spr, waypointsprite_deployed_lifetime, maxdistance, world, ofs, world, t, self, waypointsprite_deployed_fixed, FALSE); + return WaypointSprite_Spawn(spr, waypointsprite_deployed_lifetime, maxdistance, world, ofs, world, t, self, waypointsprite_deployed_fixed, FALSE, icon, rgb); } .entity waypointsprite_deployed_personal; entity WaypointSprite_DeployPersonal( string spr, - vector ofs + vector ofs, + float icon, vector rgb // initial icon and color ) { - return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, self, waypointsprite_deployed_personal, FALSE); + return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, self, waypointsprite_deployed_personal, FALSE, icon, rgb); } .entity waypointsprite_attached; .entity waypointsprite_attachedforcarrier; entity WaypointSprite_Attach( string spr, - float limited_range + float limited_range, + float icon, vector rgb // initial icon and color ) { float t, maxdistance; if(self.waypointsprite_attachedforcarrier) return world; // can't attach to FC - if(teams_matter) + if(teamplay) t = self.team; else t = 0; @@ -388,17 +454,18 @@ entity WaypointSprite_Attach( maxdistance = waypointsprite_limitedrange; else maxdistance = 0; - return WaypointSprite_Spawn(spr, waypointsprite_deployed_lifetime, maxdistance, self, '0 0 64', world, t, self, waypointsprite_attached, FALSE); + return WaypointSprite_Spawn(spr, waypointsprite_deployed_lifetime, maxdistance, self, '0 0 64', world, t, self, waypointsprite_attached, FALSE, icon, rgb); } entity WaypointSprite_AttachCarrier( string spr, - entity carrier + entity carrier, + float icon, vector rgb // initial icon and color ) { entity e; WaypointSprite_Kill(carrier.waypointsprite_attached); // FC overrides attached - e = WaypointSprite_Spawn(spr, 0, 0, carrier, '0 0 64', world, carrier.team, carrier, waypointsprite_attachedforcarrier, FALSE); + e = WaypointSprite_Spawn(spr, 0, 0, carrier, '0 0 64', world, carrier.team, carrier, waypointsprite_attachedforcarrier, FALSE, icon, rgb); if(e) { WaypointSprite_UpdateMaxHealth(e, '1 0 0' * healtharmor_maxdamage(start_health, start_armorvalue, autocvar_g_balance_armor_blockpercent) * 2); diff --git a/qcsrc/warpzonelib/anglestransform.qc b/qcsrc/warpzonelib/anglestransform.qc index 56f72bfd75..3233f6a31c 100644 --- a/qcsrc/warpzonelib/anglestransform.qc +++ b/qcsrc/warpzonelib/anglestransform.qc @@ -84,11 +84,16 @@ vector AnglesTransform_TurnDirectionFU(vector transform) return transform; } -vector AnglesTransform_Divide(vector to_transform, vector from_transform) +vector AnglesTransform_RightDivide(vector to_transform, vector from_transform) { return AnglesTransform_Multiply(to_transform, AnglesTransform_Invert(from_transform)); } +vector AnglesTransform_LeftDivide(vector from_transform, vector to_transform) +{ + return AnglesTransform_Multiply(AnglesTransform_Invert(from_transform), to_transform); +} + vector AnglesTransform_Normalize(vector t, float minimize_roll) { float need_flip; diff --git a/qcsrc/warpzonelib/anglestransform.qh b/qcsrc/warpzonelib/anglestransform.qh index 045fb24b3a..b1c8a85e9d 100644 --- a/qcsrc/warpzonelib/anglestransform.qh +++ b/qcsrc/warpzonelib/anglestransform.qh @@ -11,11 +11,12 @@ void fixedmakevectors(vector a); #endif vector AnglesTransform_Apply(vector transform, vector v); -vector AnglesTransform_Multiply(vector t1, vector t2); +vector AnglesTransform_Multiply(vector t1, vector t2); // A B vector AnglesTransform_Invert(vector transform); vector AnglesTransform_TurnDirectionFU(vector transform); vector AnglesTransform_TurnDirectionFR(vector transform); -vector AnglesTransform_Divide(vector to_transform, vector from_transform); +vector AnglesTransform_RightDivide(vector to_transform, vector from_transform); // A B^-1 +vector AnglesTransform_LeftDivide(vector from_transform, vector to_transform); // A^-1 B vector AnglesTransform_Normalize(vector t, float minimize_roll); // makes sure all angles are in their range: yaw in -180..180, pitch in -90..90, roll in -180..180 (or if minimize_roll is set, pitch in -180..180, roll in -90..90) diff --git a/qcsrc/warpzonelib/client.qc b/qcsrc/warpzonelib/client.qc index f02fa4a302..a44b379745 100644 --- a/qcsrc/warpzonelib/client.qc +++ b/qcsrc/warpzonelib/client.qc @@ -1,7 +1,11 @@ void WarpZone_Fade_PreDraw() { if(self.warpzone_fadestart) - self.alpha = bound(0, (self.warpzone_fadeend - vlen(view_origin - self.origin - 0.5 * (self.mins + self.maxs))) / (self.warpzone_fadeend - self.warpzone_fadestart), 1); + { + vector org; + org = getpropertyvec(VF_ORIGIN); + self.alpha = bound(0, (self.warpzone_fadeend - vlen(org - self.origin - 0.5 * (self.mins + self.maxs))) / (self.warpzone_fadeend - self.warpzone_fadestart), 1); + } else self.alpha = 1; //print(sprintf("%v <-> %v\n", view_origin, self.origin + 0.5 * (self.mins + self.maxs))); @@ -141,31 +145,47 @@ void WarpZone_Camera_Read(float isnew) self.drawmask = MASK_NORMAL; } -float warpzone_fixingview; -float warpzone_fixingview_drawexteriormodel; -//float warpzone_fixingview_sidespeed; -//float warpzone_fixingview_forwardspeed; -void WarpZone_Inside() +void CL_RotateMoves(vector ang) = #638; +void WarpZone_Teleported_Read(float isnew) { - if(warpzone_fixingview) + vector v; + self.classname = "warpzone_teleported"; + v_x = ReadCoord(); + v_y = ReadCoord(); + v_z = ReadCoord(); + if(!isnew) return; - warpzone_fixingview = 1; - warpzone_fixingview_drawexteriormodel = cvar("r_drawexteriormodel"); - //warpzone_fixingview_sidespeed = cvar("cl_sidespeed"); - //warpzone_fixingview_forwardspeed = cvar("cl_forwardspeed"); - cvar_set("r_drawexteriormodel", "0"); - //cvar_set("cl_sidespeed", ftos(warpzone_fixingview_sidespeed / 100)); // just keep a bit of it in case player gets stuck - //cvar_set("cl_forwardspeed", ftos(warpzone_fixingview_forwardspeed / 100)); // just keep a bit of it in case player gets stuck + self.warpzone_transform = v; + setproperty(VF_CL_VIEWANGLES, WarpZone_TransformVAngles(self, getpropertyvec(VF_CL_VIEWANGLES))); + if(checkextension("DP_CSQC_ROTATEMOVES")) + CL_RotateMoves(v); + //CL_RotateMoves('0 90 0'); } -void WarpZone_Outside() +float warpzone_fixingview; +float warpzone_fixingview_drawexteriormodel; +float autocvar_chase_active; + +void WarpZone_View_Outside() { if(!warpzone_fixingview) return; warpzone_fixingview = 0; cvar_set("r_drawexteriormodel", ftos(warpzone_fixingview_drawexteriormodel)); - //cvar_set("cl_sidespeed", ftos(warpzone_fixingview_sidespeed)); - //cvar_set("cl_forwardspeed", ftos(warpzone_fixingview_forwardspeed)); +} + +void WarpZone_View_Inside() +{ + if(autocvar_chase_active) + { + WarpZone_View_Outside(); + return; + } + if(warpzone_fixingview) + return; + warpzone_fixingview = 1; + warpzone_fixingview_drawexteriormodel = cvar("r_drawexteriormodel"); + cvar_set("r_drawexteriormodel", "0"); } vector WarpZone_FixNearClip(vector o, vector c0, vector c1, vector c2, vector c3) @@ -174,12 +194,12 @@ vector WarpZone_FixNearClip(vector o, vector c0, vector c1, vector c2, vector c3 entity e; float pd; - mi_x = min5(o_x, c0_x, c1_x, c2_x, c3_x); - ma_x = max5(o_x, c0_x, c1_x, c2_x, c3_x); - mi_y = min5(o_y, c0_y, c1_y, c2_y, c3_y); - ma_y = max5(o_y, c0_y, c1_y, c2_y, c3_y); - mi_z = min5(o_z, c0_z, c1_z, c2_z, c3_z); - ma_z = max5(o_z, c0_z, c1_z, c2_z, c3_z); + mi_x = min(o_x, c0_x, c1_x, c2_x, c3_x); + ma_x = max(o_x, c0_x, c1_x, c2_x, c3_x); + mi_y = min(o_y, c0_y, c1_y, c2_y, c3_y); + ma_y = max(o_y, c0_y, c1_y, c2_y, c3_y); + mi_z = min(o_z, c0_z, c1_z, c2_z, c3_z); + ma_z = max(o_z, c0_z, c1_z, c2_z, c3_z); e = WarpZone_Find(mi, ma); if(e) @@ -187,7 +207,7 @@ vector WarpZone_FixNearClip(vector o, vector c0, vector c1, vector c2, vector c3 if(WarpZone_PlaneDist(e, o) < 0) return '0 0 0'; // can't really be, though, but if it is, this is not my warpzone, but a random different one in the same mins/maxs - pd = min4( + pd = min( WarpZone_PlaneDist(e, c0), WarpZone_PlaneDist(e, c1), WarpZone_PlaneDist(e, c2), @@ -200,88 +220,82 @@ vector WarpZone_FixNearClip(vector o, vector c0, vector c1, vector c2, vector c3 return '0 0 0'; } -float warpzone_saved; -vector warpzone_saved_origin; -vector warpzone_saved_angles; -vector warpzone_saved_cl_viewangles; +void WarpZone_FixPMove() +{ + entity e; + e = WarpZone_Find(pmove_org, pmove_org); + if(e) + { + pmove_org = WarpZone_TransformOrigin(e, pmove_org); + input_angles = WarpZone_TransformVAngles(e, input_angles); + } +} + #ifndef KEEP_ROLL var float autocvar_cl_rollkillspeed = 10; #endif void WarpZone_FixView() { - float f; - vector o; entity e; - vector corner0, corner1, corner2, corner3, nearclip; - - warpzone_saved = 0; - warpzone_saved_origin = warpzone_fixview_origin; - warpzone_saved_angles = warpzone_fixview_angles; - warpzone_saved_cl_viewangles = warpzone_fixview_cl_viewangles; - - nearclip = '0 0 1' * (cvar("r_nearclip") * 1.125); - corner0 = cs_unproject('0 0 0' + nearclip); - corner1 = cs_unproject('1 0 0' * cvar("vid_conwidth") + nearclip); - corner2 = cs_unproject('0 1 0' * cvar("vid_conheight") + nearclip); - corner3 = cs_unproject('1 0 0' * cvar("vid_conwidth") + '0 1 0' * cvar("vid_conheight") + nearclip); + vector org, ang, nearclip, corner0, corner1, corner2, corner3, o; + float f; -#ifndef KEEP_ROLL - if(warpzone_fixview_angles_z != 0 || warpzone_fixview_cl_viewangles_z != 0) - { - if(autocvar_cl_rollkillspeed) - f = max(0, (1 - frametime * autocvar_cl_rollkillspeed)); - else - f = 0; - warpzone_fixview_angles_z *= f; - warpzone_fixview_cl_viewangles_z *= f; - warpzone_saved_angles_z *= f; // PERMANENTLY apply that change! - warpzone_saved_cl_viewangles_z *= f; // PERMANENTLY apply that change! - warpzone_saved = 2; - R_SetView(VF_CL_VIEWANGLES_Z, warpzone_fixview_angles_z); - } + org = getpropertyvec(VF_ORIGIN); + ang = getpropertyvec(VF_ANGLES); +#ifdef WORKAROUND_XON010 + float dirty; + dirty = checkextension("DP_CSQC_ROTATEMOVES"); #endif - e = WarpZone_Find(warpzone_fixview_origin, warpzone_fixview_origin); + e = WarpZone_Find(org, org); if(e) { - warpzone_saved = 1; - warpzone_fixview_origin = WarpZone_TransformOrigin(e, warpzone_fixview_origin); - corner0 = WarpZone_TransformOrigin(e, corner0); - corner1 = WarpZone_TransformOrigin(e, corner1); - corner2 = WarpZone_TransformOrigin(e, corner2); - corner3 = WarpZone_TransformOrigin(e, corner3); - warpzone_fixview_angles = WarpZone_TransformVAngles(e, warpzone_fixview_angles); - warpzone_fixview_cl_viewangles = WarpZone_TransformVAngles(e, warpzone_fixview_cl_viewangles); - WarpZone_Inside(); + org = WarpZone_TransformOrigin(e, org); + ang = WarpZone_TransformVAngles(e, ang); +#ifdef WORKAROUND_XON010 + dirty = 1; +#endif + WarpZone_View_Inside(); } else - WarpZone_Outside(); + WarpZone_View_Outside(); - // if we are near any warpzone planes - MOVE AWAY (work around nearclip) - o = WarpZone_FixNearClip(warpzone_fixview_origin, corner0, corner1, corner2, corner3); - if(o != '0 0 0') - { - warpzone_saved = 1; - warpzone_fixview_origin += o; - } +#ifndef KEEP_ROLL + float rick; + if(autocvar_cl_rollkillspeed) + f = max(0, (1 - frametime * autocvar_cl_rollkillspeed)); + else + f = 0; - if(warpzone_saved == 1) - { - R_SetView(VF_ORIGIN, warpzone_fixview_origin); - R_SetView(VF_ANGLES, warpzone_fixview_cl_viewangles); - } -} -void WarpZone_UnFixView() -{ - if(warpzone_saved) + rick = getproperty(VF_CL_VIEWANGLES_Z); + rick *= f; + setproperty(VF_CL_VIEWANGLES_Z, rick); + +#ifdef WORKAROUND_XON010 + if(ang_z > 1 || ang_z < -1) + dirty = 1; +#endif + ang_z *= f; +#endif + +#ifdef WORKAROUND_XON010 + if(dirty) { - warpzone_fixview_origin = warpzone_saved_origin; - warpzone_fixview_angles = warpzone_saved_angles; - warpzone_fixview_cl_viewangles = warpzone_saved_cl_viewangles; - R_SetView(VF_ORIGIN, warpzone_fixview_origin); - R_SetView(VF_ANGLES, warpzone_fixview_angles); - R_SetView(VF_CL_VIEWANGLES, warpzone_fixview_cl_viewangles); +#endif + setproperty(VF_ORIGIN, org); + setproperty(VF_ANGLES, ang); +#ifdef WORKAROUND_XON010 } +#endif + + nearclip = '0 0 1' * (cvar("r_nearclip") * 1.125); + corner0 = cs_unproject('0 0 0' + nearclip); + corner1 = cs_unproject('1 0 0' * cvar("vid_conwidth") + nearclip); + corner2 = cs_unproject('0 1 0' * cvar("vid_conheight") + nearclip); + corner3 = cs_unproject('1 0 0' * cvar("vid_conwidth") + '0 1 0' * cvar("vid_conheight") + nearclip); + o = WarpZone_FixNearClip(org, corner0, corner1, corner2, corner3); + if(o != '0 0 0') + setproperty(VF_ORIGIN, org + o); } void WarpZone_Init() @@ -290,5 +304,5 @@ void WarpZone_Init() void WarpZone_Shutdown() { - WarpZone_Outside(); + WarpZone_View_Outside(); } diff --git a/qcsrc/warpzonelib/client.qh b/qcsrc/warpzonelib/client.qh index e8f44be136..446c917dbf 100644 --- a/qcsrc/warpzonelib/client.qh +++ b/qcsrc/warpzonelib/client.qh @@ -1,11 +1,9 @@ void WarpZone_Read(float bIsNewEntity); void WarpZone_Camera_Read(float bIsNewEntity); +void WarpZone_Teleported_Read(float bIsNewEntity); -vector warpzone_fixview_origin; -vector warpzone_fixview_angles; -vector warpzone_fixview_cl_viewangles; -void WarpZone_FixView(); // this saves the previous values -void WarpZone_UnFixView(); // and restores them +void WarpZone_FixPMove(); +void WarpZone_FixView(); void WarpZone_Init(); void WarpZone_Shutdown(); diff --git a/qcsrc/warpzonelib/common.qc b/qcsrc/warpzonelib/common.qc index 62e7468209..f09f25bdcd 100644 --- a/qcsrc/warpzonelib/common.qc +++ b/qcsrc/warpzonelib/common.qc @@ -52,7 +52,7 @@ vector WarpZone_camera_transform(vector org, vector ang) void WarpZone_SetUp(entity e, vector my_org, vector my_ang, vector other_org, vector other_ang) { - e.warpzone_transform = AnglesTransform_Divide(other_ang, AnglesTransform_TurnDirectionFR(my_ang)); + e.warpzone_transform = AnglesTransform_RightDivide(other_ang, AnglesTransform_TurnDirectionFR(my_ang)); e.warpzone_shift = AnglesTransform_PrePostShift_GetPostShift(my_org, e.warpzone_transform, other_org); e.warpzone_origin = my_org; e.warpzone_targetorigin = other_org; @@ -191,6 +191,7 @@ void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end, entity wz; vector vf, vr, vu; + WarpZone_trace_forent = forent; WarpZone_trace_firstzone = world; WarpZone_trace_lastzone = world; WarpZone_Trace_InitTransform(); @@ -206,7 +207,7 @@ void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end, } else { - tracebox(org, mi, ma, end, nomonsters, forent); + tracebox(org, mi, ma, end, nomonsters, WarpZone_trace_forent); if(cb) cb(org, trace_endpos, end); return; @@ -229,8 +230,8 @@ void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end, nomonsters_adjusted = nomonsters; break; } - if((contentshack = (forent.dphitcontentsmask && !(forent.dphitcontentsmask & DPCONTENTS_SOLID)))) - forent.dphitcontentsmask |= DPCONTENTS_SOLID; + if((contentshack = (WarpZone_trace_forent.dphitcontentsmask && !(WarpZone_trace_forent.dphitcontentsmask & DPCONTENTS_SOLID)))) + BITSET_ASSIGN(WarpZone_trace_forent.dphitcontentsmask, DPCONTENTS_SOLID); // if starting in warpzone, first transform wz = WarpZone_Find(org + mi, org + ma); @@ -262,7 +263,7 @@ void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end, trace_ent = world; break; } - tracebox(org, mi, ma, end, nomonsters_adjusted, forent); + tracebox(org, mi, ma, end, nomonsters_adjusted, WarpZone_trace_forent); if(cb) cb(org, trace_endpos, end); if(sol < 0) @@ -273,7 +274,7 @@ void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end, break; if(trace_ent.classname != "trigger_warpzone") { - if((nomonsters == MOVE_NOTHING) || ((nomonsters == MOVE_WORLDONLY) && trace_ent) || (contentshack && (trace_dphitcontents & forent.dphitcontentsmask) == DPCONTENTS_SOLID)) + if((nomonsters == MOVE_NOTHING) || ((nomonsters == MOVE_WORLDONLY) && trace_ent) || (contentshack && (trace_dphitcontents & WarpZone_trace_forent.dphitcontentsmask) == DPCONTENTS_SOLID)) { // continue the trace, ignoring this hit (we only care for warpzones) org = trace_endpos + normalize(end - org); @@ -300,11 +301,15 @@ void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end, // we hit a warpzone... so, let's perform the trace after the warp again org = WarpZone_TransformOrigin(wz, trace_endpos); end = WarpZone_TransformOrigin(wz, end); + + // we got warped, so let's step back a bit + tracebox(org, mi, ma, org + normalize(org - end) * 32, nomonsters_adjusted, WarpZone_trace_forent); + org = trace_endpos; } WarpZone_MakeAllOther(); :fail if(contentshack) - forent.dphitcontentsmask &~= DPCONTENTS_SOLID; + BITCLR_ASSIGN(WarpZone_trace_forent.dphitcontentsmask, DPCONTENTS_SOLID); trace_startsolid = sol; v_forward = vf; v_right = vr; @@ -330,13 +335,14 @@ void WarpZone_TraceToss_ThroughZone(entity e, entity forent, entity zone, WarpZo o0 = e.origin; v0 = e.velocity; + WarpZone_trace_forent = forent; WarpZone_trace_firstzone = world; WarpZone_trace_lastzone = world; WarpZone_Trace_InitTransform(); WarpZone_tracetoss_time = 0; if(!warpzone_warpzones_exist) { - tracetoss(e, forent); + tracetoss(e, WarpZone_trace_forent); if(cb) cb(e.origin, trace_endpos, trace_endpos); dt = vlen(e.origin - o0) / vlen(e.velocity); @@ -380,12 +386,12 @@ void WarpZone_TraceToss_ThroughZone(entity e, entity forent, entity zone, WarpZo trace_ent = world; break; } - tracetoss(e, forent); + tracetoss(e, WarpZone_trace_forent); if(cb) cb(e.origin, trace_endpos, trace_endpos); - e.origin = trace_endpos; - dt = vlen(e.origin - o0) / vlen(e.velocity); + dt = vlen(trace_endpos - e.origin) / vlen(e.velocity); WarpZone_tracetoss_time += dt; + e.origin = trace_endpos; e.velocity_z -= dt * g; if(trace_fraction >= 1) break; @@ -408,6 +414,14 @@ void WarpZone_TraceToss_ThroughZone(entity e, entity forent, entity zone, WarpZo // we hit a warpzone... so, let's perform the trace after the warp again e.origin = WarpZone_TransformOrigin(wz, e.origin); e.velocity = WarpZone_TransformVelocity(wz, e.velocity); + + // we got warped, so let's step back a bit + e.velocity = -e.velocity; + tracetoss(e, WarpZone_trace_forent); + dt = vlen(trace_endpos - e.origin) / vlen(e.velocity); + WarpZone_tracetoss_time -= dt; + e.origin = trace_endpos; + e.velocity = -e.velocity; } WarpZone_MakeAllOther(); :fail @@ -663,7 +677,7 @@ void WarpZone_RefSys_AddIncrementally(entity me, entity ref) t = AnglesTransform_Invert(me.WarpZone_refsys_incremental_transform); s = AnglesTransform_PrePostShift_GetPostShift(me.WarpZone_refsys_incremental_shift, t, '0 0 0'); WarpZone_Accumulator_AddTransform(me.WarpZone_refsys, t, s); - WarpZone_Accumulator_Add(me.WarpZone_refsys, ref); + WarpZone_Accumulator_Add(me.WarpZone_refsys, ref.WarpZone_refsys); me.WarpZone_refsys_incremental_shift = ref.WarpZone_refsys.warpzone_shift; me.WarpZone_refsys_incremental_transform = ref.WarpZone_refsys.warpzone_transform; } diff --git a/qcsrc/warpzonelib/common.qh b/qcsrc/warpzonelib/common.qh index 72485f25c4..c2f36bea86 100644 --- a/qcsrc/warpzonelib/common.qh +++ b/qcsrc/warpzonelib/common.qh @@ -4,8 +4,6 @@ float warpzone_warpzones_exist; float warpzone_cameras_exist; -const void func_null(void); // never assign to this one please - .float warpzone_isboxy; .vector warpzone_shift; .vector warpzone_origin; @@ -27,6 +25,7 @@ void WarpZone_MakeAllSolid(); void WarpZone_MakeAllOther(); #define MOVE_NOTHING -1 +entity WarpZone_trace_forent; // temp, callback is allowed to change it typedef void(vector start, vector hit, vector end) WarpZone_trace_callback_t; // called on every elementary trace const var WarpZone_trace_callback_t WarpZone_trace_callback_t_null; entity WarpZone_trace_transform; // transform accumulator during a trace @@ -71,3 +70,22 @@ vector WarpZone_RefSys_TransformVelocity(entity from, entity to, vector vel); vector WarpZone_RefSys_TransformAngles(entity from, entity to, vector ang); vector WarpZone_RefSys_TransformVAngles(entity from, entity to, vector ang); entity WarpZone_RefSys_SpawnSameRefSys(entity me); + +#ifndef BITCLR +# define BITCLR(a,b) ((a) - ((a) & (b))) +#endif +#ifndef BITSET +# define BITSET(a,b) ((a) | (b)) +#endif +#ifndef BITXOR +# define BITXOR(a,b) (((a) | (b)) - ((a) & (b))) +#endif +#ifndef BITCLR_ASSIGN +# define BITCLR_ASSIGN(a,b) ((a) = (a) - ((a) & (b))) +#endif +#ifndef BITSET_ASSIGN +# define BITSET_ASSIGN(a,b) ((a) |= (b)) +#endif +#ifndef BITXOR_ASSIGN +# define BITXOR_ASSIGN(a,b) ((a) = ((a) | (b)) - ((a) & (b))) +#endif diff --git a/qcsrc/warpzonelib/mathlib.qc b/qcsrc/warpzonelib/mathlib.qc index b460a063db..42262102e5 100644 --- a/qcsrc/warpzonelib/mathlib.qc +++ b/qcsrc/warpzonelib/mathlib.qc @@ -18,7 +18,9 @@ int isinf(float x) } int isnan(float x) { - return !(x + x == x + x); + float y; + y = x; + return (x != y); } int isnormal(float x) { diff --git a/qcsrc/warpzonelib/server.qc b/qcsrc/warpzonelib/server.qc index f4141c8a3d..6c27842ef2 100644 --- a/qcsrc/warpzonelib/server.qc +++ b/qcsrc/warpzonelib/server.qc @@ -1,5 +1,16 @@ +#define REMOVEHACK + +// for think function +.vector warpzone_save_origin; +.vector warpzone_save_angles; +.vector warpzone_save_eorigin; +.vector warpzone_save_eangles; + +// for all entities .vector warpzone_oldorigin, warpzone_oldvelocity, warpzone_oldangles; .float warpzone_teleport_time; +.float warpzone_teleport_finishtime; +.entity warpzone_teleport_zone; void WarpZone_StoreProjectileData(entity e) { @@ -10,106 +21,160 @@ void WarpZone_StoreProjectileData(entity e) void WarpZone_TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity) { - vector from; - - makevectors (to_angles); - - from = player.origin; - setorigin (player, to); + setorigin (player, to); // NOTE: this also aborts the move, when this is called by touch player.oldorigin = to; // for DP's unsticking player.angles = to_angles; player.fixangle = TRUE; player.velocity = to_velocity; - if(player.effects & EF_TELEPORT_BIT) - player.effects &~= EF_TELEPORT_BIT; - else - player.effects |= EF_TELEPORT_BIT; + BITXOR_ASSIGN(player.effects, EF_TELEPORT_BIT); if(player.classname == "player") - player.flags &~= FL_ONGROUND; + BITCLR_ASSIGN(player.flags, FL_ONGROUND); WarpZone_PostTeleportPlayer_Callback(player); } -float WarpZone_Teleport(entity player) +float WarpZone_Teleported_Send(entity to, float sf) { - vector o0, a0, v0, o1, a1, v1; + WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE_TELEPORTED); + WriteCoord(MSG_ENTITY, self.angles_x); + WriteCoord(MSG_ENTITY, self.angles_y); + WriteCoord(MSG_ENTITY, self.angles_z); + return TRUE; +} + +float WarpZone_Teleport(entity wz, entity player, float f0, float f1) +{ + vector o0, a0, v0, o1, a1, v1, o10; o0 = player.origin + player.view_ofs; v0 = player.velocity; a0 = player.angles; - if(WarpZone_PlaneDist(self, o0) >= 0) // wrong side of the trigger_warpzone - return 2; - // no failure, we simply don't want to teleport yet; TODO in - // this situation we may want to create a temporary clone - // entity of the player to fix graphics glitch - - o1 = WarpZone_TransformOrigin(self, o0); - v1 = WarpZone_TransformVelocity(self, v0); + o10 = o1 = WarpZone_TransformOrigin(wz, o0); + v1 = WarpZone_TransformVelocity(wz, v0); if(clienttype(player) != CLIENTTYPE_NOTACLIENT) - a1 = WarpZone_TransformVAngles(self, player.v_angle); + a1 = WarpZone_TransformVAngles(wz, player.v_angle); else - a1 = WarpZone_TransformAngles(self, a0); + a1 = WarpZone_TransformAngles(wz, a0); + + if(f0 != 0 || f1 != 0) + { + // retry last move but behind the warpzone! + // we must first go back as far as we can, then forward again, to not cause double touch events! + + tracebox(o1 - player.view_ofs + v1 * frametime * f1, player.mins, player.maxs, o1 - player.view_ofs + v1 * frametime * f0, MOVE_WORLDONLY, player); + { + entity own; + own = player.owner; + player.owner = world; + tracebox(trace_endpos, player.mins, player.maxs, o1 - player.view_ofs + v1 * frametime * f1, MOVE_NORMAL, player); // this should get us through the warpzone + player.owner = own; + } + o1 = trace_endpos + player.view_ofs; + + float d, dv, md; + md = max(vlen(player.mins), vlen(player.maxs)); + d = WarpZone_TargetPlaneDist(wz, o1); + dv = WarpZone_TargetPlaneDist(wz, v1); + if(d < 0) + o1 = o1 - v1 * (d / dv); + } - // put him inside solid + // put him out of solid tracebox(o1 - player.view_ofs, player.mins, player.maxs, o1 - player.view_ofs, MOVE_NOMONSTERS, player); if(trace_startsolid) { - vector mi, ma; - mi = player.mins; - ma = player.maxs; - setsize(player, mi - player.view_ofs, ma - player.view_ofs); - setorigin(player, o1); + setorigin(player, o1 - player.view_ofs); if(WarpZoneLib_MoveOutOfSolid(player)) { - o1 = player.origin; - setsize(player, mi, ma); - setorigin(player, o0); + o1 = player.origin + player.view_ofs; + setorigin(player, o0 - player.view_ofs); } else { print("would have to put player in solid, won't do that\n"); - setsize(player, mi, ma); setorigin(player, o0 - player.view_ofs); - return 0; // cannot fix + return 0; } } - if(WarpZone_TargetPlaneDist(self, o1) <= 0) - { - print("inconsistent warp zones or evil roundoff error\n"); - return 0; - } - - //print(sprintf("warpzone: %f %f %f -> %f %f %f\n", o0_x, o0_y, o0_z, o1_x, o1_y, o1_z)); - - //o1 = trace_endpos; - WarpZone_RefSys_Add(player, self); - WarpZone_TeleportPlayer(self, player, o1 - player.view_ofs, a1, v1); + // do the teleport + WarpZone_RefSys_Add(player, wz); + WarpZone_TeleportPlayer(wz, player, o1 - player.view_ofs, a1, v1); WarpZone_StoreProjectileData(player); player.warpzone_teleport_time = time; + player.warpzone_teleport_finishtime = time; + player.warpzone_teleport_zone = wz; + + // prevent further teleports back + float dt = (o1 - o10) * v1 * (1 / (v1 * v1)); + if(dt < sys_frametime) + player.warpzone_teleport_finishtime += sys_frametime - dt; + +#ifndef WARPZONE_USE_FIXANGLE + if(player.classname == "player") + { + // instead of fixangle, send the transform to the client for smoother operation + player.fixangle = FALSE; + + entity ts = spawn(); + setmodel(ts, "null"); + ts.SendEntity = WarpZone_Teleported_Send; + ts.SendFlags = 0xFFFFFF; + ts.drawonlytoclient = player; + ts.think = SUB_Remove; + ts.nextthink = time + 1; + ts.owner = player; + ts.enemy = wz; + ts.effects = EF_NODEPTHTEST; + ts.classname = "warpzone_teleported"; + ts.angles = wz.warpzone_transform; + } +#endif return 1; } void WarpZone_Touch (void) { - entity oldself, e; + entity oldself; if(other.classname == "trigger_warpzone") return; + if(time <= other.warpzone_teleport_finishtime) // already teleported this frame + return; + // FIXME needs a better check to know what is safe to teleport and what not - if(other.movetype == MOVETYPE_NONE) + if(other.movetype == MOVETYPE_NONE || other.movetype == MOVETYPE_FOLLOW || other.tag_entity) return; if(WarpZoneLib_ExactTrigger_Touch()) return; - e = self.enemy; - if(WarpZone_Teleport(other)) + if(WarpZone_PlaneDist(self, other.origin + other.view_ofs) >= 0) // wrong side of the trigger_warpzone (don't teleport yet) + return; + + float f; + // number of frames we need to go back: + // dist = 16*sqrt(2) qu + // dist ~ 24 qu + // 24 qu = v*t + // 24 qu = v*frametime*n + // n = 24 qu/(v*frametime) + // for clients go only one frame though, may be too irritating otherwise + // but max 0.25 sec = 0.25/frametime frames + // 24/(0.25/frametime) + // 96*frametime + float d; + d = 24 + max(vlen(other.mins), vlen(other.maxs)); + if(clienttype(other) == CLIENTTYPE_NOTACLIENT) + f = -d / bound(frametime * d * 1, frametime * vlen(other.velocity), d); + else + f = -1; + if(WarpZone_Teleport(self, other, f, 0)) { string save1, save2; activator = other; @@ -143,11 +208,11 @@ float WarpZone_Send(entity to, float sendflags) // we must send this flag for clientside to match properly too f = 0; if(self.warpzone_isboxy) - f |= 1; + BITSET_ASSIGN(f, 1); if(self.warpzone_fadestart) - f |= 2; + BITSET_ASSIGN(f, 2); if(self.origin != '0 0 0') - f |= 4; + BITSET_ASSIGN(f, 4); WriteByte(MSG_ENTITY, f); // we need THESE to render the warpzone (and cull properly)... @@ -196,9 +261,9 @@ float WarpZone_Camera_Send(entity to, float sendflags) WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE_CAMERA); if(self.warpzone_fadestart) - f |= 2; + BITSET_ASSIGN(f, 2); if(self.origin != '0 0 0') - f |= 4; + BITSET_ASSIGN(f, 4); WriteByte(MSG_ENTITY, f); // we need THESE to render the warpzone (and cull properly)... @@ -235,73 +300,129 @@ float WarpZone_Camera_Send(entity to, float sendflags) return TRUE; } -float WarpZone_CheckProjectileImpact() +float WarpZone_CheckProjectileImpact(entity player) { - // if self hit a warpzone, abort - vector o0, v0, a0; - float mpd, pd, dpd; + vector o0, v0; + + o0 = player.origin + player.view_ofs; + v0 = player.velocity; + + // if we teleported shortly before, abort + if(time <= player.warpzone_teleport_finishtime + 0.1) + return 0; + + // if player hit a warpzone, abort entity wz; - wz = WarpZone_Find(self.origin + self.mins, self.origin + self.maxs); + wz = WarpZone_Find(o0 + player.mins, o0 + player.maxs); if(!wz) return 0; - if(self.warpzone_teleport_time == time) + +#ifdef REMOVEHACK + print("impactfilter found something - and it no longer gets handled correctly - please tell divVerent whether anything behaves broken now\n"); +#else + print("impactfilter found something - and it even gets handled correctly - please tell divVerent that this code apparently gets triggered again\n"); +#endif + print("Entity type: ", player.classname, "\n"); + print("Origin: ", vtos(player.origin), "\n"); + print("Velocity: ", vtos(player.velocity), "\n"); + +#ifdef REMOVEHACK + return 0; +#else + // retry previous move + setorigin(player, player.warpzone_oldorigin); + player.velocity = player.warpzone_oldvelocity; + if(WarpZone_Teleport(wz, player, 0, 1)) { - // just ignore if we got teleported this frame already and now hit a wall and are in a warpzone again (this will cause a detonation) - // print("2 warps 1 frame\n"); - return -1; - } - o0 = self.origin; - v0 = self.velocity; - a0 = self.angles; - - // this approach transports the projectile at its full speed, but does - // not properly retain the projectile trail (but we can't retain it - // easily anyway without delaying the projectile by two frames, so who - // cares) - WarpZone_TraceBox_ThroughZone(self.warpzone_oldorigin, self.mins, self.maxs, self.warpzone_oldorigin + self.warpzone_oldvelocity * frametime, MOVE_NORMAL, self, wz, WarpZone_trace_callback_t_null); // this will get us through the warpzone - setorigin(self, trace_endpos); - self.angles = WarpZone_TransformAngles(WarpZone_trace_transform, self.angles); - self.velocity = WarpZone_TransformVelocity(WarpZone_trace_transform, self.warpzone_oldvelocity); - - // in case we are in our warp zone post-teleport, shift the projectile forward a bit - mpd = max(vlen(self.mins), vlen(self.maxs)); - pd = WarpZone_TargetPlaneDist(wz, self.origin); - if(pd < mpd) + entity oldself; + string save1, save2; + + oldself = self; + self = wz; + other = player; + activator = player; + + save1 = self.target; self.target = string_null; + save2 = self.target3; self.target3 = string_null; + SUB_UseTargets(); + if not(self.target) self.target = save1; + if not(self.target3) self.target3 = save2; + + self = self.enemy; + save1 = self.target; self.target = string_null; + save2 = self.target2; self.target2 = string_null; + SUB_UseTargets(); + if not(self.target) self.target = save1; + if not(self.target2) self.target2 = save2; + self = oldself; + } + else { - dpd = normalize(self.velocity) * wz.warpzone_targetforward; - setorigin(self, self.origin + normalize(self.velocity) * ((mpd - pd) / dpd)); - if(!WarpZoneLib_MoveOutOfSolid(self)) - { - setorigin(self, o0); - self.angles = a0; - self.velocity = v0; - return 0; - } + setorigin(player, o0 - player.view_ofs); + player.velocity = v0; } - WarpZone_RefSys_Add(self, wz); - WarpZone_StoreProjectileData(self); - self.warpzone_teleport_time = time; return +1; +#endif } float WarpZone_Projectile_Touch() { float f; if(other.classname == "trigger_warpzone") return TRUE; - if(WarpZone_Projectile_Touch_ImpactFilter_Callback()) + + // no further impacts if we teleported this frame! + if(time == self.warpzone_teleport_time) return TRUE; - if((f = WarpZone_CheckProjectileImpact()) != 0) - return (f > 0); - if(self.warpzone_teleport_time == time) + + // this SEEMS to not happen at the moment, but if it did, it would be more reliable { - // sequence: hit warpzone, get teleported, hit wall - // print("2 hits 1 frame\n"); - setorigin(self, self.warpzone_oldorigin); - self.velocity = self.warpzone_oldvelocity; - self.angles = self.warpzone_oldangles; - return TRUE; + float save_dpstartcontents; + float save_dphitcontents; + float save_dphitq3surfaceflags; + string save_dphittexturename; + float save_allsolid; + float save_startsolid; + float save_fraction; + vector save_endpos; + vector save_plane_normal; + float save_plane_dist; + entity save_ent; + float save_inopen; + float save_inwater; + save_dpstartcontents = trace_dpstartcontents; + save_dphitcontents = trace_dphitcontents; + save_dphitq3surfaceflags = trace_dphitq3surfaceflags; + save_dphittexturename = trace_dphittexturename; + save_allsolid = trace_allsolid; + save_startsolid = trace_startsolid; + save_fraction = trace_fraction; + save_endpos = trace_endpos; + save_plane_normal = trace_plane_normal; + save_plane_dist = trace_plane_dist; + save_ent = trace_ent; + save_inopen = trace_inopen; + save_inwater = trace_inwater; + if((f = WarpZone_CheckProjectileImpact(self)) != 0) + return (f > 0); + trace_dpstartcontents = save_dpstartcontents; + trace_dphitcontents = save_dphitcontents; + trace_dphitq3surfaceflags = save_dphitq3surfaceflags; + trace_dphittexturename = save_dphittexturename; + trace_allsolid = save_allsolid; + trace_startsolid = save_startsolid; + trace_fraction = save_fraction; + trace_endpos = save_endpos; + trace_plane_normal = save_plane_normal; + trace_plane_dist = save_plane_dist; + trace_ent = save_ent; + trace_inopen = save_inopen; + trace_inwater = save_inwater; } + + if(WarpZone_Projectile_Touch_ImpactFilter_Callback()) + return TRUE; + return FALSE; } @@ -341,6 +462,22 @@ void WarpZonePosition_InitStep_FindTarget() self.enemy.aiment = self; } +void WarpZoneCamera_Think(void) +{ + if(self.warpzone_save_origin != self.origin + || self.warpzone_save_angles != self.angles + || self.warpzone_save_eorigin != self.enemy.origin + || self.warpzone_save_eangles != self.enemy.angles) + { + WarpZone_Camera_SetUp(self, self.enemy.origin, self.enemy.angles); + self.warpzone_save_origin = self.origin; + self.warpzone_save_angles = self.angles; + self.warpzone_save_eorigin = self.enemy.origin; + self.warpzone_save_eangles = self.enemy.angles; + } + self.nextthink = time; +} + void WarpZoneCamera_InitStep_FindTarget() { entity e; @@ -362,6 +499,13 @@ void WarpZoneCamera_InitStep_FindTarget() warpzone_cameras_exist = 1; WarpZone_Camera_SetUp(self, self.enemy.origin, self.enemy.angles); self.SendFlags = 0xFFFFFF; + if(self.spawnflags & 1) + { + self.think = WarpZoneCamera_Think; + self.nextthink = time; + } + else + self.nextthink = 0; } void WarpZone_InitStep_UpdateTransform() @@ -383,7 +527,7 @@ void WarpZone_InitStep_UpdateTransform() tex = getsurfacetexture(self, i_s); if not(tex) break; // this is beyond the last one - if(tex == "textures/common/trigger") + if(tex == "textures/common/trigger" || tex == "trigger") continue; n_t = getsurfacenumtriangles(self, i_s); for(i_t = 0; i_t < n_t; ++i_t) @@ -427,7 +571,7 @@ void WarpZone_InitStep_UpdateTransform() print("Position target of trigger_warpzone near ", vtos(self.aiment.origin), " points into trigger_warpzone. BEWARE.\n"); norm = -1 * norm; } - ang = vectoangles(norm, v_up); // keep rotation, but turn exactly against plane + ang = vectoangles2(norm, v_up); // keep rotation, but turn exactly against plane ang_x = -ang_x; if(norm * v_forward < 0.99) print("trigger_warpzone near ", vtos(self.aiment.origin), " has been turned to match plane orientation (", vtos(self.aiment.angles), " -> ", vtos(ang), "\n"); @@ -486,6 +630,7 @@ void WarpZone_InitStep_FindTarget() } } +void WarpZone_Think(); void WarpZone_InitStep_FinalizeTransform() { if(!self.enemy || self.enemy.enemy != self) @@ -498,6 +643,13 @@ void WarpZone_InitStep_FinalizeTransform() WarpZone_SetUp(self, self.warpzone_origin, self.warpzone_angles, self.enemy.warpzone_origin, self.enemy.warpzone_angles); self.touch = WarpZone_Touch; self.SendFlags = 0xFFFFFF; + if(self.spawnflags & 1) + { + self.think = WarpZone_Think; + self.nextthink = time; + } + else + self.nextthink = 0; } float warpzone_initialized; @@ -525,6 +677,11 @@ void spawnfunc_trigger_warpzone(void) // the map, with another killtarget to designate its // orientation +#ifndef WARPZONE_USE_FIXANGLE + // used when teleporting + precache_model("null"); +#endif + if(!self.scale) self.scale = self.modelscale; if(!self.scale) @@ -544,7 +701,7 @@ void spawnfunc_trigger_warpzone(void) setsize(self, self.mins, self.maxs); self.SendEntity = WarpZone_Send; self.SendFlags = 0xFFFFFF; - self.effects |= EF_NODEPTHTEST; + BITSET_ASSIGN(self.effects, EF_NODEPTHTEST); self.warpzone_next = warpzone_first; warpzone_first = self; } @@ -588,6 +745,31 @@ void WarpZones_Reconnect() self = e; } +void WarpZone_Think() +{ + if(self.warpzone_save_origin != self.origin + || self.warpzone_save_angles != self.angles + || self.warpzone_save_eorigin != self.enemy.origin + || self.warpzone_save_eangles != self.enemy.angles) + { + entity oldself; + oldself = self; + WarpZone_InitStep_UpdateTransform(); + self = self.enemy; + WarpZone_InitStep_UpdateTransform(); + self = oldself; + WarpZone_InitStep_FinalizeTransform(); + self = self.enemy; + WarpZone_InitStep_FinalizeTransform(); + self = oldself; + self.warpzone_save_origin = self.origin; + self.warpzone_save_angles = self.angles; + self.warpzone_save_eorigin = self.enemy.origin; + self.warpzone_save_eangles = self.enemy.angles; + } + self.nextthink = time; +} + void WarpZone_StartFrame() { entity e; @@ -603,6 +785,7 @@ void WarpZone_StartFrame() WarpZone_InitStep_UpdateTransform(); self = e; WarpZones_Reconnect(); + WarpZone_PostInitialize_Callback(); } entity oldself, oldother; @@ -610,27 +793,37 @@ void WarpZone_StartFrame() oldother = other; for(e = world; (e = nextent(e)); ) { - WarpZone_StoreProjectileData(e); - float f; - f = clienttype(e); + if(warpzone_warpzones_exist) { WarpZone_StoreProjectileData(e); } + + float f = clienttype(e); if(f == CLIENTTYPE_REAL) { - if(e.solid != SOLID_NOT) // not spectating? - continue; - if(e.movetype != MOVETYPE_NOCLIP && e.movetype != MOVETYPE_FLY) // not spectating? (this is to catch observers) - continue; - self = WarpZone_Find(e.origin + e.mins, e.origin + e.maxs); - if(!self) - continue; - other = e; - if(WarpZoneLib_ExactTrigger_Touch()) - continue; - WarpZone_Teleport(e); // NOT triggering targets by this! + if(e.solid == SOLID_NOT) // not spectating? + if(e.movetype == MOVETYPE_NOCLIP || e.movetype == MOVETYPE_FLY || e.movetype == MOVETYPE_FLY_WORLDONLY) // not spectating? (this is to catch observers) + { + other = e; // player + + // warpzones + if(warpzone_warpzones_exist) { + self = WarpZone_Find(e.origin + e.mins, e.origin + e.maxs); + if(self) + if(!WarpZoneLib_ExactTrigger_Touch()) + if(WarpZone_PlaneDist(self, e.origin + e.view_ofs) <= 0) + WarpZone_Teleport(self, e, -1, 0); } // NOT triggering targets by this! + + // teleporters + self = Teleport_Find(e.origin + e.mins, e.origin + e.maxs); + if(self) + if(!WarpZoneLib_ExactTrigger_Touch()) + Simple_TeleportPlayer(self, other); // NOT triggering targets by this! + } } + if(f == CLIENTTYPE_NOTACLIENT) { - for(; (e = nextent(e)); ) - WarpZone_StoreProjectileData(e); + if(warpzone_warpzones_exist) + for(; (e = nextent(e)); ) + WarpZone_StoreProjectileData(e); break; } } @@ -682,3 +875,16 @@ void spawnfunc_target_warpzone_reconnect() { spawnfunc_trigger_warpzone_reconnect(); // both names make sense here :( } + +void WarpZone_PlayerPhysics_FixVAngle(void) +{ +#ifndef WARPZONE_DONT_FIX_VANGLE + if(clienttype(self) == CLIENTTYPE_REAL) + if(self.v_angle_z <= 360) // if not already adjusted + if(time - self.ping * 0.001 < self.warpzone_teleport_time) + { + self.v_angle = WarpZone_TransformVAngles(self.warpzone_teleport_zone, self.v_angle); + self.v_angle_z += 720; // mark as adjusted + } +#endif +} diff --git a/qcsrc/warpzonelib/server.qh b/qcsrc/warpzonelib/server.qh index 392e6f39d1..7a301a8b82 100644 --- a/qcsrc/warpzonelib/server.qh +++ b/qcsrc/warpzonelib/server.qh @@ -8,3 +8,7 @@ float WarpZone_Projectile_Touch_ImpactFilter_Callback(); // server must also define a float called ENT_CLIENT_WARPZONE for the initial byte of WarpZone entities const float ENT_CLIENT_WARPZONE; const float ENT_CLIENT_WARPZONE_CAMERA; + +void WarpZone_PlayerPhysics_FixVAngle(void); + +void WarpZone_PostInitialize_Callback(void); diff --git a/qcsrc/xonotic-gamecode.workspace b/qcsrc/xonotic-gamecode.workspace deleted file mode 100644 index 3f4a59a303..0000000000 --- a/qcsrc/xonotic-gamecode.workspace +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> -<CodeBlocks_workspace_file> - <Workspace title="Xonotic Gamecode"> - <Project filename="qc-server.cbp" active="1" /> - <Project filename="qc-client.cbp" /> - <Project filename="qc-common.cbp" /> - </Workspace> -</CodeBlocks_workspace_file> diff --git a/quake.rc b/quake.rc index a85fbab69b..5dd32c8ac0 100644 --- a/quake.rc +++ b/quake.rc @@ -3,6 +3,8 @@ exec config.cfg maxplayers $menu_maxplayers exec data/campaign.cfg exec config_update.cfg +exec font-xolonium.cfg +exec autoexec/*.cfg exec autoexec.cfg stuffcmds //startdemos demos/demo1 demos/demo2 demos/demo3 diff --git a/sRGB-disable.cfg b/sRGB-disable.cfg new file mode 100644 index 0000000000..de04760696 --- /dev/null +++ b/sRGB-disable.cfg @@ -0,0 +1,7 @@ +// good non-sRGB settings +vid_sRGB 0 +mod_q3bsp_sRGBlightmaps 0 +r_hdr_scenebrightness 1 +r_ambient 4 + +menu_cmd sync diff --git a/sRGB-enable.cfg b/sRGB-enable.cfg new file mode 100644 index 0000000000..a8ff4ccff2 --- /dev/null +++ b/sRGB-enable.cfg @@ -0,0 +1,7 @@ +// good sRGB settings +vid_sRGB 1 +mod_q3bsp_sRGBlightmaps 1 +r_hdr_scenebrightness 1 +r_ambient 0.25 + +menu_cmd sync diff --git a/scripts/akordeon.shader b/scripts/akordeon.shader new file mode 100644 index 0000000000..19a3041736 --- /dev/null +++ b/scripts/akordeon.shader @@ -0,0 +1,9 @@ +akordeon +{ + dpglossexponentmod 64 + dpreflectcube env/exomorph/exomorph + { + map models/weapons/akordeon.tga + rgbgen lightingDiffuse + } +} \ No newline at end of file diff --git a/scripts/casings.shader b/scripts/casings.shader new file mode 100644 index 0000000000..9286c43a51 --- /dev/null +++ b/scripts/casings.shader @@ -0,0 +1,15 @@ +models/casing_bronze +{ + dpglossintensitymod 2 + dpglossexponentmod 4 + dpreflectcube env/exomorph/exomorph + { + map models/casing_bronze.tga + } + { + map $lightmap + rgbGen identity + tcGen lightmap + blendfunc filter + } +} diff --git a/scripts/flags.shader b/scripts/flags.shader deleted file mode 100644 index 1ed38d6ccd..0000000000 --- a/scripts/flags.shader +++ /dev/null @@ -1,33 +0,0 @@ -flags/flag_red_cloth { - cull none - deformVertexes wave 100 sin 0 0.4 0 2.5 - { - map textures/flags/flag_red_cloth.tga - } -} - -flags/flag_red_laser { - { - map textures/flags/flag_red_laser.tga - tcMod scroll 0.2 -1 - blendfunc add - } -} - - -flags/flag_blue_cloth { - cull none - deformVertexes wave 100 sin 0 0.4 0 2.5 - { - map textures/flags/flag_blue_cloth.tga - } -} - -flags/flag_blue_laser { - { - map textures/flags/flag_blue_laser.tga - tcMod scroll 0.2 -1 - blendfunc add - } -} - diff --git a/scripts/gibs.shader b/scripts/gibs.shader new file mode 100644 index 0000000000..c1c40e572a --- /dev/null +++ b/scripts/gibs.shader @@ -0,0 +1,111 @@ +meat +{ + surfaceparm nomarks + { + map textures/meat + } + { + map $lightmap + } +} + +meat_alien +{ + surfaceparm nomarks + { + map textures/meat_alien + } + { + map $lightmap + } +} + +meat_robot +{ + surfaceparm nomarks + { + map textures/meat_robot + } + { + map $lightmap + } +} + +eyeblood +{ + surfaceparm nomarks + { + map textures/eyeblood + } + { + map $lightmap + } +} + +nutsandbolts1 +{ + surfaceparm nomarks + { + map textures/nutsandbolts1 + } + { + map $lightmap + } +} + +nutsandbolts3 +{ + surfaceparm nomarks + { + map textures/nutsandbolts3 + } + { + map $lightmap + } +} + +nutsandbolts4 +{ + surfaceparm nomarks + { + map textures/nutsandbolts4 + } + { + map $lightmap + } +} + +nutsandbolts5 +{ + surfaceparm nomarks + { + map textures/nutsandbolts5 + } + { + map $lightmap + } +} + +nutsandboltssteel +{ + surfaceparm nomarks + { + map textures/nutsandbolts3 + tcgen environment + } + { + map $lightmap + } +} + +models/gibs/chunk.mdl_0 +{ + surfaceparm nomarks + { + map models/gibs/chunk.mdl_0 + tcgen environment + } + { + map $lightmap + } +} diff --git a/scripts/items.shader b/scripts/items.shader new file mode 100644 index 0000000000..4d6565719e --- /dev/null +++ b/scripts/items.shader @@ -0,0 +1,41 @@ +models/items/5hp +{ + dpreflectcube cubemaps/default/sky + { + map models/items/5hp.tga + rgbgen lightingDiffuse + } +} +models/items/h25 +{ + dpreflectcube cubemaps/default/sky + { + map models/items/h25.tga + rgbgen lightingDiffuse + } +} +models/items/red +{ + dpreflectcube cubemaps/default/sky + { + map models/items/red.tga + blendfunc filter + rgbgen lightingDiffuse + } +} +models/items/h50 +{ + dpreflectcube cubemaps/default/sky + { + map models/items/h50.tga + rgbgen lightingDiffuse + } +} +models/items/h_mega +{ + dpreflectcube cubemaps/default/sky + { + map models/items/h_mega.tga + rgbgen lightingDiffuse + } +} \ No newline at end of file diff --git a/scripts/mnex.shader b/scripts/mnex.shader new file mode 100644 index 0000000000..718c93ed41 --- /dev/null +++ b/scripts/mnex.shader @@ -0,0 +1,9 @@ +MNex-Diffuse +{ + dpglossexponentmod 64 + dpreflectcube env/exomorph/exomorph + { + map models/weapons/mnex.tga + rgbgen lightingDiffuse + } +} \ No newline at end of file diff --git a/scripts/nutsandbolts.shader b/scripts/nutsandbolts.shader deleted file mode 100644 index e0eb347fcb..0000000000 --- a/scripts/nutsandbolts.shader +++ /dev/null @@ -1,10 +0,0 @@ -nutsandboltssteel -{ - { - map textures/nutsandbolts3 - tcgen environment - } - { - map $lightmap - } -} diff --git a/scripts/projectiles.shader b/scripts/projectiles.shader index 28b1e94920..16847e57df 100644 --- a/scripts/projectiles.shader +++ b/scripts/projectiles.shader @@ -5,7 +5,7 @@ crylink_projectile_core deformVertexes autosprite { map textures/projectiles/crylink_projectile_core.tga - blendfunc add + blendfunc GL_SRC_ALPHA GL_ONE rgbGen lightingDiffuse } } @@ -16,7 +16,7 @@ crylink_projectile_long deformVertexes autosprite2 { map textures/projectiles/crylink_projectile_long.tga - blendfunc add + blendfunc GL_SRC_ALPHA GL_ONE rgbGen lightingDiffuse } } @@ -87,4 +87,4 @@ laser_projectile_long blendfunc add rgbGen lightingDiffuse } -} \ No newline at end of file +} diff --git a/scripts/relics.shader b/scripts/relics.shader new file mode 100644 index 0000000000..24f95617f1 --- /dev/null +++ b/scripts/relics.shader @@ -0,0 +1,160 @@ +models/relics/relic +{ + dpreflectcube cubemaps/default/sky + { + map models/relics/relic.tga + rgbgen lightingDiffuse + } +} +models/relics/relic_ring +{ + { + map models/relics/relic_ring.tga + blendfunc GL_SRC_ALPHA GL_ONE + rgbgen lightingDiffuse + } +} +models/relics/sign_resistance +{ + cull none + { + map models/relics/sign_resistance.tga + blendfunc add + rgbgen lightingDiffuse + } +} +models/relics/sign_regeneration +{ + cull none + { + map models/relics/sign_regeneration.tga + blendfunc add + rgbgen lightingDiffuse + } +} +models/relics/sign_vampire +{ + cull none + { + map models/relics/sign_vampire.tga + blendfunc add + rgbgen lightingDiffuse + } +} +models/relics/sign_ammo +{ + cull none + { + map models/relics/sign_ammo.tga + blendfunc add + rgbgen lightingDiffuse + } +} +models/relics/sign_damage +{ + cull none + { + map models/relics/sign_damage.tga + blendfunc add + rgbgen lightingDiffuse + } +} +models/relics/sign_splashdamage +{ + cull none + { + map models/relics/sign_splashdamage.tga + blendfunc add + rgbgen lightingDiffuse + } +} +models/relics/sign_firingspeed +{ + cull none + { + map models/relics/sign_firingspeed.tga + blendfunc add + rgbgen lightingDiffuse + } +} +models/relics/sign_disability +{ + cull none + { + map models/relics/sign_disability.tga + blendfunc add + rgbgen lightingDiffuse + } +} +models/relics/sign_teamboost +{ + cull none + { + map models/relics/sign_teamboost.tga + blendfunc add + rgbgen lightingDiffuse + } +} +models/relics/sign_speed +{ + cull none + { + map models/relics/sign_speed.tga + blendfunc add + rgbgen lightingDiffuse + } +} +models/relics/sign_jump +{ + cull none + { + map models/relics/sign_jump.tga + blendfunc add + rgbgen lightingDiffuse + } +} +models/relics/sign_flight +{ + cull none + { + map models/relics/sign_flight.tga + blendfunc add + rgbgen lightingDiffuse + } +} +models/relics/sign_invisible +{ + cull none + { + map models/relics/sign_invisible.tga + blendfunc add + rgbgen lightingDiffuse + } +} +models/relics/sign_radioactive +{ + cull none + { + map models/relics/sign_radioactive.tga + blendfunc add + rgbgen lightingDiffuse + } +} +models/relics/sign_resurrection +{ + cull none + { + map models/relics/sign_resurrection.tga + blendfunc add + rgbgen lightingDiffuse + } +} +models/relics/sign_vengeance +{ + cull none + { + map models/relics/sign_vengeance.tga + blendfunc add + rgbgen lightingDiffuse + } +} diff --git a/scripts/rocket.shader b/scripts/rocket.shader index b3041f215c..a5c9d181df 100644 --- a/scripts/rocket.shader +++ b/scripts/rocket.shader @@ -4,7 +4,7 @@ rocketThrust cull disable { clampmap textures/thrustc1.tga - blendfunc add + blendfunc GL_SRC_ALPHA GL_ONE tcMod rotate 720 } } diff --git a/scripts/turrets.shader b/scripts/turrets.shader index 9e4f68e3ff..f407aba153 100644 --- a/scripts/turrets.shader +++ b/scripts/turrets.shader @@ -1,3 +1,11 @@ +evil_basewall/mtl_gray +{ + { + map textures/exx/base/base_metal01 + rgbgen lightingDiffuse + } +} + models/turrets/tesla_chrome { @@ -22,7 +30,7 @@ models/turrets/phaser_beam qer_editorimage models/turrets/phaser_beam { map models/turrets/phaser_beam - blendFunc add + blendFunc GL_SRC_ALPHA GL_ONE } } diff --git a/scripts/vehicles.shader b/scripts/vehicles.shader new file mode 100644 index 0000000000..2d4d606752 --- /dev/null +++ b/scripts/vehicles.shader @@ -0,0 +1,48 @@ +spiderbot +{ + dpreflectcube cubemaps/default/sky + { + map textures/spiderbot.tga + rgbgen lightingDiffuse + } +} +wakazachi +{ + dpreflectcube cubemaps/default/sky + { + map textures/wakazachi.tga + rgbgen lightingDiffuse + } +} +cockpit +{ + dpreflectcube cubemaps/default/sky + { + map textures/cockpit.tga + rgbgen lightingDiffuse + } +} +vehicles/tracercore +{ + surfaceparm nonsolid + surfaceparm nolightmap + deformVertexes autosprite + { + map models/vehicles/tracercore.tga + blendfunc add + rgbGen lightingDiffuse + } + } +vehicles/tracertrail +{ + surfaceparm nonsolid + surfaceparm nolightmap + cull none + deformVertexes autosprite2 + { + map models/vehicles/tracertrail.tga + blendfunc GL_SRC_ALPHA GL_ONE + rgbGen lightingDiffuse + } +} + diff --git a/scripts/vrockets.shader b/scripts/vrockets.shader new file mode 100644 index 0000000000..4425994f2e --- /dev/null +++ b/scripts/vrockets.shader @@ -0,0 +1,16 @@ +models/vehicles/rockets +{ + dpreflectcube cubemaps/default/sky + { + map models/vehicles/rockets.tga + rgbgen lightingDiffuse + } +} +rockets +{ + dpreflectcube cubemaps/default/sky + { + map models/vehicles/rockets.tga + rgbgen lightingDiffuse + } +} \ No newline at end of file diff --git a/scripts/weapons.shader b/scripts/weapons.shader index c093eb3334..1243955c8b 100644 --- a/scripts/weapons.shader +++ b/scripts/weapons.shader @@ -54,14 +54,6 @@ shotgun2 rgbgen lightingDiffuse } } -nex -{ - dpreflectcube cubemaps/default/sky - { - map textures/nex.tga - rgbgen lightingDiffuse - } -} rl { dpreflectcube cubemaps/default/sky diff --git a/sound/misc/medplat1.ogg b/sound/misc/medplat1.ogg deleted file mode 100644 index 018782cf2b..0000000000 Binary files a/sound/misc/medplat1.ogg and /dev/null differ diff --git a/sound/misc/medplat2.ogg b/sound/misc/medplat2.ogg deleted file mode 100644 index 3e7d65bfe2..0000000000 Binary files a/sound/misc/medplat2.ogg and /dev/null differ diff --git a/sound/object/impact_flesh_1.ogg b/sound/object/impact_flesh_1.ogg new file mode 100644 index 0000000000..2d7d4233ba Binary files /dev/null and b/sound/object/impact_flesh_1.ogg differ diff --git a/sound/object/impact_flesh_2.ogg b/sound/object/impact_flesh_2.ogg new file mode 100644 index 0000000000..c490c75d52 Binary files /dev/null and b/sound/object/impact_flesh_2.ogg differ diff --git a/sound/object/impact_flesh_3.ogg b/sound/object/impact_flesh_3.ogg new file mode 100644 index 0000000000..12af02891b Binary files /dev/null and b/sound/object/impact_flesh_3.ogg differ diff --git a/sound/object/impact_flesh_4.ogg b/sound/object/impact_flesh_4.ogg new file mode 100644 index 0000000000..18bf0128aa Binary files /dev/null and b/sound/object/impact_flesh_4.ogg differ diff --git a/sound/object/impact_flesh_5.ogg b/sound/object/impact_flesh_5.ogg new file mode 100644 index 0000000000..2c83777dd2 Binary files /dev/null and b/sound/object/impact_flesh_5.ogg differ diff --git a/sound/object/impact_metal_1.ogg b/sound/object/impact_metal_1.ogg new file mode 100644 index 0000000000..331728a6a7 Binary files /dev/null and b/sound/object/impact_metal_1.ogg differ diff --git a/sound/object/impact_metal_2.ogg b/sound/object/impact_metal_2.ogg new file mode 100644 index 0000000000..645dc20c80 Binary files /dev/null and b/sound/object/impact_metal_2.ogg differ diff --git a/sound/object/impact_metal_3.ogg b/sound/object/impact_metal_3.ogg new file mode 100644 index 0000000000..d1128fd4c4 Binary files /dev/null and b/sound/object/impact_metal_3.ogg differ diff --git a/sound/object/impact_metal_4.ogg b/sound/object/impact_metal_4.ogg new file mode 100644 index 0000000000..cbb99f854b Binary files /dev/null and b/sound/object/impact_metal_4.ogg differ diff --git a/sound/object/impact_metal_5.ogg b/sound/object/impact_metal_5.ogg new file mode 100644 index 0000000000..60d4d43f38 Binary files /dev/null and b/sound/object/impact_metal_5.ogg differ diff --git a/sound/object/impact_stone_1.ogg b/sound/object/impact_stone_1.ogg new file mode 100644 index 0000000000..429b1c5559 Binary files /dev/null and b/sound/object/impact_stone_1.ogg differ diff --git a/sound/object/impact_stone_2.ogg b/sound/object/impact_stone_2.ogg new file mode 100644 index 0000000000..0a4feb7133 Binary files /dev/null and b/sound/object/impact_stone_2.ogg differ diff --git a/sound/object/impact_stone_3.ogg b/sound/object/impact_stone_3.ogg new file mode 100644 index 0000000000..f33b43c183 Binary files /dev/null and b/sound/object/impact_stone_3.ogg differ diff --git a/sound/object/impact_stone_4.ogg b/sound/object/impact_stone_4.ogg new file mode 100644 index 0000000000..507e4a62d4 Binary files /dev/null and b/sound/object/impact_stone_4.ogg differ diff --git a/sound/object/impact_stone_5.ogg b/sound/object/impact_stone_5.ogg new file mode 100644 index 0000000000..89c9df71bf Binary files /dev/null and b/sound/object/impact_stone_5.ogg differ diff --git a/sound/object/impact_wood_1.ogg b/sound/object/impact_wood_1.ogg new file mode 100644 index 0000000000..cb665e0b3b Binary files /dev/null and b/sound/object/impact_wood_1.ogg differ diff --git a/sound/object/impact_wood_2.ogg b/sound/object/impact_wood_2.ogg new file mode 100644 index 0000000000..ab826a0e96 Binary files /dev/null and b/sound/object/impact_wood_2.ogg differ diff --git a/sound/object/impact_wood_3.ogg b/sound/object/impact_wood_3.ogg new file mode 100644 index 0000000000..1d383c274e Binary files /dev/null and b/sound/object/impact_wood_3.ogg differ diff --git a/sound/object/impact_wood_4.ogg b/sound/object/impact_wood_4.ogg new file mode 100644 index 0000000000..314917d661 Binary files /dev/null and b/sound/object/impact_wood_4.ogg differ diff --git a/sound/object/impact_wood_5.ogg b/sound/object/impact_wood_5.ogg new file mode 100644 index 0000000000..9d8c929891 Binary files /dev/null and b/sound/object/impact_wood_5.ogg differ diff --git a/sound/player/default.sounds b/sound/player/default.sounds index cf93bb6a4a..6800c2f663 100644 --- a/sound/player/default.sounds +++ b/sound/player/default.sounds @@ -1,31 +1,31 @@ -//affirmative sound/player/torus/coms/affirmative 0 -attack sound/player/torus/coms/attack 0 -//attacking sound/player/torus/coms/attacking 0 -attackinfive sound/player/torus/coms/letsgo 0 -coverme sound/player/torus/coms/coverme 0 -//defend sound/player/torus/coms/defend 1 -//defending sound/player/torus/coms/defending 0 -//droppedflag sound/player/torus/coms/droppedflag 0 -//flagcarriertakingdamage sound/player/torus/coms/flagcarriertakingdamage 0 -//freelance sound/player/torus/coms/freelance 1 -//getflag sound/player/torus/coms/getflag 0 -incoming sound/player/torus/coms/incoming 0 -meet sound/player/torus/coms/waypoint 0 -needhelp sound/player/torus/coms/needhelp 0 -//negative sound/player/torus/coms/negative 0 -//onmyway sound/player/torus/coms/onmyway 0 -//roaming sound/player/torus/coms/roaming 0 -//seenenemy sound/player/torus/coms/seenenemy 0 -seenflag sound/player/torus/coms/seenflag 0 -taunt sound/player/torus/coms/taunt 2 -teamshoot sound/player/torus/coms/teamshoot 0 -death sound/player/torus/player/death 0 -drown sound/player/torus/player/drown 0 -//fall sound/player/torus/player/fall 0 -//falling sound/debug/v_falling 0 -gasp sound/player/torus/player/gasp 0 -jump sound/player/torus/player/fall 0 -pain25 sound/player/torus/player/pain25 0 -pain50 sound/player/torus/player/pain50 0 -pain75 sound/player/torus/player/pain75 0 -pain100 sound/player/torus/player/pain100 0 +affirmative sound/player/espeak/coms/affirmative 0 +attack sound/player/espeak/coms/attack 0 +attacking sound/player/espeak/coms/attacking 0 +attackinfive sound/player/espeak/coms/attackinfive 0 +coverme sound/player/espeak/coms/coverme 0 +defend sound/player/espeak/coms/defend 0 +defending sound/player/espeak/coms/defending 0 +droppedflag sound/player/espeak/coms/droppedflag 0 +flagcarriertakingdamage sound/player/espeak/coms/flagcarriertakingdamage 0 +freelance sound/player/espeak/coms/freelance 0 +getflag sound/player/espeak/coms/getflag 0 +incoming sound/player/espeak/coms/incoming 0 +meet sound/player/espeak/coms/meet 0 +needhelp sound/player/espeak/coms/needhelp 0 +negative sound/player/espeak/coms/negative 0 +onmyway sound/player/espeak/coms/onmyway 0 +roaming sound/player/espeak/coms/roaming 0 +seenenemy sound/player/espeak/coms/seenenemy 0 +seenflag sound/player/espeak/coms/seenflag 0 +taunt sound/player/espeak/coms/taunt 0 +teamshoot sound/player/espeak/coms/teamshoot 0 +death sound/player/espeak/player/death 0 +drown sound/player/espeak/player/drown 0 +fall sound/player/espeak/player/fall 0 +falling sound/player/espeak/player/falling 0 +gasp sound/player/espeak/player/gasp 0 +jump sound/player/espeak/player/jump 0 +pain25 sound/player/espeak/player/pain25 0 +pain50 sound/player/espeak/player/pain50 0 +pain75 sound/player/espeak/player/pain75 0 +pain100 sound/player/espeak/player/pain100 0 diff --git a/sound/player/espeak/coms/affirmative.ogg b/sound/player/espeak/coms/affirmative.ogg new file mode 100644 index 0000000000..310fe84335 Binary files /dev/null and b/sound/player/espeak/coms/affirmative.ogg differ diff --git a/sound/player/espeak/coms/attack.ogg b/sound/player/espeak/coms/attack.ogg new file mode 100644 index 0000000000..535bed839f Binary files /dev/null and b/sound/player/espeak/coms/attack.ogg differ diff --git a/sound/player/espeak/coms/attackinfive.ogg b/sound/player/espeak/coms/attackinfive.ogg new file mode 100644 index 0000000000..998848f4be Binary files /dev/null and b/sound/player/espeak/coms/attackinfive.ogg differ diff --git a/sound/player/espeak/coms/attacking.ogg b/sound/player/espeak/coms/attacking.ogg new file mode 100644 index 0000000000..9ba2394256 Binary files /dev/null and b/sound/player/espeak/coms/attacking.ogg differ diff --git a/sound/player/espeak/coms/coverme.ogg b/sound/player/espeak/coms/coverme.ogg new file mode 100644 index 0000000000..079595b57d Binary files /dev/null and b/sound/player/espeak/coms/coverme.ogg differ diff --git a/sound/player/espeak/coms/defend.ogg b/sound/player/espeak/coms/defend.ogg new file mode 100644 index 0000000000..8a3a92c02b Binary files /dev/null and b/sound/player/espeak/coms/defend.ogg differ diff --git a/sound/player/espeak/coms/defending.ogg b/sound/player/espeak/coms/defending.ogg new file mode 100644 index 0000000000..32808d3f92 Binary files /dev/null and b/sound/player/espeak/coms/defending.ogg differ diff --git a/sound/player/espeak/coms/droppedflag.ogg b/sound/player/espeak/coms/droppedflag.ogg new file mode 100644 index 0000000000..fc2f009ef3 Binary files /dev/null and b/sound/player/espeak/coms/droppedflag.ogg differ diff --git a/sound/player/espeak/coms/flagcarriertakingdamage.ogg b/sound/player/espeak/coms/flagcarriertakingdamage.ogg new file mode 100644 index 0000000000..8f27d15c7f Binary files /dev/null and b/sound/player/espeak/coms/flagcarriertakingdamage.ogg differ diff --git a/sound/player/espeak/coms/freelance.ogg b/sound/player/espeak/coms/freelance.ogg new file mode 100644 index 0000000000..ac023a0309 Binary files /dev/null and b/sound/player/espeak/coms/freelance.ogg differ diff --git a/sound/player/espeak/coms/getflag.ogg b/sound/player/espeak/coms/getflag.ogg new file mode 100644 index 0000000000..958296db0e Binary files /dev/null and b/sound/player/espeak/coms/getflag.ogg differ diff --git a/sound/player/espeak/coms/incoming.ogg b/sound/player/espeak/coms/incoming.ogg new file mode 100644 index 0000000000..526f09f4e6 Binary files /dev/null and b/sound/player/espeak/coms/incoming.ogg differ diff --git a/sound/player/espeak/coms/meet.ogg b/sound/player/espeak/coms/meet.ogg new file mode 100644 index 0000000000..ff4aa6cbc6 Binary files /dev/null and b/sound/player/espeak/coms/meet.ogg differ diff --git a/sound/player/espeak/coms/needhelp.ogg b/sound/player/espeak/coms/needhelp.ogg new file mode 100644 index 0000000000..ef84985a73 Binary files /dev/null and b/sound/player/espeak/coms/needhelp.ogg differ diff --git a/sound/player/espeak/coms/negative.ogg b/sound/player/espeak/coms/negative.ogg new file mode 100644 index 0000000000..1f63a57e6b Binary files /dev/null and b/sound/player/espeak/coms/negative.ogg differ diff --git a/sound/player/espeak/coms/onmyway.ogg b/sound/player/espeak/coms/onmyway.ogg new file mode 100644 index 0000000000..ce8d2036ee Binary files /dev/null and b/sound/player/espeak/coms/onmyway.ogg differ diff --git a/sound/player/espeak/coms/roaming.ogg b/sound/player/espeak/coms/roaming.ogg new file mode 100644 index 0000000000..5fee542261 Binary files /dev/null and b/sound/player/espeak/coms/roaming.ogg differ diff --git a/sound/player/espeak/coms/seenenemy.ogg b/sound/player/espeak/coms/seenenemy.ogg new file mode 100644 index 0000000000..da21bcf9e8 Binary files /dev/null and b/sound/player/espeak/coms/seenenemy.ogg differ diff --git a/sound/player/espeak/coms/seenflag.ogg b/sound/player/espeak/coms/seenflag.ogg new file mode 100644 index 0000000000..a6a78fb76e Binary files /dev/null and b/sound/player/espeak/coms/seenflag.ogg differ diff --git a/sound/player/espeak/coms/taunt.ogg b/sound/player/espeak/coms/taunt.ogg new file mode 100644 index 0000000000..03bf24c5af Binary files /dev/null and b/sound/player/espeak/coms/taunt.ogg differ diff --git a/sound/player/espeak/coms/teamshoot.ogg b/sound/player/espeak/coms/teamshoot.ogg new file mode 100644 index 0000000000..040db89cab Binary files /dev/null and b/sound/player/espeak/coms/teamshoot.ogg differ diff --git a/sound/player/espeak/make.sh b/sound/player/espeak/make.sh new file mode 100644 index 0000000000..a93c2cc99f --- /dev/null +++ b/sound/player/espeak/make.sh @@ -0,0 +1,40 @@ +v() +{ + espeak -w "$1.wav" "$2" + normalize "$1.wav" + oggenc -q1 "$1.wav" -o "$1.ogg" + rm -f "$1.wav" +} + +v player/death "Mine Leyben!" +v player/fall "Ooh!" +v player/drown "Gloog gloog gloog!" +v player/gasp "Ha!" +v player/jump "Hem!" +v player/pain25 "Owowowow!" +v player/pain50 "Owow!" +v player/pain75 "Ouuu!" +v player/pain100 "Ouch!" +v player/fall "Arh!" +v player/falling "Aaaaaaaaaaaaaaaaaaaaa!" +v coms/attack "Attack!" +v coms/attackinfive "Attack in 5! In 4! In 3! In 2! In 1! Attack NOW!" +v coms/meet "Let's meet at the waypoint." +v coms/seenflag "I've seen the flag!" +v coms/taunt "Double facepalm!" +v coms/teamshoot "I'm on your team!" +v coms/incoming "Incoming!" +v coms/coverme "Cover me!" +v coms/needhelp "I need help!" +v coms/defend "Defend the base!" +v coms/freelance "Do whatever you want." +v coms/flagcarriertakingdamage "Our flag carrier is taking damage!" +v coms/getflag "Somebody get our flag back!" +v coms/affirmative "Affirmative." +v coms/attacking "I'm attacking." +v coms/defending "I'm defending." +v coms/roaming "I'm roaming around." +v coms/onmyway "I'm on my way." +v coms/droppedflag "I dropped the flag!" +v coms/negative "Negative." +v coms/seenenemy "I've seen an enemy." diff --git a/sound/player/espeak/player/death.ogg b/sound/player/espeak/player/death.ogg new file mode 100644 index 0000000000..b382da7579 Binary files /dev/null and b/sound/player/espeak/player/death.ogg differ diff --git a/sound/player/espeak/player/drown.ogg b/sound/player/espeak/player/drown.ogg new file mode 100644 index 0000000000..55db0c8891 Binary files /dev/null and b/sound/player/espeak/player/drown.ogg differ diff --git a/sound/player/espeak/player/fall.ogg b/sound/player/espeak/player/fall.ogg new file mode 100644 index 0000000000..b5ca319590 Binary files /dev/null and b/sound/player/espeak/player/fall.ogg differ diff --git a/sound/player/espeak/player/falling.ogg b/sound/player/espeak/player/falling.ogg new file mode 100644 index 0000000000..7e1d44ad1b Binary files /dev/null and b/sound/player/espeak/player/falling.ogg differ diff --git a/sound/player/espeak/player/gasp.ogg b/sound/player/espeak/player/gasp.ogg new file mode 100644 index 0000000000..cf126b1a97 Binary files /dev/null and b/sound/player/espeak/player/gasp.ogg differ diff --git a/sound/player/espeak/player/jump.ogg b/sound/player/espeak/player/jump.ogg new file mode 100644 index 0000000000..0da2706388 Binary files /dev/null and b/sound/player/espeak/player/jump.ogg differ diff --git a/sound/player/espeak/player/pain100.ogg b/sound/player/espeak/player/pain100.ogg new file mode 100644 index 0000000000..ca32d93e8a Binary files /dev/null and b/sound/player/espeak/player/pain100.ogg differ diff --git a/sound/player/espeak/player/pain25.ogg b/sound/player/espeak/player/pain25.ogg new file mode 100644 index 0000000000..e39bc689ad Binary files /dev/null and b/sound/player/espeak/player/pain25.ogg differ diff --git a/sound/player/espeak/player/pain50.ogg b/sound/player/espeak/player/pain50.ogg new file mode 100644 index 0000000000..2755a9d446 Binary files /dev/null and b/sound/player/espeak/player/pain50.ogg differ diff --git a/sound/player/espeak/player/pain75.ogg b/sound/player/espeak/player/pain75.ogg new file mode 100644 index 0000000000..60d61f99bd Binary files /dev/null and b/sound/player/espeak/player/pain75.ogg differ diff --git a/sound/relics/relic_effect.wav b/sound/relics/relic_effect.wav new file mode 100644 index 0000000000..b78cebaeed Binary files /dev/null and b/sound/relics/relic_effect.wav differ diff --git a/sound/vehicles/alarm.wav b/sound/vehicles/alarm.wav new file mode 100644 index 0000000000..95b4f5566b Binary files /dev/null and b/sound/vehicles/alarm.wav differ diff --git a/sound/vehicles/alarm_shield.wav b/sound/vehicles/alarm_shield.wav new file mode 100644 index 0000000000..8e46d62acb Binary files /dev/null and b/sound/vehicles/alarm_shield.wav differ diff --git a/sound/vehicles/lock.wav b/sound/vehicles/lock.wav new file mode 100644 index 0000000000..54a0a0d5ff Binary files /dev/null and b/sound/vehicles/lock.wav differ diff --git a/sound/vehicles/locked.wav b/sound/vehicles/locked.wav new file mode 100644 index 0000000000..e846776cfa Binary files /dev/null and b/sound/vehicles/locked.wav differ diff --git a/sound/vehicles/locking.wav b/sound/vehicles/locking.wav new file mode 100644 index 0000000000..210d88ec51 Binary files /dev/null and b/sound/vehicles/locking.wav differ diff --git a/sound/vehicles/racer_boost.wav b/sound/vehicles/racer_boost.wav new file mode 100644 index 0000000000..93149e4b4d Binary files /dev/null and b/sound/vehicles/racer_boost.wav differ diff --git a/sound/vehicles/racer_idle.wav b/sound/vehicles/racer_idle.wav new file mode 100644 index 0000000000..025332ab0f Binary files /dev/null and b/sound/vehicles/racer_idle.wav differ diff --git a/sound/vehicles/racer_move.wav b/sound/vehicles/racer_move.wav new file mode 100644 index 0000000000..193a5e2cff Binary files /dev/null and b/sound/vehicles/racer_move.wav differ diff --git a/sound/vehicles/raptor_fly.wav b/sound/vehicles/raptor_fly.wav new file mode 100644 index 0000000000..88c8609a5c Binary files /dev/null and b/sound/vehicles/raptor_fly.wav differ diff --git a/sound/vehicles/raptor_speed.wav b/sound/vehicles/raptor_speed.wav new file mode 100644 index 0000000000..439eebc2f5 Binary files /dev/null and b/sound/vehicles/raptor_speed.wav differ diff --git a/sound/vehicles/spiderbot_die.wav b/sound/vehicles/spiderbot_die.wav new file mode 100644 index 0000000000..10b3d6e892 Binary files /dev/null and b/sound/vehicles/spiderbot_die.wav differ diff --git a/sound/vehicles/spiderbot_idle.wav b/sound/vehicles/spiderbot_idle.wav new file mode 100644 index 0000000000..fdc20e7125 Binary files /dev/null and b/sound/vehicles/spiderbot_idle.wav differ diff --git a/sound/vehicles/spiderbot_jump.wav b/sound/vehicles/spiderbot_jump.wav new file mode 100644 index 0000000000..60444992ac Binary files /dev/null and b/sound/vehicles/spiderbot_jump.wav differ diff --git a/sound/vehicles/spiderbot_land.wav b/sound/vehicles/spiderbot_land.wav new file mode 100644 index 0000000000..d797e1fb6a Binary files /dev/null and b/sound/vehicles/spiderbot_land.wav differ diff --git a/sound/vehicles/spiderbot_strafe.wav b/sound/vehicles/spiderbot_strafe.wav new file mode 100644 index 0000000000..3f132203bf Binary files /dev/null and b/sound/vehicles/spiderbot_strafe.wav differ diff --git a/sound/vehicles/spiderbot_walk.wav b/sound/vehicles/spiderbot_walk.wav new file mode 100644 index 0000000000..6b7638ae2e Binary files /dev/null and b/sound/vehicles/spiderbot_walk.wav differ diff --git a/sound/weapons/campingrifle_fire2.ogg b/sound/weapons/campingrifle_fire2.ogg new file mode 100644 index 0000000000..721b37b914 Binary files /dev/null and b/sound/weapons/campingrifle_fire2.ogg differ diff --git a/sound/weapons/campingrifle_fire2.wav b/sound/weapons/campingrifle_fire2.wav deleted file mode 100644 index 66bda4fab4..0000000000 Binary files a/sound/weapons/campingrifle_fire2.wav and /dev/null differ diff --git a/sound/weapons/campingrifle_reload.ogg b/sound/weapons/campingrifle_reload.ogg deleted file mode 100644 index 2edb3739cc..0000000000 Binary files a/sound/weapons/campingrifle_reload.ogg and /dev/null differ diff --git a/sound/weapons/hagar_beep.ogg b/sound/weapons/hagar_beep.ogg new file mode 100644 index 0000000000..52ef8e8a97 Binary files /dev/null and b/sound/weapons/hagar_beep.ogg differ diff --git a/sound/weapons/hagar_load.ogg b/sound/weapons/hagar_load.ogg new file mode 100644 index 0000000000..92b88beebe Binary files /dev/null and b/sound/weapons/hagar_load.ogg differ diff --git a/sound/weapons/reload.ogg b/sound/weapons/reload.ogg new file mode 100644 index 0000000000..2edb3739cc Binary files /dev/null and b/sound/weapons/reload.ogg differ diff --git a/sound/weapons/tuba1_loopnote-12.ogg b/sound/weapons/tuba1_loopnote-12.ogg new file mode 100644 index 0000000000..f838b61bbf Binary files /dev/null and b/sound/weapons/tuba1_loopnote-12.ogg differ diff --git a/sound/weapons/tuba1_loopnote-18.ogg b/sound/weapons/tuba1_loopnote-18.ogg new file mode 100644 index 0000000000..53ca26b747 Binary files /dev/null and b/sound/weapons/tuba1_loopnote-18.ogg differ diff --git a/sound/weapons/tuba1_loopnote-6.ogg b/sound/weapons/tuba1_loopnote-6.ogg new file mode 100644 index 0000000000..4d444679e5 Binary files /dev/null and b/sound/weapons/tuba1_loopnote-6.ogg differ diff --git a/sound/weapons/tuba1_loopnote-src.txt b/sound/weapons/tuba1_loopnote-src.txt new file mode 100644 index 0000000000..91b43003b3 --- /dev/null +++ b/sound/weapons/tuba1_loopnote-src.txt @@ -0,0 +1,47 @@ +r=44642 + +base=261.6 +ls=$((7646/2)) +le=$((10378/2)) +for n in -18 -12 -6; do + this=`echo "440*e(l(2)/12*($n+60-69))" | bc -l` + f=`echo "$r * $this / $base + 0.5" | bc -l` + f=${f%.*} + echo "$r -> $f" + if [ "$f" -gt 48000 ]; then + o="-r 48000" + s=`echo "$ls * 48000 / $f + 0.5" | bc -l` + s=${s%.*} + e=`echo "$le * 48000 / $f + 0.5" | bc -l` + e=${e%.*} + else + o= + s=$ls + e=$le + fi + sox -r "$f" 023_Tango_Accordion-0.wav $o "tuba1_loopnote$n.wav" + oggenc -c "LOOP_START=$s" -c "LOOP_END=$e" -q8 -o "tuba1_loopnote$n.ogg" "tuba1_loopnote$n.wav" +done + +base=659.191 +ls=$((6326/2)) +le=$((7140/2)) +for n in 0 6 12 18 24; do + this=`echo "440*e(l(2)/12*($n+60-69))" | bc -l` + f=`echo "$r * $this / $base + 0.5" | bc -l` + f=${f%.*} + echo "$r -> $f" + if [ "$f" -gt 48000 ]; then + o="-r 48000" + s=`echo "$ls * 48000 / $f + 0.5" | bc -l` + s=${s%.*} + e=`echo "$le * 48000 / $f + 0.5" | bc -l` + e=${e%.*} + else + o= + s=$ls + e=$le + fi + sox -r "$f" 023_Tango_Accordion-1.wav $o "tuba1_loopnote$n.wav" + oggenc -c "LOOP_START=$s" -c "LOOP_END=$e" -q8 -o "tuba1_loopnote$n.ogg" "tuba1_loopnote$n.wav" +done diff --git a/sound/weapons/tuba1_loopnote0.ogg b/sound/weapons/tuba1_loopnote0.ogg new file mode 100644 index 0000000000..b0cd552eef Binary files /dev/null and b/sound/weapons/tuba1_loopnote0.ogg differ diff --git a/sound/weapons/tuba1_loopnote12.ogg b/sound/weapons/tuba1_loopnote12.ogg new file mode 100644 index 0000000000..dc53a271fd Binary files /dev/null and b/sound/weapons/tuba1_loopnote12.ogg differ diff --git a/sound/weapons/tuba1_loopnote18.ogg b/sound/weapons/tuba1_loopnote18.ogg new file mode 100644 index 0000000000..122a875323 Binary files /dev/null and b/sound/weapons/tuba1_loopnote18.ogg differ diff --git a/sound/weapons/tuba1_loopnote24.ogg b/sound/weapons/tuba1_loopnote24.ogg new file mode 100644 index 0000000000..23bd01b597 Binary files /dev/null and b/sound/weapons/tuba1_loopnote24.ogg differ diff --git a/sound/weapons/tuba1_loopnote6.ogg b/sound/weapons/tuba1_loopnote6.ogg new file mode 100644 index 0000000000..a89fa7e7e7 Binary files /dev/null and b/sound/weapons/tuba1_loopnote6.ogg differ diff --git a/sound/weapons/tuba_loopnote-12.ogg b/sound/weapons/tuba_loopnote-12.ogg index 3b5ed66274..de5a5661c9 100644 Binary files a/sound/weapons/tuba_loopnote-12.ogg and b/sound/weapons/tuba_loopnote-12.ogg differ diff --git a/sound/weapons/tuba_loopnote-18.ogg b/sound/weapons/tuba_loopnote-18.ogg index dda1ed85c1..df83c9f409 100644 Binary files a/sound/weapons/tuba_loopnote-18.ogg and b/sound/weapons/tuba_loopnote-18.ogg differ diff --git a/sound/weapons/tuba_loopnote-6.ogg b/sound/weapons/tuba_loopnote-6.ogg index 12eae360a4..35c46954c3 100644 Binary files a/sound/weapons/tuba_loopnote-6.ogg and b/sound/weapons/tuba_loopnote-6.ogg differ diff --git a/sound/weapons/tuba_loopnote0.ogg b/sound/weapons/tuba_loopnote0.ogg index e7e601769b..5536ed97cd 100644 Binary files a/sound/weapons/tuba_loopnote0.ogg and b/sound/weapons/tuba_loopnote0.ogg differ diff --git a/sound/weapons/tuba_loopnote12.ogg b/sound/weapons/tuba_loopnote12.ogg index 4a20ee68a4..cd6b241ac4 100644 Binary files a/sound/weapons/tuba_loopnote12.ogg and b/sound/weapons/tuba_loopnote12.ogg differ diff --git a/sound/weapons/tuba_loopnote18.ogg b/sound/weapons/tuba_loopnote18.ogg index 3a27ec3707..8c9ec5ab06 100644 Binary files a/sound/weapons/tuba_loopnote18.ogg and b/sound/weapons/tuba_loopnote18.ogg differ diff --git a/sound/weapons/tuba_loopnote24.ogg b/sound/weapons/tuba_loopnote24.ogg index 927d63a23a..a271b2a9a1 100644 Binary files a/sound/weapons/tuba_loopnote24.ogg and b/sound/weapons/tuba_loopnote24.ogg differ diff --git a/sound/weapons/tuba_loopnote6.ogg b/sound/weapons/tuba_loopnote6.ogg index 664f4a1201..3f72b4aeb2 100644 Binary files a/sound/weapons/tuba_loopnote6.ogg and b/sound/weapons/tuba_loopnote6.ogg differ diff --git a/sound/weapons/tuba_note-1.ogg b/sound/weapons/tuba_note-1.ogg deleted file mode 100644 index 25396922b6..0000000000 Binary files a/sound/weapons/tuba_note-1.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note-10.ogg b/sound/weapons/tuba_note-10.ogg deleted file mode 100644 index 254a7f6097..0000000000 Binary files a/sound/weapons/tuba_note-10.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note-11.ogg b/sound/weapons/tuba_note-11.ogg deleted file mode 100644 index d9b05986dc..0000000000 Binary files a/sound/weapons/tuba_note-11.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note-12.ogg b/sound/weapons/tuba_note-12.ogg deleted file mode 100644 index 855bb22452..0000000000 Binary files a/sound/weapons/tuba_note-12.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note-13.ogg b/sound/weapons/tuba_note-13.ogg deleted file mode 100644 index 082ab0b5be..0000000000 Binary files a/sound/weapons/tuba_note-13.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note-14.ogg b/sound/weapons/tuba_note-14.ogg deleted file mode 100644 index 06a6c470a2..0000000000 Binary files a/sound/weapons/tuba_note-14.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note-15.ogg b/sound/weapons/tuba_note-15.ogg deleted file mode 100644 index ecbbdff0b5..0000000000 Binary files a/sound/weapons/tuba_note-15.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note-16.ogg b/sound/weapons/tuba_note-16.ogg deleted file mode 100644 index 990d4fa939..0000000000 Binary files a/sound/weapons/tuba_note-16.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note-17.ogg b/sound/weapons/tuba_note-17.ogg deleted file mode 100644 index 0d6277cc4d..0000000000 Binary files a/sound/weapons/tuba_note-17.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note-18.ogg b/sound/weapons/tuba_note-18.ogg deleted file mode 100644 index d065eb9271..0000000000 Binary files a/sound/weapons/tuba_note-18.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note-2.ogg b/sound/weapons/tuba_note-2.ogg deleted file mode 100644 index b91b5b7e01..0000000000 Binary files a/sound/weapons/tuba_note-2.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note-3.ogg b/sound/weapons/tuba_note-3.ogg deleted file mode 100644 index 94a56cb969..0000000000 Binary files a/sound/weapons/tuba_note-3.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note-4.ogg b/sound/weapons/tuba_note-4.ogg deleted file mode 100644 index 023a7d37aa..0000000000 Binary files a/sound/weapons/tuba_note-4.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note-5.ogg b/sound/weapons/tuba_note-5.ogg deleted file mode 100644 index 25ff35b92b..0000000000 Binary files a/sound/weapons/tuba_note-5.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note-6.ogg b/sound/weapons/tuba_note-6.ogg deleted file mode 100644 index 8bff99a27f..0000000000 Binary files a/sound/weapons/tuba_note-6.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note-7.ogg b/sound/weapons/tuba_note-7.ogg deleted file mode 100644 index 3cc7f9370d..0000000000 Binary files a/sound/weapons/tuba_note-7.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note-8.ogg b/sound/weapons/tuba_note-8.ogg deleted file mode 100644 index 23f54105bb..0000000000 Binary files a/sound/weapons/tuba_note-8.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note-9.ogg b/sound/weapons/tuba_note-9.ogg deleted file mode 100644 index c15291c712..0000000000 Binary files a/sound/weapons/tuba_note-9.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note0.ogg b/sound/weapons/tuba_note0.ogg deleted file mode 100644 index 64d73c49bb..0000000000 Binary files a/sound/weapons/tuba_note0.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note1.ogg b/sound/weapons/tuba_note1.ogg deleted file mode 100644 index d0b26e94f4..0000000000 Binary files a/sound/weapons/tuba_note1.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note10.ogg b/sound/weapons/tuba_note10.ogg deleted file mode 100644 index e5e81571e7..0000000000 Binary files a/sound/weapons/tuba_note10.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note11.ogg b/sound/weapons/tuba_note11.ogg deleted file mode 100644 index 042139973c..0000000000 Binary files a/sound/weapons/tuba_note11.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note12.ogg b/sound/weapons/tuba_note12.ogg deleted file mode 100644 index a0139f42af..0000000000 Binary files a/sound/weapons/tuba_note12.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note13.ogg b/sound/weapons/tuba_note13.ogg deleted file mode 100644 index b5794c3b0d..0000000000 Binary files a/sound/weapons/tuba_note13.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note14.ogg b/sound/weapons/tuba_note14.ogg deleted file mode 100644 index ae414fade6..0000000000 Binary files a/sound/weapons/tuba_note14.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note15.ogg b/sound/weapons/tuba_note15.ogg deleted file mode 100644 index 6193dc7f15..0000000000 Binary files a/sound/weapons/tuba_note15.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note16.ogg b/sound/weapons/tuba_note16.ogg deleted file mode 100644 index a7c3d64b5a..0000000000 Binary files a/sound/weapons/tuba_note16.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note17.ogg b/sound/weapons/tuba_note17.ogg deleted file mode 100644 index ce94216284..0000000000 Binary files a/sound/weapons/tuba_note17.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note18.ogg b/sound/weapons/tuba_note18.ogg deleted file mode 100644 index 47f9bc1a49..0000000000 Binary files a/sound/weapons/tuba_note18.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note19.ogg b/sound/weapons/tuba_note19.ogg deleted file mode 100644 index d51d714a6c..0000000000 Binary files a/sound/weapons/tuba_note19.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note2.ogg b/sound/weapons/tuba_note2.ogg deleted file mode 100644 index 4ee01b095f..0000000000 Binary files a/sound/weapons/tuba_note2.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note20.ogg b/sound/weapons/tuba_note20.ogg deleted file mode 100644 index 8598e49e86..0000000000 Binary files a/sound/weapons/tuba_note20.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note21.ogg b/sound/weapons/tuba_note21.ogg deleted file mode 100644 index 42e4d05bea..0000000000 Binary files a/sound/weapons/tuba_note21.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note22.ogg b/sound/weapons/tuba_note22.ogg deleted file mode 100644 index 40c9e6461f..0000000000 Binary files a/sound/weapons/tuba_note22.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note23.ogg b/sound/weapons/tuba_note23.ogg deleted file mode 100644 index 81e2215aa5..0000000000 Binary files a/sound/weapons/tuba_note23.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note24.ogg b/sound/weapons/tuba_note24.ogg deleted file mode 100644 index 8dafb9ba2f..0000000000 Binary files a/sound/weapons/tuba_note24.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note25.ogg b/sound/weapons/tuba_note25.ogg deleted file mode 100644 index 0ded2949cc..0000000000 Binary files a/sound/weapons/tuba_note25.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note26.ogg b/sound/weapons/tuba_note26.ogg deleted file mode 100644 index 39a7401f73..0000000000 Binary files a/sound/weapons/tuba_note26.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note27.ogg b/sound/weapons/tuba_note27.ogg deleted file mode 100644 index 6c87882045..0000000000 Binary files a/sound/weapons/tuba_note27.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note3.ogg b/sound/weapons/tuba_note3.ogg deleted file mode 100644 index 3057d3943a..0000000000 Binary files a/sound/weapons/tuba_note3.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note4.ogg b/sound/weapons/tuba_note4.ogg deleted file mode 100644 index 36e22c478f..0000000000 Binary files a/sound/weapons/tuba_note4.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note5.ogg b/sound/weapons/tuba_note5.ogg deleted file mode 100644 index 08c3c006fe..0000000000 Binary files a/sound/weapons/tuba_note5.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note6.ogg b/sound/weapons/tuba_note6.ogg deleted file mode 100644 index 2db08711ca..0000000000 Binary files a/sound/weapons/tuba_note6.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note7.ogg b/sound/weapons/tuba_note7.ogg deleted file mode 100644 index 89776e1f6b..0000000000 Binary files a/sound/weapons/tuba_note7.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note8.ogg b/sound/weapons/tuba_note8.ogg deleted file mode 100644 index 0ebea71b6e..0000000000 Binary files a/sound/weapons/tuba_note8.ogg and /dev/null differ diff --git a/sound/weapons/tuba_note9.ogg b/sound/weapons/tuba_note9.ogg deleted file mode 100644 index dc19ff433f..0000000000 Binary files a/sound/weapons/tuba_note9.ogg and /dev/null differ diff --git a/textures/campingrifle.tga b/textures/campingrifle.tga index 6d719e6bcf..6189b51e95 100644 Binary files a/textures/campingrifle.tga and b/textures/campingrifle.tga differ diff --git a/textures/campingrifle_glow.tga b/textures/campingrifle_glow.tga index b7a33d947a..f42532995f 100644 Binary files a/textures/campingrifle_glow.tga and b/textures/campingrifle_glow.tga differ diff --git a/textures/campingrifle_pants.tga b/textures/campingrifle_pants.tga deleted file mode 100644 index 633d3dd09a..0000000000 Binary files a/textures/campingrifle_pants.tga and /dev/null differ diff --git a/textures/campingrifle_shirt.tga b/textures/campingrifle_shirt.tga deleted file mode 100644 index 8944408de3..0000000000 Binary files a/textures/campingrifle_shirt.tga and /dev/null differ diff --git a/textures/cockpit_gloss.tga b/textures/cockpit_gloss.tga new file mode 100644 index 0000000000..422b5bd70a Binary files /dev/null and b/textures/cockpit_gloss.tga differ diff --git a/textures/cockpit_reflect.tga b/textures/cockpit_reflect.tga new file mode 100644 index 0000000000..ea39a453bd Binary files /dev/null and b/textures/cockpit_reflect.tga differ diff --git a/textures/crylink.tga b/textures/crylink.tga index f67d646740..c07f02a704 100644 Binary files a/textures/crylink.tga and b/textures/crylink.tga differ diff --git a/textures/crylink_gloss.tga b/textures/crylink_gloss.tga index 97016866eb..84e2c17c7c 100644 Binary files a/textures/crylink_gloss.tga and b/textures/crylink_gloss.tga differ diff --git a/textures/crylink_glow.jpg b/textures/crylink_glow.jpg index e73aaaa406..de4be8ef2e 100644 Binary files a/textures/crylink_glow.jpg and b/textures/crylink_glow.jpg differ diff --git a/textures/crylink_pants.tga b/textures/crylink_pants.tga deleted file mode 100644 index cc53e76a6d..0000000000 Binary files a/textures/crylink_pants.tga and /dev/null differ diff --git a/textures/crylink_reflect.tga b/textures/crylink_reflect.tga index 5c5109e694..ec7857b197 100644 Binary files a/textures/crylink_reflect.tga and b/textures/crylink_reflect.tga differ diff --git a/textures/electro.tga b/textures/electro.tga index 1fe74b161d..adf55c2ed5 100644 Binary files a/textures/electro.tga and b/textures/electro.tga differ diff --git a/textures/electro_glow.tga b/textures/electro_glow.tga index 91736effd5..9c6a5bfffe 100644 Binary files a/textures/electro_glow.tga and b/textures/electro_glow.tga differ diff --git a/textures/electro_pants.tga b/textures/electro_pants.tga deleted file mode 100644 index b8e70848b2..0000000000 Binary files a/textures/electro_pants.tga and /dev/null differ diff --git a/textures/electro_plasma.tga b/textures/electro_plasma.tga index f57bc18ac2..a0600288cc 100644 Binary files a/textures/electro_plasma.tga and b/textures/electro_plasma.tga differ diff --git a/textures/electro_plasma_glow.tga b/textures/electro_plasma_glow.tga index f57bc18ac2..a0600288cc 100644 Binary files a/textures/electro_plasma_glow.tga and b/textures/electro_plasma_glow.tga differ diff --git a/textures/glauncher_glow.tga b/textures/glauncher_glow.tga new file mode 100644 index 0000000000..bd9367337d Binary files /dev/null and b/textures/glauncher_glow.tga differ diff --git a/textures/glauncher_pants.tga b/textures/glauncher_pants.tga deleted file mode 100644 index 1f3957e1e2..0000000000 Binary files a/textures/glauncher_pants.tga and /dev/null differ diff --git a/textures/glscope.tga b/textures/glscope.tga index f582ce6633..22c345637d 100644 Binary files a/textures/glscope.tga and b/textures/glscope.tga differ diff --git a/textures/glscope_glow.tga b/textures/glscope_glow.tga index f582ce6633..22c345637d 100644 Binary files a/textures/glscope_glow.tga and b/textures/glscope_glow.tga differ diff --git a/textures/hagar2.tga b/textures/hagar2.tga index 2b77dd918e..f05fef985c 100644 Binary files a/textures/hagar2.tga and b/textures/hagar2.tga differ diff --git a/textures/hagar2_glow.tga b/textures/hagar2_glow.tga index 9fff206a22..cd4b353123 100644 Binary files a/textures/hagar2_glow.tga and b/textures/hagar2_glow.tga differ diff --git a/textures/hagar2_pants.tga b/textures/hagar2_pants.tga deleted file mode 100644 index 5992dbf962..0000000000 Binary files a/textures/hagar2_pants.tga and /dev/null differ diff --git a/textures/hlac_accessory.tga b/textures/hlac_accessory.tga index 9fe31cc24a..7b86985c81 100644 Binary files a/textures/hlac_accessory.tga and b/textures/hlac_accessory.tga differ diff --git a/textures/hlac_accessory_glow.tga b/textures/hlac_accessory_glow.tga new file mode 100644 index 0000000000..c322008068 Binary files /dev/null and b/textures/hlac_accessory_glow.tga differ diff --git a/textures/hlac_accessory_pants.tga b/textures/hlac_accessory_pants.tga deleted file mode 100644 index 23516cc89d..0000000000 Binary files a/textures/hlac_accessory_pants.tga and /dev/null differ diff --git a/textures/hlac_body.tga b/textures/hlac_body.tga index c4c6882a20..fa24925a76 100644 Binary files a/textures/hlac_body.tga and b/textures/hlac_body.tga differ diff --git a/textures/hlac_body_glow.tga b/textures/hlac_body_glow.tga index fffafabf98..c9c04abf94 100644 Binary files a/textures/hlac_body_glow.tga and b/textures/hlac_body_glow.tga differ diff --git a/textures/hlac_body_pants.tga b/textures/hlac_body_pants.tga deleted file mode 100644 index 32ee034605..0000000000 Binary files a/textures/hlac_body_pants.tga and /dev/null differ diff --git a/textures/hlac_body_shirt.tga b/textures/hlac_body_shirt.tga index c3bddd150d..32ee034605 100644 Binary files a/textures/hlac_body_shirt.tga and b/textures/hlac_body_shirt.tga differ diff --git a/textures/hlac_glass.tga b/textures/hlac_glass.tga new file mode 100644 index 0000000000..e0ed0a7206 Binary files /dev/null and b/textures/hlac_glass.tga differ diff --git a/textures/hlac_metal.tga b/textures/hlac_metal.tga index 5842c4f6ca..264a8cdf01 100644 Binary files a/textures/hlac_metal.tga and b/textures/hlac_metal.tga differ diff --git a/textures/hlac_metal_glow.tga b/textures/hlac_metal_glow.tga index 3a6abf5f11..a20be9f640 100644 Binary files a/textures/hlac_metal_glow.tga and b/textures/hlac_metal_glow.tga differ diff --git a/textures/hlac_plasma.tga b/textures/hlac_plasma.tga new file mode 100644 index 0000000000..956b241762 Binary files /dev/null and b/textures/hlac_plasma.tga differ diff --git a/textures/hookgun_pants.tga b/textures/hookgun_pants.tga deleted file mode 100644 index 327822d4ef..0000000000 Binary files a/textures/hookgun_pants.tga and /dev/null differ diff --git a/textures/hookgun_shirt.tga b/textures/hookgun_shirt.tga new file mode 100644 index 0000000000..327822d4ef Binary files /dev/null and b/textures/hookgun_shirt.tga differ diff --git a/textures/laser.tga b/textures/laser.tga index d651d382f9..c0f2bc78c6 100644 Binary files a/textures/laser.tga and b/textures/laser.tga differ diff --git a/textures/laser_glow.tga b/textures/laser_glow.tga index 9e7eb10357..90e32e7235 100644 Binary files a/textures/laser_glow.tga and b/textures/laser_glow.tga differ diff --git a/textures/laser_pants.tga b/textures/laser_pants.tga deleted file mode 100644 index 4566bc0472..0000000000 Binary files a/textures/laser_pants.tga and /dev/null differ diff --git a/textures/minelayer.tga b/textures/minelayer.tga index e0fa48c143..834a987bd6 100644 Binary files a/textures/minelayer.tga and b/textures/minelayer.tga differ diff --git a/textures/minelayer_glow.tga b/textures/minelayer_glow.tga index 163735f7fa..34e865f0c8 100644 Binary files a/textures/minelayer_glow.tga and b/textures/minelayer_glow.tga differ diff --git a/textures/nex.tga b/textures/nex.tga deleted file mode 100644 index 1fdc59a78d..0000000000 Binary files a/textures/nex.tga and /dev/null differ diff --git a/textures/nex_bump.tga b/textures/nex_bump.tga deleted file mode 100644 index b833a51f82..0000000000 Binary files a/textures/nex_bump.tga and /dev/null differ diff --git a/textures/nex_gloss.tga b/textures/nex_gloss.tga deleted file mode 100644 index 8bfd691e80..0000000000 Binary files a/textures/nex_gloss.tga and /dev/null differ diff --git a/textures/nex_glow.tga b/textures/nex_glow.tga deleted file mode 100644 index 915001cde7..0000000000 Binary files a/textures/nex_glow.tga and /dev/null differ diff --git a/textures/nex_norm.tga b/textures/nex_norm.tga deleted file mode 100644 index a5bafa8f2a..0000000000 Binary files a/textures/nex_norm.tga and /dev/null differ diff --git a/textures/nex_pants.tga b/textures/nex_pants.tga deleted file mode 100644 index 6fc3833df3..0000000000 Binary files a/textures/nex_pants.tga and /dev/null differ diff --git a/textures/nex_reflect.tga b/textures/nex_reflect.tga deleted file mode 100644 index c44e7befd2..0000000000 Binary files a/textures/nex_reflect.tga and /dev/null differ diff --git a/textures/nex_shirt.tga b/textures/nex_shirt.tga deleted file mode 100644 index 7cd8f52c85..0000000000 Binary files a/textures/nex_shirt.tga and /dev/null differ diff --git a/textures/pickups.tga b/textures/pickups.tga deleted file mode 100644 index ee2a1f5631..0000000000 Binary files a/textures/pickups.tga and /dev/null differ diff --git a/textures/pickups_bump.tga b/textures/pickups_bump.tga deleted file mode 100644 index 90acf588ce..0000000000 Binary files a/textures/pickups_bump.tga and /dev/null differ diff --git a/textures/pickups_gloss.tga b/textures/pickups_gloss.tga deleted file mode 100644 index 4f310bfcff..0000000000 Binary files a/textures/pickups_gloss.tga and /dev/null differ diff --git a/textures/pickups_glow.tga b/textures/pickups_glow.tga deleted file mode 100644 index d74702995e..0000000000 Binary files a/textures/pickups_glow.tga and /dev/null differ diff --git a/textures/portalgun.tga b/textures/portalgun.tga index 420bf15654..9da7035651 100644 Binary files a/textures/portalgun.tga and b/textures/portalgun.tga differ diff --git a/textures/portalgun_glow.tga b/textures/portalgun_glow.tga index 1719b0511b..3a36355fb2 100644 Binary files a/textures/portalgun_glow.tga and b/textures/portalgun_glow.tga differ diff --git a/textures/raptor.jpg b/textures/raptor.jpg deleted file mode 100644 index 8a1cdcebb0..0000000000 Binary files a/textures/raptor.jpg and /dev/null differ diff --git a/textures/raptor.tga b/textures/raptor.tga new file mode 100644 index 0000000000..2037f7b10b Binary files /dev/null and b/textures/raptor.tga differ diff --git a/textures/raptor_cockpit.jpg b/textures/raptor_cockpit.jpg deleted file mode 100644 index fd999b57f6..0000000000 Binary files a/textures/raptor_cockpit.jpg and /dev/null differ diff --git a/textures/rl_glow.tga b/textures/rl_glow.tga new file mode 100644 index 0000000000..755f96a22d Binary files /dev/null and b/textures/rl_glow.tga differ diff --git a/textures/rl_pants.tga b/textures/rl_pants.tga deleted file mode 100644 index 9f7cd2eaf9..0000000000 Binary files a/textures/rl_pants.tga and /dev/null differ diff --git a/textures/seeker.tga b/textures/seeker.tga index e275817b59..3e70ade018 100644 Binary files a/textures/seeker.tga and b/textures/seeker.tga differ diff --git a/textures/seeker_glow.tga b/textures/seeker_glow.tga index 84acdbc3eb..79acae87d3 100644 Binary files a/textures/seeker_glow.tga and b/textures/seeker_glow.tga differ diff --git a/textures/seeker_pants.tga b/textures/seeker_pants.tga deleted file mode 100644 index 471fe0c043..0000000000 Binary files a/textures/seeker_pants.tga and /dev/null differ diff --git a/textures/seeker_shirt.tga b/textures/seeker_shirt.tga new file mode 100644 index 0000000000..471fe0c043 Binary files /dev/null and b/textures/seeker_shirt.tga differ diff --git a/textures/shotgun2_glow.tga b/textures/shotgun2_glow.tga index 863f3830b5..10e3c433c8 100644 Binary files a/textures/shotgun2_glow.tga and b/textures/shotgun2_glow.tga differ diff --git a/textures/shotgun2_shirt.tga b/textures/shotgun2_shirt.tga index 442ced63a6..8bc227c20c 100644 Binary files a/textures/shotgun2_shirt.tga and b/textures/shotgun2_shirt.tga differ diff --git a/textures/shotgun_sight.tga b/textures/shotgun_sight.tga index bc74918718..36ce078d00 100644 Binary files a/textures/shotgun_sight.tga and b/textures/shotgun_sight.tga differ diff --git a/textures/shotgun_sight_glow.tga b/textures/shotgun_sight_glow.tga new file mode 100644 index 0000000000..e432842572 Binary files /dev/null and b/textures/shotgun_sight_glow.tga differ diff --git a/textures/spiderbot_reflect.tga b/textures/spiderbot_reflect.tga new file mode 100644 index 0000000000..a2a4a047ef Binary files /dev/null and b/textures/spiderbot_reflect.tga differ diff --git a/textures/uzi_glow.tga b/textures/uzi_glow.tga index de6d9db315..ee180f442a 100644 Binary files a/textures/uzi_glow.tga and b/textures/uzi_glow.tga differ diff --git a/textures/uzi_pants.tga b/textures/uzi_pants.tga deleted file mode 100644 index 62f6659ed8..0000000000 Binary files a/textures/uzi_pants.tga and /dev/null differ diff --git a/textures/wakazachi_gloss.jpg b/textures/wakazachi_gloss.jpg new file mode 100644 index 0000000000..2c7878cb1d Binary files /dev/null and b/textures/wakazachi_gloss.jpg differ diff --git a/textures/wakazachi_glow.tga b/textures/wakazachi_glow.tga new file mode 100644 index 0000000000..89e4813563 Binary files /dev/null and b/textures/wakazachi_glow.tga differ diff --git a/textures/wakazachi_reflect.tga b/textures/wakazachi_reflect.tga new file mode 100644 index 0000000000..cb88c1ad78 Binary files /dev/null and b/textures/wakazachi_reflect.tga differ diff --git a/tooltips.db b/tooltips.db index e8aa0f6cd1..5e2a0e83b1 100644 --- a/tooltips.db +++ b/tooltips.db @@ -7,9 +7,8 @@ \menu_slist_showempty\Show empty servers \menu_slist_showfull\Show full servers that have no slots available \net_slist_pause\Pause updating the server list to prevent servers from "jumping around" -\XonoticMultiplayerDialog/Info\Show more information about the currently highlighted server +\XonoticMultiplayerDialog/Info...\Show more information about the currently highlighted server \XonoticMultiplayerDialog/Bookmark\Bookmark the currently highlighted server so that it's faster to find in the future -\XonoticMultiplayerDialog/Havoc\Change to Havoc mode which has some modifications to the gameplay \XonoticMultiplayerDialog/Create\Host your own game \XonoticMultiplayerDialog/Demos\Browse and view demos \XonoticMultiplayerDialog/Player Setup\Customize your player settings @@ -29,9 +28,10 @@ \sv_vote_simple_majority_factor\Simple majority wins a vote \XonoticMultiplayerDialog/Advanced settings...\Advanced server settings \XonoticMultiplayerDialog/Mutators...\Mutators and weapon arenas +\g_dodging\Enable dodging \g_cloaked\All players are almost invisible \g_footsteps\Enable footstep sounds -\g_midair\Only possible to inflict damage on your enemy while he's airborn +\g_midair\Only possible to inflict damage on your enemy while he's airborne \g_vampire\Damage done to your enemy gets added to your own health \g_bloodloss\Amount of health below which your player gets stunned because of blood loss \sv_gravity\Make things fall to the ground slower, lower value means lower gravity @@ -42,10 +42,10 @@ \g_weaponarena\Selecting a weapon arena will give all players that weapon at spawn as well as unlimited ammo, and disable all other weapon pickups. \menu_weaponarena_with_laser\Also enable the laser in the weapon arena \g_minstagib\Players will be given the Minstanex, which is a railgun with infinite damage. If the player runs out of ammo, he will have 10 seconds to find some or if he fails to do so, face death. The secondary fire mode is a laser which does not inflict any damage and is good for doing trickjumps. -\g_nixnex\No items Xonotic - instead of pickup items, everyone plays with the same weapon. After some time, a countdown will start, after which everyone will switch to another weapon. -\g_nixnex_with_laser\Always carry the laser as an additional weapon in NixNex -\XonoticMultiplayerDialog/All\Select all maps -\XonoticMultiplayerDialog/None\Unselect all maps +\g_nix\No items Xonotic - instead of pickup items, everyone plays with the same weapon. After some time, a countdown will start, after which everyone will switch to another weapon. +\g_nix_with_laser\Always carry the laser as an additional weapon in Nix +\XonoticMultiplayerDialog/Select all\Select all maps +\XonoticMultiplayerDialog/Select none\Unselect all maps \XonoticMultiplayerDialog/Timedemo\Benchmark how fast your computer can run the highlighted demo @@ -63,14 +63,12 @@ \cl_gunalign\Position of the weapon model; requires reconnect \crosshair_per_weapon\Set a different crosshair for each weapon, good if you play without weapon models -\crosshair_color_override\Also set the color of the crosshair depending on the weapon you are currently holding +\crosshair_color_per_weapon\Set the color of the crosshair depending on the weapon you are currently holding \crosshair_size\Adjust the size of the crosshair -\crosshair_color_alpha\Adjust the opacity of the crosshair -\crosshair_color_red\Red color component of the crosshair color -\crosshair_color_green\Green color component of the crosshair color -\crosshair_color_blue\Blue color component of the crosshair color +\crosshair_alpha\Adjust the opacity of the crosshair +\crosshair_color\Adjust the crosshair color \sbar_hudselector\Use the old HUD layout -\XonoticMultiplayerDialog/Radar, HUD & Waypoints...\Adjust the radar, HUD and waypoints +\XonoticMultiplayerDialog/Waypoints setup...\- \_cl_name\Name under which you will appear in the game \XonoticSettingsDialog\Change the game settings @@ -96,8 +94,6 @@ \m_pitch\Invert mouse movement on the Y-axis \vid_dgamouse\Make use of DGA mouse input \con_closeontoggleconsole\Allow the console toggling bind to also close the console -\sbar_showbinds\Display actions / bound keys in the strings shown during the game -\cl_showpressedkeys\Show which movement keys the player is pressing \XonoticSettingsDialog/Video\Video settings \vid_width\Screen resolution @@ -155,16 +151,16 @@ \r_damageblur\Amount of motion blur when hurt - 0.4 recommended \XonoticSettingsDialog/Audio\Audio settings +\mastervolume\- \bgmvolume\- -\volume\- \snd_staticvolume\- -\snd_worldchannel0volume\- -\snd_entchannel3volume\- -\snd_playerchannel6volume\- -\snd_playerchannel7volume\- -\snd_entchannel4volume\- -\snd_playerchannel2volume\- -\snd_playerchannel1volume\- +\snd_channel0volume\- +\snd_channel3volume\- +\snd_channel6volume\- +\snd_channel7volume\- +\snd_channel4volume\- +\snd_channel2volume\- +\snd_channel1volume\- \snd_speed\Sound output frequency \snd_channels\Number of channels for the sound output \snd_swapstereo\Swap left/right channels @@ -187,32 +183,17 @@ \cl_port\Force client to use chosen port unless it is set to 0 \XonoticSettingsDialog/Misc\Misc settings +\menu_tooltips\Menu tooltips: disabled, standard or advanced (also shows cvar or console command bound to the menu item) \showtime\Show current time of day, useful on screenshots \showdate\Show current date, useful on screenshots \showfps\Show your rendered frames per second -\cl_showspeed\Show the speed of the player -\cl_showspeed_unit\Select the unit used by the speedometer. qu/s = in/s -\cl_showacceleration\Show the acceleration of the player -\cl_showacceleration_scale\Excaggerate the accelerometer by this scale multiplier \XonoticSettingsDialog/Advanced settings...\Advanced settings where you can tweak every single variable of the game \g_friendlyfire\Percentage of damage dealt to teammates \g_mirrordamage\Percentage of teamdamage that will be mirrored to you \g_tdm_teams_override\Override the default amount of teams in teamgames -\cl_teamradar_position\- -\cl_teamradar_size\- -\cl_teamradar_zoommode\- -\cl_teamradar_rotation\- -\cl_teamradar_scale\- -\cl_teamradar_foreground_alpha\- -\cl_teamradar_background_alpha\Opacity value of the radar background \viewsize\Enable/disable the HUD background -\sbar_alpha_bg\Opacity value of the HUD background -\sbar_color_bg_r\Red color component of the HUD background -\sbar_color_bg_g\Green color component of the HUD background -\sbar_color_bg_b\Blue color component of the HUD background -\sbar_color_bg_team\Team color saturation of the HUD background \cl_hidewaypoints\Show various gametype specific waypoints \g_waypointsprite_scale\Scale multiplier of the waypoints \g_waypointsprite_alpha\Control transparency of the waypoints diff --git a/tooltips.db.de b/tooltips.db.de new file mode 100644 index 0000000000..08a30a97b3 --- /dev/null +++ b/tooltips.db.de @@ -0,0 +1,226 @@ +0 +\XonoticSingleplayerDialog\Spiele die Einzelspieler-Kampagne oder habe Instant-Action Spiele gegen Bots + + +\XonoticMultiplayerDialog\Spiele online, gegen deine Freunde im LAN, gucke dir Demos an oder ändere deine Spieler-Einstellungen +\XonoticMultiplayerDialog/Server\Finde Server und spiele online +\menu_slist_showempty\Aktiviere die Anzeige von leeren Servern +\menu_slist_showfull\Aktiviere die Anzeige von vollen Servern, die keinen freien Platz mehr haben +\net_slist_pause\Unterbreche die automatische Aktualisierung der Serverliste um ein "Herumspringen" zu verhindern +\XonoticMultiplayerDialog/Info...\Lass dir mehr Informationen über den markierten Server anzeigen +\XonoticMultiplayerDialog/Speichern\Setze ein Lesezeichen für den markierten Server um ihn beim nächsten mal schneller wiederzufinden +\XonoticMultiplayerDialog/Starten\Hoste dein eigenes Spiel +\XonoticMultiplayerDialog/Demos\Gucke dir Demos an +\XonoticMultiplayerDialog/Spieler-Einstellungen\Ändere deine Spieler-Einstellungen + +\XonoticTeamSelectDialog/'bestem' Team beitreten\Automatische Auswahl des Teams (bevorzugt) +\XonoticTeamSelectDialog/rot\Trete dem roten Team bei +\XonoticTeamSelectDialog/blau\Trete dem blauen Team bei +\XonoticTeamSelectDialog/gelb\Trete dem gelben Team bei +\XonoticTeamSelectDialog/pink\Trete dem pinken Team bei + +\timelimit_override\Wähle ein Zeitlimit bei dem die Map endet oder verwende den Map-Standard für diese Option. +\fraglimit_override\Wähle die Anzahl an Frags die benötigt wird, damit die Map endet oder verwende den Map-Standard für diese Option. +\menu_maxplayers\Wähle die maximale Anzahl der Spieler, welche sich mit deinem Server gleichzeitig verbinden dürfen. Freie Plätze können mit Bots aufgefüllt werden. +\bot_number\Wähle die maximale Anzahl von Bots auf dem Server. +\skill\Stelle die Stärke der Bots ein. +\g_maplist_votable\Anzahl von Maps, welche am Ende des Spiels zur Wahl stehen. +\sv_vote_simple_majority_factor\Die einfache Mehrheit gewinnt die Abstimmung. +\XonoticMultiplayerDialog/Erweiterte Einstellungen...\Erweiterte Einstellungen für den Server +\XonoticMultiplayerDialog/Mutators...\Wähle Mutators und Waffen-Arenen. +\g_dodging\Ausweichmodus: Es ist möglich rasch zur Seite zu springen (spezielle Bewegung). +\g_cloaked\Tarnmodus: Alle Spieler sind fast unsichtbar. +\g_footsteps\Schrittklang: Schritte von Spielern erzeugen Geräusche. +\g_midair\"Luft"modus: Dem Gegner Schaden zuzufügen ist nur möglich, wenn er sich in der Luft befindet. +\g_vampire\Vampirmodus: Der Schaden dem du anderen Spielern zufügst, wird deiner eigenen Lebensenergie hinzugefügt. +\g_bloodloss\Blutverlust: Aktiviere diesen Modus und stelle den Wert der Lebensenergie, bei der Spieler auf Grund von Blutverlust betäubt wirken, ein. +\sv_gravity\Verringere die Schwerkraft und lass Gegenstände langsamer zu Boden fallen, ein niedrigerer Wert verringert die Gravitation. +\g_grappling_hook\Neu erzeugte/auferstandene Spieler starten mit dem Enterhaken. +\g_jetpack\Neu erzeugte/auferstandene Spieler starten mit dem Jetpack. +\g_pinata\Gestorbene Spieler lassen alle Waffen fallen, die sie besaßen - Waffen verschwinden nicht. +\g_rocket_flying\Raketen fliegen in allen Physikeinstellungen. +\g_weapon_stay\Alle Waffen bleiben liegen, auch wenn sie aufgenommen wurden. +\g_weaponarena\Waffen-Arenen: Die Auswahl einer Waffen-Arena führt dazu, dass jeder Spieler mit der gewählten Waffe startet. Diese hat unendlich viel Munition, andere Waffen sind nicht vorhanden. - Spezielle Waffen-Arenen: Spieler starten mit allen Waffen und unendlich viel Munition +\menu_weaponarena_with_laser\Aktiviere auch den Laser in der Waffen-Arena. +\g_minstagib\Alle Spieler starten mit der Minstanex, eine elektromagnetische Schienenkanone mit unendlich viel Schaden. Wenn ein Spieler keine Munition mehr hat, bleiben ihm 10 Sekunden um neue zu finden, ansonsten stirbt er. Der 2. Feuermodus ist Laser, welcher keinen Schaden hinzufügen kann. Dieser eignet sich gut für Tricksprünge. +\g_nix\Es gibt keine aufzusammelnden Gegenstände in Xonotic - Anstelle der Möglichkeit Waffen aufzusammeln, spielen alle mit der gleichen Waffe. Nach einiger Zeit startet ein Countdown, danach wechseln alle Spieler zu einer neuen gleichen Waffe. +\g_nix_with_laser\In Nix ist als zweite Waffe der Laser vorhanden. +\XonoticMultiplayerDialog/Select all\Wähle alle Maps. +\XonoticMultiplayerDialog/Select none\Wähle alle Maps ab. + + +\XonoticMultiplayerDialog/Timedemo\Mache einen Benchmark-Test der markierten Demo. Die Demo wird in Zeitraffer, -lupe abgespielt. Das Ergebnis wird in "gamedir/data/benchmark.log" gespeichert. + +\fov\Stelle den Wert für das Sichtfeld in Grad (60-130) ein - Standard ist 90. +\cl_bobcycle\Setze einen Wert für das Sicht-Wackeln oder deaktiviere es vollständig. +\cl_zoomfactor\Setze den Vergrößerungsfaktor. +\cl_zoomsensitivity\Bestimme die Änderung der Empfindlichkeit während des Vergrößerns. Werte von 0 (geringste Sensiviät) bis 1 (keine Änderung der Sensivität sind möglich). +\cl_zoomspeed\Bestimme wie schnell der angegebene Vergrößerungsfaktor erreicht werden soll, deaktivieren für sofortige Vergrößerung. +\XonoticMultiplayerDialog/Waffeneinstellungen...\Lege deine bevorzugten Waffen fest, den automatischen Wechsel der Waffen und weiteres. + +\cl_weaponpriority_useforcycling\Verwende die oben angegebene Liste, wenn die Waffen mit Hilfe des Mausrads gewechselt werden. +\cl_autoswitch\Wechsel automatisch zu der neu aufgesammelten Waffe, wenn diese in der Liste weiter oben steht als die, welche Du gerade trägst. +\r_drawviewmodel\Darstellung der Waffe im Spiel. +\cl_gunalign\Position der Waffe, links oder rechts; erfordert Neustart. + +\crosshair_per_weapon\Ermögliche unterschiedliche Fadenkreuze für unterschiedliche Waffen. Diese Option ist zu empfehlen, wenn du ohne dargstelltes Waffenmodel spielst. +\crosshair_color_override\Ermögliche unterschiedliche Farben für unterschiedliche Fandenkreuze, abhängig von der Waffe die gerade getragen wird. +\crosshair_size\Lege die Größe des Fadenkreuzes fest. +\crosshair_color_alpha\Lege die Opazität des Fadenkreuzes fest. +\crosshair_color_by_health\Die Einfärbung des Fadenkreuzes ist abhängig von der Lebensenergie. +\crosshair_color_red\Roter Farbanteil des Fadenkreuzes. +\crosshair_color_green\Grüner Farbanteil des Fadenkreuzes. +\crosshair_color_blue\Blauer Farbanteil des Fadenkreuzes. +\sbar_hudselector\Verwende das alte HUD Layout. +\XonoticMultiplayerDialog/Waypoints setup...\- +\_cl_name\Lege deinen Namen im Spiel fest. + +\XonoticSettingsDialog\Ändere die Spiel-Einstellungen +\XonoticCreditsDialog\Die Xonotic Entwickler +\XonoticTeamSelectDialog\- +\XonoticMutatorsDialog\- +\XonoticMapInfoDialog\- +\XonoticUserbindEditDialog\- +\XonoticWinnerDialog\- +\XonoticWeaponsDialog\- +\XonoticRadarDialog\- +\XonoticServerInfoDialog\- +\XonoticCvarsDialog\- + +\XonoticQuitDialog\Beende das Spiel +\XonoticQuitDialog/Ja\Zurück an die Arbeit... +\XonoticQuitDialog/Nein\Ich muss noch ein paar Typen fraggen! + +\XonoticSettingsDialog/Eingabe\Einstellungen der Eingabe +\sensitivity\Geschwindigkeitsmultiplikator um die Sensivität der Maus einzustellen. +\menu_mouse_speed\Multiplikator für die Geschwindigkeit der Maus im Menü, hat keinen Effekt auf die Mausbewegung im Spiel. +\m_filter\Glättet die Mausbewegung, aber verringert die Reaktion des Zielens etwas. +\m_pitch\Umkehren der Mausbewegung entlang der Y-Achse. +\vid_dgamouse\Verwende die DGA Maus Eingabe. +\joy_enable\Zur Verwendung eines Joysticks aktivieren. +\con_closeontoggleconsole\Schließen der Konsole auch mit der Taste, die zum Öffnen verwendet wird +\sbar_showbinds\Darstellung von gedrückten Aktionen / gedrückten Tasten, während des Spielens. +\cl_showpressedkeys\Lass dir die gedrückten Tasten während des Spielens anzeigen. + +\XonoticSettingsDialog/Grafik\Grafik Einstellungen + +\vid_width\Einstellung der zu verwendenden Bildschirmauflösung +\vid_bitsperpixel\Bestimme wie viele Bits pro Pixel (BPP) gerendert werden sollen, 32 ist der bevorzugte Wert +\vid_fullscreen\Aktiviere den Vollbildmodus (Standard: aktiviert) +\vid_vsync\Aktiviere die vertikale Synchronization um ein Zeilenreißen zu unterdrücken, die FPS werden auf den Wert der Bildwiederholungsrate deines Monitors gesetzt (Standard: deaktiviert) +\vid_gl20\Aktiviere OpenGL 2.0 für Lichteffekte (Standard: aktiviert) +\gl_vbo\Speicher Eckpunkte und/oder Dreiecke der statischen Geometrie im Videospeicher um ein schnelleres Rendern zu ermöglichen (Standard: Eckpunkte, einige Dreiecke) +\r_depthfirst\Verhindere das Überblenden, in dem das Tiefenbild der Szene vor dem Licht gerendert wird (Standard: nur Map) +\gl_texturecompression\Komprimiere die Texturen für Grafikkarten mit einem geringen Grafikspeicher (Standard: deaktiviert) +\gl_finish\Die Grafikkarte wartet bis die CPU die Berechnung eines jeden Frames beendet hat, dies kann bei merkwürdigen Verhalten der Eingabe helfen (Standard: deaktiviert) +\v_brightness\Helligkeit von Schwarz (Standard: 0) +\v_contrast\Helligkeit von Weiß (Standard: 1) +\v_gamma\Korrekturwert für die Kontraststärke (Gamma-Wert), Helligkeitseffekt, der keinen Einfluss auf Weiß und Schwarz hat (Standard: 1) +\v_contrastboost\Faktor für die Änderung des Kontrasts in dunklen Bildteilen (Standard: 1) +\r_glsl_saturation\Sättigungskorrektur (0 = Graustufenbild, 1 = normales Bild, 2 = übersättigtes Bild), benötigt GLSL Farbkontrolle (Standard: 1) +\v_glslgamma\Aktiviere die Verwendung von GLSL um die Gamma-Korrektur zu ermöglichen, kann die Leistung stark verringern (Standard: Aus) +\r_ambient\Umgebungslicht, ein zu hoch eingestellter Wert lässt die Map matt und flach erscheinen (Standard: 4) +\r_hdr_scenebrightness\Globales Rendern der Lichtstärke (Standard: 1) +\vid_samples\Aktiviere Antialiasing um Ecken der 3D-Geometire zu glätten. Kann die Leistung stark verringern (Standard: Aus) +\v_flipped\Linkshänder Modus (Standard: deaktiviert) + +\XonoticSettingsDialog/Effekte\Einstellungen der Effekte +\r_subdivisions_tolerance\Ändere die Qualität der Geometrie in der Map - Rundheit/Glattheit von Kurven (Standard: Gut) +\gl_picmip\Ändere die Auflösung von Texturen. Ein geringerer Wert verringert die Auslastung des Speichers, aber lässt die Texturen verschwommen aussehen. (Standard: Gut) +\gl_texturecompression\Wenn aktiviert, wird die Kompression von Texturen verhindert. +\r_picmipworld\Wenn aktiviert, wird nur die Texturqualität von Modellen verringert (Standard: aktiviert) +\mod_q3bsp_nolightmaps\Verwende hochauflösende Lightmaps, welche sehr schön aussehen, aber etwas mehr Videospeicher benötigen. (Standard: aktiviert) +\cl_particles_quality\Faktor für die Anzahl von Partikel. Weniger beudetet weniger Parikel, was zu einer besseren Performance führt. (Standard: 1.0) +\r_drawparticles_drawdistance\Weiter, als eingestellt, entfernte Partikel werden nicht dargestellt (Standard 1000) +\cl_decals\Aktiviere Dekore (Einschusslöcher und Blut) (Standard: aktiviert) +\r_drawdecals_drawdistance\Weiter, als eingestellt, entfernte Dekore werden nicht dargestellt (Standard: 300) +\cl_decals_time\Zeit in Sekunden nach dem Dekore verschwinden (Standard: 2) +\cl_gentle\Blut und Fleischteile werden durch andere, nicht blutige, Effekte ersetzt +\cl_nogibs\Verringere die Anzahl von Fleischteilen oder entferne sie vollständig (Standard: Viele) +\v_kicktime\Wert für die Dauer der Beeinträchtigung der Sicht durch einen Schaden (Standard: 0) +\gl_texture_anisotropy\Qualität für das Filtern von Anisotropie (Standard: Aus) +\r_glsl_deluxemapping\Verwende ein-Pixel Lichteffekte (Standard: aktiviert) +\r_shadow_gloss\Aktiviere Glanzeffekte für Texturen, wenn die Textur es unterstützt. (Standard: aktiviert) +\gl_flashblend\Aktiviere schnell gerenderte dynamische Lichter. Es wird eine große Korona anstelle von eines richtigen dynamischen Lichts dargestellt. (Standard: aktiviert) +\r_shadow_realtime_dlight\Aktiviere das Rendern von dynamischen Lichtern, wie Explosionen und Raketen-Lichter. (Standard: aktiviert) +\r_shadow_realtime_dlight_shadows\Aktiviere das Rendern von Schatten von dynamischen Lichtern (Standard: deaktiviert) +\r_shadow_realtime_world\Aktiviere das Rendern der gesamten Echtzeit-Welt-Lichter. Hat einen großen Einfluss auf die Performance (Standard: deaktiviert) +\r_shadow_realtime_world_shadows\Aktiviere das Rendern von Schatten von Echtzeit-Welt-Lichter (Standard: deaktiviert) +\r_shadow_usenormalmap\Aktiviere die Verwendung von gerichteter Schattierung auf Texturen (Standard: aktiviert) +\r_showsurfaces\Komplettes Deaktivieren von Texturen für sehr langsame Hardware. Starke Verbesserung der Performace, sieht aber sehr komisch aus. (Standard: deaktiviert) +\r_glsl_offsetmapping\Effekt für den Tiefendruck von Texturen, dieser Effekt lässt Texturen mit Bumpmap aus der 2D Ebene "herausgedrückt" erscheinen (Deaktiviert: deaktiviert) +\r_glsl_offsetmapping_reliefmapping\Bessere Qualität des Offsetmappings, hat einen großen Einfluss auf die Leistung (Standard: deaktiviert) +\r_water\Reflektions- und Refraktionsqualität, hat einen großen Einfluss auf die Performance von Maps mit reflektierenden Oberflächen (Standard: deaktiviert) +\r_water_resolutionmultiplier\Auflösung von Reflektion und Refraktion (Standard: gut) +\r_coronas\Aktiviere die Korona um bestimmte Lichter (Standard: aktiviert) +\r_coronas_occlusionquery\Verringern der Korona - Angepasst an die Sichtbarkeit (Standard: deaktiviert) +\r_bloom\Aktiviere Überstrahlung, welche die umgebenden Pixel sehr hell erleuchteter Pixel erhellt. Dieser Effekt hat einen großen Einfluss auf die Leistung (Standard: deaktiviert) +\r_hdr\Bessere Qualität des Überstrahlunseffekts, hat einen sehr großen Einfluss auf die Leistung (Standard: deaktiviert) +\r_motionblur\Wert für die Bewegungsunschärfe - 0.5 empfohlen +\r_damageblur\Wert für die Unschärfe bei einer Verletzung - 0.4 empfohlen + +\XonoticSettingsDialog/Ton\Audio-Einstellungen +\mastervolume\- +\bgmvolume\- +\snd_staticvolume\- +\snd_channel0volume\- +\snd_channel3volume\- +\snd_channel6volume\- +\snd_channel7volume\- +\snd_channel4volume\- +\snd_channel2volume\- +\snd_channel1volume\- +\snd_speed\Ausgangsfrequenz des Tons +\snd_channels\Anzahl der Kanäle für die Audiowiedergabe +\snd_swapstereo\Linken und rechten Kanal der Stereowiedergabe tauschen +\snd_spatialization_control\Aktiviere "räumlicheren" Klang (Mischung des linken und rechten Kanals um die Stereo-Trennung leicht zu verringern, für Kopfhörer). +\cl_voice_directional\Aktiviere richtungsunabhängige Geräusche. +\cl_voice_directional_taunt_attenuation\Distanz in der spöttige Bemerkungen anderer Spieler gehört werden können. +\cl_autotaunt\Automatisches Abspielen einer spöttigen Bemerkung, wenn Gegner gefraggt wurden. +\cl_sound_maptime_warning\Abspielen einer Ansage für die verbleibenden Minuten des Spiels. +\cl_hitsound\Spiele einen Treffer-Sound, wenn der Spieler auf den gezielt wurde, getroffen wurde. +\menu_sounds\Sound abspielen, wenn auf ein Menüitem geklickt wird oder mit dem Mauszeiger auf das Menüitem gezeit wird. + +\XonoticSettingsDialog/Netzwerk\Netzwerk Einstellungen +\cl_movement\Aktiviere die Client-seitige Bewegungssimulation +\cl_nolerp\Enable network update smoothing +\shownetgraph\Anzeige eines Netzwerkgraphens für gesendete/empfangene Pakete und weitere Informationen +\_cl_rate\Gib deine Netzwerkgeschwindigkeit mit dem Schieberegler an. +\cl_netfps\Anzahl der Pakete die pro Sekunde zum Server, mit dem du verbunden bist, geschickt werden sollen. +\cl_curl_maxdownloads\Maximale Anzahl der gleichzeitigen HTTP/FTP Downloads +\cl_curl_maxspeed\Stelle die maximale Download Geschwindigkeit ein. +\cl_port\Stelle den zu verwendenden UDP Port als Client ein. Wenn der Port auf 0 gesetzt ist, wird kein Port erzwungen. + +\XonoticSettingsDialog/Sonstiges\Sonstige Einstellungen, wie Sprache, Menü-Skins +\showtime\Uhrzeit im Spiel anzeigen, geeignet für Screenshots +\showdate\Datum im Spiel anzeigen, geeignet für Screenshots +\showfps\Zeige die gerenderten Frames pro Sekunde +\cl_showspeed\Zeige die Gescheindigkeit des Spielers +\cl_showspeed_unit\Wähle die Einheit, in der die Geschindigkeit angezeigt werden soll, qu/s = in/s +\cl_showacceleration\Zeige die Beschleunigung des Spielers +\cl_showacceleration_scale\Skalierungsfaktor für das Akzelerometer + +\XonoticSettingsDialog/Erweiterte Einstellungen...\Erweiterte Einstellungen, in denen du jede beliebige Variable des Spiels ändern kannst +\g_friendlyfire\Prozentualer Anteil des Schadens, der Mitspielern hinzugefügt wird +\g_mirrordamage\Percentage of teamdamage that will be mirrored to you +\g_tdm_teams_override\Überschreibe die Standardgröße eines Teams in Teammodi + +\cl_teamradar_position\- +\cl_teamradar_size\- +\cl_teamradar_zoommode\- +\cl_teamradar_rotation\- +\cl_teamradar_scale\- +\cl_teamradar_foreground_alpha\- +\cl_teamradar_background_alpha\Wert für die Opazität des Radar-Hintergrunds +\viewsize\Aktiviere/Deaktiviere den HUD-Hintergrund +\sbar_alpha_bg\Wert für die Opazität des HUD-Hintergrunds +\sbar_color_bg_r\Roter Farbanteil des HUD-Hintergrunds +\sbar_color_bg_g\Grüner Farbanteil des HUD-Hintergrunds +\sbar_color_bg_b\Blauer Farbanteil des HUD-Hintergrunds +\sbar_color_bg_team\Team-Farben Sättigung des HUD-Hintergrunds +\cl_hidewaypoints\Lass dir verschiedene Spieltyp spezifische Wegpunkte anzeigen +\g_waypointsprite_scale\Skalierungsfaktor für Wegpunkte +\g_waypointsprite_alpha\Verändere den Wert der Transparenz von der Anzeige der Wegpunkte +\cl_shownames\Lass dir den Namen des Spielers anzeigen auf den du gerade zielst. + +\crosshair_hittest\None: do not do hit tests for the crosshair; TrueAim: blur the crosshair when you would not hit the wall; Enemies: also enlarge the crosshair when you would hit an enemy diff --git a/tooltips.db.es b/tooltips.db.es new file mode 100644 index 0000000000..21bc586bcd --- /dev/null +++ b/tooltips.db.es @@ -0,0 +1,221 @@ +0 +\XonoticSingleplayerDialog\ Empieza una campaña de un solo jugador o acción instantánea de batalla contra bots + + +\XonoticMultiplayerDialog\Juega online, contra tus amigos en LAN, ver demos o cambia la configuración del jugador +\XonoticMultiplayerDialog/Servidores\Encuentra servidores para jugar +\menu_slist_showempty\Mostrar servidores vacíos +\menu_slist_showfull\Mostrar los servidores que no tienen espacio disponible +\net_slist_pause\Pausa la actualización de la lista de servidores para evitar que salteen +\XonoticMultiplayerDialog/Info...\Mostrar mas información sobre el actual servidor resaltado +\XonoticMultiplayerDialog/Marcador\Marcar el actual servidor resaltado para que sea mas facil encontrarlo en un futuro +\XonoticMultiplayerDialog/Crear\Crear tu propio juego +\XonoticMultiplayerDialog/Demos\Navegar y ver demos +\XonoticMultiplayerDialog/Player Setup\Configuración de jugador + +\XonoticTeamSelectDialog/Unirse al'mejor' equipo (seleccion automática)\Auto seleccionar equipo (recomendado) +\XonoticTeamSelectDialog/rojo\Unirse al equipo rojo +\XonoticTeamSelectDialog/azul\Unirse al equipo azul +\XonoticTeamSelectDialog/amarillo\Unirse al equipo amarillo +\XonoticTeamSelectDialog/rosa\Unirse al equipo rosa + +\timelimit_override\Límite de tiempo en minutos que cuando pase, terminara el combate +\fraglimit_override\Cantidad de puntos necesarios antes de que termine el combate +\menu_maxplayers\La máxima cantidad de jugadores o bots que pueden conectarse a tu servidor a la vez +\bot_number\Cantidad de bots en tu servidor +\skill\Especificar que experiencia tendran los bots +\g_maplist_votable\Numero de mapas que seran mostrados en en voto dde mapas al final de un combate +\sv_vote_simple_majority_factor\La mayoria gana +\XonoticMultiplayerDialog/Advanced settings...\Configuración avanzada ddel servidor +\XonoticMultiplayerDialog/Mutators...\Mutators +\g_dodging\Activar esquivado +\g_cloaked\Todos los jugadores son casi invisibles +\g_footsteps\Activar sonidos de pasos +\g_midair\solo es posible dañar a tu enemigo mientras este en el aire +\g_vampire\Daño dado a tu enemigo sera añadido a tu propia vida +\g_bloodloss\Cantidad de vida sera afectada por perdida de sangre +\sv_gravity\Hace que las cosas caigan lentamente al suelo, un valor bajo significa baja gravedad +\g_grappling_hook\Los jugadores aparecen con un gancho para aferrarse +\g_jetpack\Los jugadores aparecen con el jetpack +\g_pinata\Los jugadores dejan todas las armas cuando mueren +\g_weapon_stay\Las armas quedan despues de que son tomadas +\g_weaponarena\Seleccionando un arma, dara a todos los jugadores cual arma se eligió asi como infinita munición, y deshabilita cualquier otra toma de arma. +\menu_weaponarena_with_laser\Tambien habilita el láser en la arena +\g_minstagib\Los jugadores tendran Minstanex, el cual es un railgun con daño infinito. Si el jugador queda sin munición, tendra 10 segundos para buscar mas o morira. El modo de disparo secundario es un laser que no inflige daño y es bueno para hacer bromas. +\g_nix\Xonotic sin items - en vez de recoger items, todos juegan con la misma arma. Despues de algún tiempo, comienza una cuenta regresiva, despues del cual todos juegan con otra arma. +\g_nix_with_laser\Siempre lleva el láser como arma adicional en Nix +\XonoticMultiplayerDialog/Select all\Seleccionar todos los mapas +\XonoticMultiplayerDialog/Select none\Deseleccionar todos los mapas + + +\XonoticMultiplayerDialog/Demo temporizado\Prueba cuan rápido tu computadora puede correr la demo seleccionada + +\fov\Campo de visión en grados de 60 a 130, 90 es el default +\cl_bobcycle\Frecuencia de balanceo de la vista +\cl_zoomfactor\Cuan grande es el factor de zoom cuando la tecla de zoom es presionada +\cl_zoomsensitivity\Cuanto el zoom cambia la sensibilidad, desde 0 (baja sensibilidad) a 1 (sin cambio de sensibilidad) +\cl_zoomspeed\Cuan rápido es la vista ampliada, deshabilitar para un zoom instantáneo +\XonoticMultiplayerDialog/Weapon settings...\Seleccionar tu arma preferida, cambio automático y modelo de arma + +\cl_weaponpriority_useforcycling\Haz uso de la lista de abajo when cambia de arma con la rueda del raton +\cl_autoswitch\Cambia automáticamente al arma recogida si es mejor que la que esta llevando +\r_drawviewmodel\Muestra el modelo de arma +\cl_gunalign\Posición del modelo de arma; requiere conexión + +\crosshair_per_weapon\Configura diferentes miras para cada arma, esto ayuda si estas jugando sin un modelo de arma +\crosshair_color_override\Tambien configura el color del punto de mira dependiendo del arma que uses actualmente +\crosshair_size\Ajusta el tamaño del punto de mira +\crosshair_color_alpha\Ajusta la opacidad del punto de mira +\crosshair_color_red\Componente rojo del color del punto de mira +\crosshair_color_green\Componente verde del color del punto de mira +\crosshair_color_blue\Componente azul del color del punto de mira +\sbar_hudselector\Usar el viejo diseño de HUD +\XonoticMultiplayerDialog/Waypoints setup...\- +\_cl_name\Nombre con el cual aparecerás en el juego + +\XonoticSettingsDialog\Cambiar la configuración del juego +\XonoticCreditsDialog\Los créditos de Xonotic +\XonoticTeamSelectDialog\- +\XonoticMutatorsDialog\- +\XonoticMapInfoDialog\- +\XonoticUserbindEditDialog\- +\XonoticWinnerDialog\- +\XonoticWeaponsDialog\- +\XonoticRadarDialog\- +\XonoticServerInfoDialog\- +\XonoticCvarsDialog\- + +\XonoticQuitDialog\Salir del juego +\XonoticQuitDialog/Si\Volver al trabajo... +\XonoticQuitDialog/No\Tengo algunos puntos más por hacer! + +\XonoticSettingsDialog/Entrada\configuración de entrada +\sensitivity\Multiplicador de velocidad del ratón +\menu_mouse_speed\Multiplicador de velocidad del raton en el menu, esto no afecta al apuntar en el juego +\m_filter\Suaviza el movimiento del raton, pero hace menos sensible al apuntar al objetivo +\m_pitch\Invierte el movimiento del raton en el eje Y +\vid_dgamouse\Hace uso de la entrada DGA del raton +\con_closeontoggleconsole\Permite el fijar un lazo de la consola para tambien cerrarla +\sbar_showbinds\Display actions / Teclas vinculadas en la cadena se mostrará en el juego +\cl_showpressedkeys\Mostrar el movimiento de teclas que el jugador esta presionando + +\XonoticSettingsDialog/Video\configuración de video +\vid_width\Resolución de pantalla +\vid_bitsperpixel\Cuantos bits por pixel (BPP) para renderizar, 32 es lo recomendado +\vid_fullscreen\Habilitar el modo de pantalla completa (habilitado por defecto) +\vid_vsync\Habilitar sincronización vertical para prevenir rasgaduras en la imagen, limitara los fps a la tasa de refresco del monitor (desactivado por defecto) +\r_glsl\Habilitar sombreado de pixel de OpenGL 2.0 (activado por defecto) +\gl_vbo\Haz uso de objetos de búfer de vertices para almacenar geometría estática en la memoria de video para acelerar el renderizado (Vertices y Triangulos por defecto) +\r_depthfirst\Eliminar sobre-dibujado renderizando una version de única profundidad de la escena antes de que comience la renderización normal (desactivado por defecto) +\gl_texturecompression\Comprimir las texturas para tarjetas de video con poca cantidad de memoria disponible (ninguno por defecto) +\gl_finish\Hacer que la CPU wait esperen que la gpu termine cada marco, puede ayudar con algunas extrañas entradas o retraso de video en algunas máquinas (desactivado por defecto) +\v_brightness\Brillo en negros (por defecto: 0) +\v_contrast\Brillo en blancos (por defecto: 1) +\v_gamma\Valor de corrección de gama inverso, un efecto de brillo que no afecta a blancos o negros (por defecto: 1.125) +\v_contrastboost\Por cuanto multiplicar el contraste en areas oscuras (por defecto: 1) +\r_glsl_saturation\Ajuste de saturación (0 = escala de grises, 1 = normal, 2 = sobresaturado), requiere un control de color (por defecto: 1) +\v_glslgamma\Abilita el uso de GLSL para aplicar en la corrección gama, note que esto podría disminuir mucho el rendimiento (default: disabled) +\r_ambient\iluminación del ambiente, si se configura en muy elevado, tiende a hacer luz en los mapas de imagen aburrida y plana (por defecto: 4) +\r_hdr_scenebrightness\Brillo del renderizador global (por defecto: 1) +\vid_samples\activar antialiasing, el cual suaviza los bordes en geometrias en 3D. Note que esto puede disminuir bastante el rendimiento (por defecto: desactivado) +\v_flipped\Invertir la imagen horizontalmente (por defecto: desactivado) + +\XonoticSettingsDialog/Efectos\configuración de efectos. +\r_subdivisions_tolerance\Cambiar la suavidad de las curvas en el mapa (por defecto: normal) +\gl_picmip\Cambiar la dureza de las texturas. Bajándolo efectivamente reducira el uso de la memoria de la textura, pero hará que las texturas aparezcan muy borrosas. (por defecto: bueno) +\r_picmipworld\Si se activa, solo reduce la calidad de texturas de los modelos (activado por defecto) +\mod_q3bsp_nolightmaps\Use mapas de alta resolución, hara que se vea lindo pero reducira la memoria de video (activado por defecto) +\cl_particles_quality\Multiplicador de cantidad de partículas. Menos significa menos partículas, lo cual dara mejor rendimiento (por defecto: 0.5) +\r_drawparticles_drawdistance\Las partículas que se alejen de esto no se dibujarán (por defecto: 1000) +\cl_decals\Activar decals (agujeros de balas y sangre) (habilitado por defecto) +\r_drawdecals_drawdistance\Los decals que se alejen de esta distancia no se dibujarán (por defecto: 300) +\cl_decals_time\Tiempo en segundos antes de que los decals desaparezcan (por defecto: 2) +\cl_gentle\Reemplazar sangre y tripas por cosas que no tengan nada de gore (desactivado por defecto) +\cl_nogibs\Reduce la cantidad de tripas o lo remueve completamente (por defecto: muchos) +\v_kicktime\Cuanto tiempo se verá el ultimo daño (por defecto: 0) +\gl_texture_anisotropy\Calidad de filtrado anisotrópico (por defecto: 1x) +\r_glsl_deluxemapping\Usar efectos de iluminado por pixel (activado por defecto) +\r_shadow_gloss\Activar el uso de glossmaps en texturas soportandolo (activado por defecto) +\gl_flashblend\Activar luces dinámicas por renderizado de coronas en vez de iluminación dinámica real (desactivado por defecto) +\r_shadow_realtime_dlight\Activar renderizado de luces dinámicas como explosiones y luces de cohete (activado por defecto) +\r_shadow_realtime_dlight_shadows\Activar renderizado de sombras de luces dinamicas (desactivado por defecto) +\r_shadow_realtime_world\Activar renderizado de la iluminación del mundo en tiempo real en mapas que lo soporten. Note que esto puede tener un gran impacto en el rendimiento. (desactivado por defecto) +\r_shadow_realtime_world_shadows\Activar renderizado de sombras de luces del mundo en tiempo real (desactivado por defecto) +\r_shadow_usenormalmap\Activar el uso de sombreado direccional en texturas (activado por defecto) +\r_showsurfaces\Desactivar texturas completamente para hardware muy lento. Esto aumentara el rendimiento en gran medida, pero se verça muy feo. (desactivado por defecto) +\r_glsl_offsetmapping\Efecto de mapeado del desplazamiento, que hará texturas con mapas de relieve parecerse como resaltado de la superficie plana de 2D (desactivado por defecto) +\r_glsl_offsetmapping_reliefmapping\Alta calidad de mapeado de desplazamiento, el cual también tiene un gran impacto en el rendimiento (desactivado por defecto) +\r_water\Calidad de refleccion y refracción, tiene un gran impacto en el rendimiento en mapas de superficies reflectantes (desactivado por defecto) +\r_water_resolutionmultiplier\Resolución de reflecciones/refracciones (por defecto: bueno) +\r_coronas\Habilitar iluminación en corona alrededor de ciertas luces (activado por defecto) +\r_coronas_occlusionquery\Coronas apagadas acorde a la visibilidad (activado por defecto) +\r_bloom\Activar efecto bloom, que ilumina los píxeles vecinos de píxeles muy brillantes.Tiene un gran impacto en el rendimiento. (desactivado por defecto) +\r_hdr\Versión de gran calidad de bloom, que tiene un gran impacto en el rendimiento. (desactivado por defecto) +\r_motionblur\Nivel de difuminado de movimiento - 0.5 recomendado +\r_damageblur\Cantidad de difuminado de movimiento en presencia de daños - 0.4 recomendado + +\XonoticSettingsDialog/Sonido\configuración de audio +\mastervolume\- +\bgmvolume\- +\snd_staticvolume\- +\snd_channel0volume\- +\snd_channel3volume\- +\snd_channel6volume\- +\snd_channel7volume\- +\snd_channel4volume\- +\snd_channel2volume\- +\snd_channel1volume\- +\snd_speed\Frecuencia de salida del sonido +\snd_channels\Número de canales para la salida del sonido +\snd_swapstereo\Invertir canales izquierda o derecha +\snd_spatialization_control\Activar espacialización (mezcla ligeramente el canal derecho e izquierdo para disminuir la separación estereo un poco en los auriculares) +\cl_voice_directional\Activar voces direccionales +\cl_voice_directional_taunt_attenuation\Distancia desde el cual las burlas pueden escucharse +\cl_autotaunt\automáticamente burlarse del enemigo al anotar puntos +\cl_sound_maptime_warning\Sonido del anunciante que te indica el tiempo restante del combate +\cl_hitsound\Reproduce un sonido indicador de anotacion cuando disparas a un enemigo +\menu_sounds\Reproduce sonidos cuando se clickea o se posiciona sobre un item del menú + +\XonoticSettingsDialog/Red\configuración de la red +\cl_movement\Activar predicción de movimiento del lado del cliente +\cl_nolerp\Activar actualización suave en la red +\shownetgraph\Activar un gráfico de tamaño de paquetes y otra información +\_cl_rate\Especificar tu velocidad de conección con este separador +\cl_netfps\Cuantos paquetes de entrada mandar a un servidor por cada segundo +\cl_curl_maxdownloads\Número máximo de descargas concurrentes de HTTP/FTP +\cl_curl_maxspeed\Velocidad de descarga máxima +\cl_port\Forzar al cliente a usar un puerto elegido a menos que se establezca en 0 + +\XonoticSettingsDialog/Misc\configuración misc +\showtime\Mostrar la hora y el día actual, útil en capturas de pantalla +\showdate\Mostrar el día actual, útil en capturas de pantalla +\showfps\Mostrar tus marcos/frames por segundo +\cl_showspeed\Mostrar la velocidad del jugador +\cl_showspeed_unit\Seleccionar la velocidad del velocímetro. qu/s = in/s +\cl_showacceleration\Mostrar la aceleración del jugador +\cl_showacceleration_scale\Cambiar el acelerómetro por este multiplicador de escala + +\XonoticSettingsDialog/configuración avanzada...\configuracion avanzada donde puedes ajustar cada variable del juego +\g_friendlyfire\Porcentaje de daño infligido a tus compañeros de equipo +\g_mirrordamage\Porcentaje de daño de equipo que se reflejará a ti +\g_tdm_teams_override\Sobreescribir la cantidad de equipos por defecto de los modos en equipo + +\cl_teamradar_position\- +\cl_teamradar_size\- +\cl_teamradar_zoommode\- +\cl_teamradar_rotation\- +\cl_teamradar_scale\- +\cl_teamradar_foreground_alpha\- +\cl_teamradar_background_alpha\Valor de opacidad del radar de fondo +\viewsize\Enable/Desavilitar el HUD de fondo +\sbar_alpha_bg\alor de opacidad del HUD de fondo +\sbar_color_bg_r\Componente rojo del HUD de fondo +\sbar_color_bg_g\Componente verde del HUD de fondo +\sbar_color_bg_b\Componente azul del HUD de fondo +\sbar_color_bg_team\Saturacion del color de equipo del HUD de fondo +\cl_hidewaypoints\Mostrar indicadores de ubicación/caminos específicos de diferentes tipos de juego +\g_waypointsprite_scale\Escala del multiplicador de los indicadores de ubicación/caminos +\g_waypointsprite_alpha\Transparencia del control de los indicadores de ubicación/caminos +\cl_shownames\Mostrar el nombre del jugador al que estás apuntando + +\crosshair_hittest\Ninguno: no hacer pruebas de aciertos para el punto de mira; Apuntado: difuminar la punta de mira cuando no se apunta contra la pared; Enemigos: también ampliar el punto de mira cuando aciertas al enemigo diff --git a/tooltips.db.fr b/tooltips.db.fr new file mode 100644 index 0000000000..e365df9ba5 --- /dev/null +++ b/tooltips.db.fr @@ -0,0 +1,220 @@ +0 +\XonoticSingleplayerDialog\Jouer en mode un joueur contre des adversaires contrôlés par l'ordinateur + + +\XonoticMultiplayerDialog\Jouer en ligne avec des amis en réseau local ou sur Internet +\XonoticMultiplayerDialog/Serveurs\Trouver des serveurs pour y jouer dessus +\menu_slist_showempty\Montrer les serveurs vides +\menu_slist_showfull\Montrer les serveurs où toutes les places sont prises +\net_slist_pause\Ne met pas à jour la liste de serveurs pour éviter de "glisser" sur un autre serveur +\XonoticMultiplayerDialog/Info...\Montrer plus d'information sur le serveur séléctionné +\XonoticMultiplayerDialog/Marque-page\Mettre le serveur en haut de la liste pour pouvoir le repérer plus facilement plus tard +\XonoticMultiplayerDialog/Créer\Héberger votre propre partie +\XonoticMultiplayerDialog/Vidéos\Regarder des Vidéos pré-enregistrées +\XonoticMultiplayerDialog/Player Setup\Personaliser vos paramètres + +\XonoticTeamSelectDialog/join 'best' team (auto-select)\Auto-séléction de l'équipe qui a le plus besoin de vous (recommandé) +\XonoticTeamSelectDialog/rouge\Joindre l'équipe rouge +\XonoticTeamSelectDialog/bleu\Joindre l'équipe bleue +\XonoticTeamSelectDialog/jaune\Joindre l'équipe jaune +\XonoticTeamSelectDialog/rose\Joindre l'équipe rose + +\timelimit_override\Limite de temps au match, le match se finit quand elle est atteinte +\fraglimit_override\Limite de tués pour le match, le match se finit quand elle est atteinte +\menu_maxplayers\Le nombre maximum de personnes pouvant jouer sur votre serveur en même temps +\bot_number\Nombre d'adversaires ordinateur +\skill\Spécifier la difficulté des adversaires ordinateur +\g_maplist_votable\Le nombre de cartes pouvant être votées à la fin du match +\sv_vote_simple_majority_factor\À partir de 51% de oui seulement, un vote est gagné +\XonoticMultiplayerDialog/Advanced settings...\Paramètres du serveur avancés +\XonoticMultiplayerDialog/Mutators...\Spéciales et arènes d'une seule arme +\g_cloaked\Tous les joueurs sont presque invisibles +\g_footsteps\Activer les bruitages de pas +\g_midair\Il faut que votre adversaire soit en l'air pour lui faire mal +\g_vampire\Les dégâts faits à vos enemies vous font gagner de la santé +\g_bloodloss\Si vous avez moins de santé que spécifié ici, vous perdrez du sang et mourez progressivement +\sv_gravity\Vous tombez plus lentement, comme sur la lune +\g_grappling_hook\Tous les joueurs ont un grappin +\g_jetpack\Tous les joueurs ont un jetpack +\g_pinata\Tous les joueurs lâchent toutes leurs armes quand ils meurent +\g_weapon_stay\Les armes restent où elles sont quand elles sont prises sur la carte +\g_weaponarena\Séléctionner une arène d'une seule arme donne des munitions illimitées pour cette arme, et désactive toutes les autres armes +\menu_weaponarena_with_laser\Also enable the laser in the weapon arena +\g_minstagib\Tous les joueurs reçoivent un MinstaNex, qui est un sniper hyperpuissant qui tue d'un coup. Si vous n'avez plus de munitions, vous mourez progressivement. +\g_nix\No Items Xonotic; tous les joueurs ont la même arme en même temps, et on change d'arme régulièrement +\g_nix_with_laser\Porter le laser avec l'arme du No Items Xonotic +\XonoticMultiplayerDialog/Select all\Séléctionner toutes les cartes +\XonoticMultiplayerDialog/Select none\Déséléctionner toutes les cartes + + +\XonoticMultiplayerDialog/Test Performance\Faire un test de performance en utilisant la vidéo choisie + +\fov\Champ de vision en degrés, par défaut 90, certains joueurs préfèrent entre 110 et 130 +\cl_bobcycle\Effet de "tremblement" de la caméra en courant +\cl_zoomfactor\Facteur de Zoom +\cl_zoomsensitivity\Changer la sensitivité du Zoom: 0 est la plus basse, 1 ne comporte pas de changement par rapport au mode dézoomé +\cl_zoomspeed\Facteur "d'adoucissement" du Zoom, 0 désactive complètement +\XonoticMultiplayerDialog/Weapon settings...\Paramétrer les armes (affichage, priorité) + +\cl_weaponpriority_useforcycling\Utiliser la liste de priorité pour le changement d'armes à la molette +\cl_autoswitch\Automatiquement changer d'arme si vous avez une meilleure arme que celle que vous portez +\r_drawviewmodel\Afficher l'arme à la permière personne +\cl_gunalign\Position de l'arme à l'écran, reconnection au serveur nécessaire pour prendre effet + +\crosshair_per_weapon\Set a different crosshair for each weapon, good if you play without weapon models +\crosshair_color_override\Also set the color of the crosshair depending on the weapon you are currently holding +\crosshair_size\Ajuster la taille du viseur +\crosshair_color_alpha\Ajuster l'opacité du viseur +\crosshair_color_red\Couleur: intensité du rouge dans le viseur +\crosshair_color_green\Couleur: intensité du vert dans le viseur +\crosshair_color_blue\Couleur: intensité du bleu dans le viseur +\sbar_hudselector\Utiliser l'ancienne interface HUD +\XonoticMultiplayerDialog/Waypoints setup...\- +\_cl_name\Pseudonyme utilisé pour vous reconnaître dans le jeu + +\XonoticSettingsDialog\Changer les paramètres du jeu +\XonoticCreditsDialog\Les Crédits de Xonotic +\XonoticTeamSelectDialog\- +\XonoticMutatorsDialog\- +\XonoticMapInfoDialog\- +\XonoticUserbindEditDialog\- +\XonoticWinnerDialog\- +\XonoticWeaponsDialog\- +\XonoticRadarDialog\- +\XonoticServerInfoDialog\- +\XonoticCvarsDialog\- + +\XonoticQuitDialog\Quitter Xonotic +\XonoticQuitDialog/Oui\Retour au boulot... +\XonoticQuitDialog/Non\'Faut que je fragge plus de monde! + +\XonoticSettingsDialog/Contrôles\Paramètres contrôle souris/clavier +\sensitivity\Sensitivité de la souris +\menu_mouse_speed\Sensitivité de la souris dans les menus, n'affecte pas le jeu +\m_filter\Adoucit le mouvement de souris, mais crée une légère latence de souris +\m_pitch\Inverser la souris sur l'axe vertical (mode jeu d'avion) +\vid_dgamouse\Utiliser une souris DGA +\con_closeontoggleconsole\Autoriser la fermeture de console avec la touche d'ouverture de console (sinon, Shift+Échap) +\sbar_showbinds\Afficher les actions possibles avec des touches/commandes +\cl_showpressedkeys\Afficher les touches qu'un joueur est en train d'appuyer + +\XonoticSettingsDialog/Vidéo\Video settings +\vid_width\Résolution de l'écran +\vid_bitsperpixel\Profondeur des couleurs: 16 bits est plus rapide, mais 32 bits est de meilleure qualité (recommandé) +\vid_fullscreen\Activer le mode plein écran (par défaut: activé) +\vid_vsync\Activer la syncronisation verticale pour éviter des problèmes d'affichage, limite le nombre maximum d'images par seconde (par défaut: désactivé) +\r_glsl\Activer les Shaders OpenGL 2.0 pour des effets de lumière améliorés +\gl_vbo\Utiliser les VBOs pour stocker les modèles 3D statiques dans la mémoire pour une meilleure performance (par défaut: Points et Triangles) +\r_depthfirst\Éviter des problèmes de profondeur de rendu en faisant un rendu de profondeur de la carte/joueurs avant le rendu "standard" (par défaut: désactivé) +\gl_texturecompression\Compresser les textures pour économiser de la mémoire graphique (par défaut: aucun) +\gl_finish\Faire attendre le processeur que le rendu graphique se finisse pour éviter des problèmes d'affichage divers (par défaut: désactivé) +\v_brightness\Luminosité du noir (par défaut: 0) +\v_contrast\Luminosité du blanc (par défaut: 1) +\v_gamma\Correction du gamma ne changeant pas la luminosité du noir ou du blanc (par défaut: 1.125) +\v_contrastboost\Multiplier le constraste dans des salles sombres (par défaut: 1) +\r_glsl_saturation\Ajustement de la saturation (0 = noir et blanc, 1 = normal, 2 = saturé) des couleurs (par défaut: 1) +\v_glslgamma\Utiliser GLSL pour corriger le gamma, attention, cela risque d'augementer fortement l'utilisation de ressources (par défaut: désactivé) +\r_ambient\Lumière ambiente, si elle est trop élévée, les cartes auront un éclairage plus "plat" et moins contrasté +\r_hdr_scenebrightness\Éclairage du rendu global (par défaut: 1) +\vid_samples\Activer l'anticrénelage, réduit l'effet d'escalier sur les modèles 3D, mais augmente fortement l'utilisation des ressources +\v_flipped\Mode mirroir (par défaut: désactivé) + +\XonoticSettingsDialog/Graphiques\Paramètres des effets graphiques +\r_subdivisions_tolerance\Ajuster la qualité des modèles 3D de carte (courbes, tuyaux) (par défaut: normal) +\gl_picmip\Ajuster la qualité des textures. La baisser diminue l'utilisation des ressources, mais rend les textures floues. (par défaut: normal) +\r_picmipworld\If set, only reduce the texture quality of models (default: enabled) +\mod_q3bsp_nolightmaps\Utiliser des lightmaps haute résolution, augmente l'utilisation des resources, mais rend les lightmaps plus nettes (par défaut: activé) +\cl_particles_quality\Nombre de particules; moins de particules consomment moins de ressources (par défaut: 0.5) +\r_drawparticles_drawdistance\Toutes les particules qui sont plus loin que cette distance ne seront pas affichées (par défaut: 1000) +\cl_decals\Activer les marques d'impacts et de sang (par défaut: activé) +\r_drawdecals_drawdistance\Toutes les marques d'impacts qui sont plus loin que cette distance ne seront pas affichées (par défaut: 300) +\cl_decals_time\Temps en secondes avant que les marques d'impacts disparaissent (par défaut: 2 secondes) +\cl_gentle\Remplacer les effets gore par des effets moins violents (par défaut: désactivé) +\cl_nogibs\Réduire le nombre de Gibs ou les désactiver totalement (par défaut: beaucoup) +\v_kicktime\Faire trembler la vue en recevant des dégâts (par défaut: 0) +\gl_texture_anisotropy\Qualité du filtrage anistrope (par défaut: 1x) +\r_glsl_deluxemapping\Utiliser les effets lumineux avancés (par défaut: activé) +\r_shadow_gloss\Utiliser le reflet des textures (par défaut: activé) +\gl_flashblend\Enable faster but uglier dynamic lights by rendering bright coronas instead of real dynamic lights (default: disabled) +\r_shadow_realtime_dlight\Activer le rendu des lumières dynamiques en temps réel (par défaut: activé) +\r_shadow_realtime_dlight_shadows\Activer le rendu des ombres depuis les lumières dynamiques en temps réel (par défaut: désactivé) +\r_shadow_realtime_world\Activer le rendu des lumières carte en temps réel, a un gros impact sur la performance (par défaut: désactivé) +\r_shadow_realtime_world_shadows\Activer le rendu des ombres depuis les lumières carte en temps réel, a un impact sur la performance aussi (par défaut: désactivé) +\r_shadow_usenormalmap\Utiliser des effets d'ombrage de lumière sur les textures (par défaut: activé) +\r_showsurfaces\Désactiver les textures et les remplacer par des couleurs unies. Utile pour les configurations très faible, mais laid. (par défaut: désactivé) +\r_glsl_offsetmapping\Activer l'effet de relief sur les textures, a un léger impact sur la performance (par défaut: désactivé) +\r_glsl_offsetmapping_reliefmapping\Augmenter la qualité des effets de relief sur les textures, a un gros impact sur la performance (par défaut: désactivé) +\r_water\Activer des reflets de réflecion et de réfraction d'eau et des portails Warpzone (par défaut: désactivé) +\r_water_resolutionmultiplier\Qualité des reflets d'eau et des portails Warpzone, l'augmenter a un gros impact sur la performance (par défaut: bon) +\r_coronas\Activer des effets d'éblouissement peu gourmands (par défaut: activé) +\r_coronas_occlusionquery\Prendre en compte la visibilité pour les effets "Brillance Lumière" (par défaut: activé) +\r_bloom\Activer un effet d'éblouissement plus beau, mais gourmand (par défaut: désactivé) +\r_hdr\Activer un effet d'ébloissement encore plus beau, mais encore plus gourmand (par défaut: désactivé) +\r_motionblur\Intensité du flou de mouvement - 0.5 est recommandé +\r_damageblur\Intensité du flou en recevant des dégâts - 0.4 est recommandé + +\XonoticSettingsDialog/Audio\Audio settings +\mastervolume\- +\bgmvolume\- +\snd_staticvolume\- +\snd_channel0volume\- +\snd_channel3volume\- +\snd_channel6volume\- +\snd_channel7volume\- +\snd_channel4volume\- +\snd_channel2volume\- +\snd_channel1volume\- +\snd_speed\Fréquence de la sortie audio +\snd_channels\Nombre de canaux pour la sortie audio +\snd_swapstereo\Échanger les canneaux stéréo gauche/droite +\snd_spatialization_control\Essayer de diminuer le "constraste" entre la partie gauche et droite du casque audio pour un meilleur son +\cl_voice_directional\Activer les voix des personnages sur la carte +\cl_voice_directional_taunt_attenuation\Distance à laquelle les voix sont audibles +\cl_autotaunt\Automatiquement narguer les enemis quand vous les tuez +\cl_sound_maptime_warning\Voix (en anglais) qui vous dit le temps restant avant la fin du match +\cl_hitsound\Jouer un son quand vous touchez un enemi +\menu_sounds\Jouer des sons en cliquant ou en passant la souris sur des options + +\XonoticSettingsDialog/Réseau\Paramètres du jeu en réseau +\cl_movement\Activer la prédiction des mouvements du joueur pour éviter les saccades lors de parties en réseau +\cl_nolerp\Algorithme pour éviter les saccades lors de parties en réseau +\shownetgraph\Show a +\_cl_rate\Specify your network speed with this slider +\cl_netfps\Nombre maximum de paquets à envoyer au server chaque seconde +\cl_curl_maxdownloads\Nombre maximum de téléchargements simultanés +\cl_curl_maxspeed\Vitesse maximum de téléchargement +\cl_port\Forcer le client à passer par le port défini (UDP) s'il n'est pas 0 + +\XonoticSettingsDialog/Autres\Autres paramètres +\showtime\Montrer l'heure, utile pour les captures d'écran +\showdate\Montrer la date, utile pour les captures d'écran +\showfps\Montrer le nombre d'Images Par Seconde rendues (Frames Per Second = FPS) +\cl_showspeed\Montrer la vitesse du joueur +\cl_showspeed_unit\Séléctionner l'unité de mesure de la vitesse (qu/s = in/s) +\cl_showacceleration\Montrer l'accélération du joueur +\cl_showacceleration_scale\Éxagérer l'accéléromètre avec ce facteur pour qu'il soit plus visible + +\XonoticSettingsDialog/Advanced settings...\Paramètres avancés pour configuer le jeu dans ses moindres détails +\g_friendlyfire\Pourcentage de dégâts infligés aux équipiers si vous les touchez +\g_mirrordamage\Pourcentage de dégâts infligés aux équipiers qui vous sera renvoyé +\g_tdm_teams_override\Écraser le nombre d'équipes défini par la carte + +\cl_teamradar_position\- +\cl_teamradar_size\- +\cl_teamradar_zoommode\- +\cl_teamradar_rotation\- +\cl_teamradar_scale\- +\cl_teamradar_foreground_alpha\- +\cl_teamradar_background_alpha\Opacité de l'arrière-plan du radar +\viewsize\Enable/Désactiver l'arrière plan de l'interface +\sbar_alpha_bg\Opacité de l'arrière plan de l'interface +\sbar_color_bg_r\Intensité du rouge dans l'arrière-plan de l'interface +\sbar_color_bg_g\Intensité du vert dans l'arrière-plan de l'interface +\sbar_color_bg_b\Intensité du bleu dans l'arrière-plan de l'interface +\sbar_color_bg_team\Saturation de la couleur d'équipe avec l'arrière-plan de l'interface +\cl_hidewaypoints\Montrer/Cacher les Waypoints (flèches 3D) +\g_waypointsprite_scale\Ajuster la taille des Waypoints +\g_waypointsprite_alpha\Ajuster l'opacité des Waypoints +\cl_shownames\Afficher le nom du joueur que vous pointez avec votre viseur + +\crosshair_hittest\Aucun: aucun effet de viseur - TrueAim: rendre le viseur flou si vous risquez de vous blesser vous même ou un équipier - Enemis: rendre le viseur plus grand si vous pouvez toucher un enemi diff --git a/tooltips.db.hu b/tooltips.db.hu new file mode 100644 index 0000000000..dffb1853cb --- /dev/null +++ b/tooltips.db.hu @@ -0,0 +1,203 @@ +0 +\XonoticSingleplayerDialog\Egyjátékos mód vagy azonnali játék gépi vezérlésű botok ellen + + +\XonoticMultiplayerDialog\Meccsek neten, a barátaid elleni helyi hálózaton, demó nézés, vagy a karaktered beállításainak finomítása +\XonoticMultiplayerDialog/Szerverek keresése a játékhoz +\menu_slist_showempty\Üres szerverek mutatása +\menu_slist_showfull\Teli szerverek is mutatása, amelyeken nincs már szabad férőhely +\net_slist_pause\Megállítja a szerver lista frissítését, hogy a szerverek ne 'ugráljanak össze-vissza' a listában +\XonoticMultiplayerDialog/Adatok...\Több adat az éppen kiválasztott szerverről +\XonoticMultiplayerDialog/Könyvjelzők\Az éppen kiválasztott szerver megjelölése, hogy a jövőben könnyebben megtalálható legyen +\XonoticMultiplayerDialog/Létrehozás\Saját játékszerver indítása +\XonoticMultiplayerDialog/Demók\Demók böngészése és megtekintése +\XonoticMultiplayerDialog/Játékos beállítások\Játékoskarakter testreszabása + +\XonoticTeamSelectDialog/A 'legjobb' csapathoz csatlakozás (auto-választás)\Önműködő csapatválasztás (ajánlott) +\XonoticTeamSelectDialog/piros\Csatlakozás a vörös csapathoz +\XonoticTeamSelectDialog/kék\Csatlakozás a kék csapathoz +\XonoticTeamSelectDialog/sárga\Csatlakozás a sárga csapathoz +\XonoticTeamSelectDialog/rózsaszín\Csatlakozás a rózsaszín csapathoz + +\timelimit_override\Időhatár percben, aminek elérése után vége a meccsnek +\fraglimit_override\Gyilokok száma, amit a meccs vége előtt el kell érni +\menu_maxplayers\A játékosok és botok maximális összszáma, ahányan egyszerre a szerverre csatlakozhatnak +\bot_number\Botok száma a szervereden +\skill\A botok ügyességi szintjének meghatározása +\g_maplist_votable\Pályaválasztásnál megjelenő lehetőségek száma egy meccs után +\sv_vote_simple_majority_factor\Egyszerű többség nyerjen egy szavazásban +\XonoticMultiplayerDialog/Haladó beállítások...\Haladó szerverbeállítások +\XonoticMultiplayerDialog/Módosítók...\Módosítók és fegyverarénák +\g_dodging\El tudsz szökkenni jobbra-balra a lövések elől +\g_cloaked\Minden játékos majdnem láthatatlan +\g_footsteps\Lépészaj engedélyezése +\g_midair\Csak addig tudod az ellenséged megsebezni, amíg az levegőben tartózkodik +\g_vampire\Annyi pont adódik életerődhöz, amennyi sebzést a másiknak okozol +\g_bloodloss\Életerőpont, ami alatt a játékos elkábul a vérveszteségtől +\sv_gravity\A tárgyak lassabban esnek a földre, kisebb érték alacsonyabb gravitációt jelent +\g_grappling_hook\A játékosok arzenáljában a vonóhorog is szerepelni fog +\g_jetpack\A játékosok hátán sugárhajtóműves hátizsák van +\g_pinata\A játékosok eldobnak minden fegyvert, amit birtokoltak a haláluk előtt +\g_weapon_stay\A fegyverek a helyükön maradnak, még azután is, hogy valaki felvette őket +\g_weaponarena\ A kiválasztott fegyver aréna minden játékosnak ugyanazt a fegyvert biztosítja korlátlan lőszerrel, és letiltja minden más fegyver felvételét +\menu_weaponarena_with_laser\A lézer is engedélyezett a fegyver arénában +\g_minstagib\A játékosok egy Minstanex-et kapnak, ami egy azonnal ölő mesterlövész fegyver. Ha a játékos kifogy a lőszerből, 10 másodperce van muníciót találni, vagy meghal. A másodlagos tűz mód a lézer, amely nem okoz kárt, de jól jön trükkös ugrások végrehajtásánál +\g_nix\Xonotic felvehető fegyverek nélkül – Mindenki ugyanazzal a fegyverrel játszik. Kis idő után visszaszámlálás indul, amely végén mindenki fegyvert vált +\g_nix_with_laser\Mindig legyen a lézer a Nix mellett kiegészítésül +\XonoticMultiplayerDialog/Mind jelölve\Minden pálya kiválasztása +\XonoticMultiplayerDialog/Egyet se jelölj be\Egyik pálya sincs kiválasztva + + +\XonoticMultiplayerDialog/Timedemo\Leméri, hogy a számítógéped milyen gyorsan képes futtatni a kiválasztott demót. + +\fov\A látószög fokban mérve 60-tól 130-ig, alapérték 90 +\cl_bobcycle\A megjelenített kép biccentése járás közben. +\cl_zoomfactor\A nagyítási szorzó a ráközelítés gomb megnyomása esetén +\cl_zoomsensitivity\Mennyire változtatja a nagyítás az egér érzékenységet, 0-tól (kisebb érzékenység) 1-ig (nem változik az érzékenység) +\cl_zoomspeed\Milyen gyorsan hajtsa végre a távcső a nagyítást. Tiltás esetén a nagyítás azonnal végbemegy +\XonoticMultiplayerDialog/Fegyver beállítások...\A legkedveltebb fegyver, önműködő fegyverváltás és fegyvermodell pozíciójának beállításai + +\cl_weaponpriority_useforcycling\A fenti lista használata, amikor az egérgörgővel lépkedsz a fegyverek között +\cl_autoswitch\Önmagától átvált az újonnan felvett fegyverekre, ha azok jobbak az addig használtnál +\r_drawviewmodel\Fegyvermodell kirajzolása +\cl_gunalign\Fegyvermodell helyzete; játék közben újracsatlakozás szükséges az adott szerverhez + +\crosshair_per_weapon\Különböző célkeresztek beállítása az éppen kézben tartott fegyverhez; hasznos lehet fegyvermodell nélküli játék során +\crosshair_color_per_weapon\A célkereszt színének változtatása az éppen kézben tartott fegyvertől függően +\crosshair_size\ A célkereszt méretének megváltoztatása +\crosshair_alpha\A célkereszt átlátszóságának megváltoztatása +\crosshair_color\A célkereszt színének megváltoztatása +\sbar_hudselector\A régi HUD elrendezés használata +\XonoticMultiplayerDialog/Irányjelzők beállításai...\- +\_cl_name\A név, amivel szerepelsz a játékban + +\XonoticSettingsDialog\A beállítások megváltoztatása +\XonoticCreditsDialog\A Xonotic készítőinek és segítségnyújtóinak listája +\XonoticTeamSelectDialog\- +\XonoticMutatorsDialog\- +\XonoticMapInfoDialog\- +\XonoticUserbindEditDialog\- +\XonoticWinnerDialog\- +\XonoticWeaponsDialog\- +\XonoticRadarDialog\- +\XonoticServerInfoDialog\- +\XonoticCvarsDialog\- + +\XonoticQuitDialog\Kilépés a játékból +\XonoticQuitDialog/Igen\Vissza a munkához... +\XonoticQuitDialog/Nem\A mészárlás folytatódik! + +\XonoticSettingsDialog/Bemenet\Bemenet szabályozása +\sensitivity\Egér sebesség többszörözése +\menu_mouse_speed\Egér sebessége a menüben, nincs hatással a játékbeli célzásra +\m_filter\Elsimítja az egérmozgást, de a célzás érzékenység némiképp csökken +\m_pitch\Fordított egérmozgás az Y-tengely mentén +\vid_dgamouse\Segíti a DGA egér bemenet használatát +\con_closeontoggleconsole\Lehetővé teszi, hogy a konzolnyitó billentyű, a következő megnyomásra visszazárja azt + +\XonoticSettingsDialog/Kép\Kép beállítások +\vid_width\Képernyő felbontás +\vid_bitsperpixel\Hány bit per pixel(BPP)-el jelenítse meg a képet, 32 az ajánlott +\vid_fullscreen\Teljes képernyős mód engedélyezése (alapértelmezett: engedélyezve) +\vid_vsync\A függőleges szinkronizáció engedélyezése, hogy megelőzze a kép szétesését, a másodpercenkénti képkockák számát a képernyő frissítési rátához igazítja (alapértelmezett: letiltva) +\r_glsl\Az OpenGL 2.0 pixel árnyalók alkalmazása a világításhoz (alapértelmezett: engedélyezve) +\gl_vbo\A statikus geometriákhoz Vertex Buffer Object-eket használ a videómemóriában a gyorsabb számítás érdekében (alapértelmezett: Csúcspontok és háromszögek) +\r_depthfirst\Eltávolítja a kép csak a távolban tartozó részeit, mielőtt a normál számítás kezdődne (alapértelmezett: letiltva) +\gl_texturecompression\Textúrák tömörítése, hogy a videokártyán található memóriából kevesebbet használjon (alapértelmezett: nem) +\gl_finish\A CPU megvárja amíg a GPU befejezi a képkockát leképzését, ez segít egyes gépeken jelentkező furcsa bemeneti és videó késés elkerülésében (alapértelmezett: letiltva) +\v_brightness\A fekete fényessége (alapérték: 0) +\v_contrast\A fehér fényessége (alapérték: 1) +\v_gamma\Fordított gamma korrekciós érték, egy fényességi hatás , ami nem befolyásolja a fehéret vagy feketét (alapérték: 1.125) +\v_contrastboost\Milyen mértékben erősítse a sötét területek kontrasztját (alapérték: 1) +\r_glsl_saturation\Színtelítettség beállítása (0 = szürke, 1 = normál, 2 = túltelített ), GLSL színkezelés szükséges (alapérték: 1) +\v_glslgamma\A GLSL alkalmazása a gamma korrekcióhoz, Megjegyzendő, hogy jelentősen csökkenheti a teljesítményt (alapértelmezett: letiltva) +\r_ambient\Környezeti világítás, ha túl magasra van állítva a térkép fakónak és laposnak tűnhet (alapérték: 4) +\r_hdr_scenebrightness\Általános számítási világosság (alapérték: 1) +\vid_samples\Élsimítás engedélyezés, 3D-s tárgyak szélének csipkézettségét csökkenti. Megjegyzendő, hogy jelentősen csökkenheti a teljesítményt (alapértelmezett: letiltva) +\v_flipped\Szegény ember bal kezes módja (alapértelmezett: ki) + +**** +\XonoticSettingsDialog/Hatások\Hatások beállítása +\r_subdivisions_tolerance\Az ívek finomságának változtatása a pályán (alapértelmezett: normál) +\gl_picmip\ A textúrák élességének változtatása. Kisebb érték hatásosan csökkenti a textúra memória használatot, de a textúrák megjelenése homályosabb lehet. (alapértelmezett: jó) +\r_picmipworld\Ha ha be van állítva, csak a modellek textúra minősége csökken (alapértelmezett: engedélyezve) +\mod_q3bsp_nolightmaps\Magas felbontású fény térképek használata, ami szépen néz ki, de megemeli a szükséges videó memória mennyiségét (alapértelmezett: engedélyezve) +\cl_particles_quality\A részecskék számának megtöbbszörözése. Kisebb érték kevesebb részecskét jelent, ami jobb teljesítményt ad (alapérték: 0,5) +\r_drawparticles_drawdistance\A részecskék csak eddig a távolsági rajzolódnak ki (alapérték: 1000) +\cl_decals\Foltok engedélyzése (égési és robbanási nyomok, vérfoltok) (alapértelmezett: engedélyezve) +\r_drawdecals_drawdistance\A minták csak eddig a távolsági rajzolódnak ki (alapérték: 300) +\cl_decals_time\A foltok eltűnésének kezdetének időtartama másodpercben (alapérték: 2) +\cl_gentle\Kicseréli a vért és húscafatokat olyan tartalomra, ami nem tartalmaz vérontást (alapértelmezett: letiltva) +\cl_nogibs\A húscafatok mennyiségének csökkentése vagy teljesen eltávolítása (alapértelmezett: sok) +\v_kicktime\Mennyi ideig legyen a kép kiütve a sérülés után (alapérték: 0) +\gl_texture_anisotropy\Anizotropikus szűrés minősége (alapérték: 1x) +\r_glsl_deluxemapping\Képpontokkénti világítás hatások használata (alapértelmezett: engedélyezve) +\r_shadow_gloss\Csillogás a textúrákon, amik támogatják azt (alapértelmezett: engedélyezve) +\gl_flashblend\A gyorsabb, de csúnyább dinamikus fények engedélyezése a világos fénykörök számításához, a valós dinamikus világítás helyett (alapértelmezett: letiltva) +\r_shadow_realtime_dlight\A dinamikus világítások engedélyezése, mint robbanások és rakéták fényei (alapértelmezett: engedélyezve) +\r_shadow_realtime_dlight_shadows\Árnyékok számítása a dinamikus fényekből (alapértelmezett: letiltva) +\r_shadow_realtime_world\A teljes valósidejű világ világítások engedélyezése azokon a térképeken, amik támogatják Megjegyzendő, hogy jelentősen csökkenheti a teljesítményt (alapértelmezett: letiltva) +\r_shadow_realtime_world_shadows\A valósidejű világ fényekhez tartozó árnyékok engedélyezése (alapértelmezett: letiltva) +\r_shadow_usenormalmap\Irányított árnyékok használatának engedélye a textúrákon (alapértelmezett: engedélyezve) +\r_showsurfaces\Textúra összetettség letiltása nagyon lassú gépeken. Ez egy nagy gyorsulást hozz a teljesítményben, de nagyon csúnyán néz ki. (alapértelmezett: letiltva) +\r_glsl_offsetmapping\Offset mapping hatás , ami rücskössé teszi a textúrák megjelenését, mintha kiállna a 2D-s felületből (alapértelmezett: letiltva) +\r_glsl_offsetmapping_reliefmapping\Magasabb minőségű offset mapping, ami szintén óriási hatása van a teljesítményre (alapértelmezett: letiltva) +\r_water\Tükröződések és fénytörések minősége, óriási hatással van a teljesítményre azokon a pályákon, ahol vannak tükröződő felületek (alapértelmezett: letiltva) +\r_water_resolutionmultiplier\Tükröződések/fénytörések felbontása (alapértelmezett: jó) +\r_coronas\A fényudvar engedélyezése bizonyos világítás körül. (alapértelmezett: engedélyezve) +\r_coronas_occlusionquery\A fényudvar elhalványodik a láthatósága szerint (alapértelmezett: engedélyezve) +\r_bloom\A bloom hatás engedélyezése, aminél a nagyon világos pixelek növelik a szomszédaik világosságát is. Nagy hatással van a teljesítményre. (alapértelmezett: letiltva) +\r_hdr\A bloom magas minőségű verziója, ami óriási hatással van a teljesítményre. (alapértelmezett: letiltva) +\r_motionblur\Mozgási elmosódás nagysága - ajánlott értéke 0.5 +\r_damageblur\Mozgási elmosódás mértéke sérülés esetén – ajánlott értéke 0.4 + +**** +\XonoticSettingsDialog/Hang\Hang beállítás +\mastervolume\- +\bgmvolume\- +\snd_staticvolume\- +\snd_channel0volume\- +\snd_channel3volume\- +\snd_channel6volume\- +\snd_channel7volume\- +\snd_channel4volume\- +\snd_channel2volume\- +\snd_channel1volume\- +\snd_speed\Hang kimenet frekvenciája +\snd_channels\A hang kimenet csatornáinak száma +\snd_swapstereo\Jobb/bal csatorna felcserélése +\snd_spatialization_control\Közelítés engedélyezése (kissé összemossa a jobb és bal csatornát, hogy csökkentse a sztereó szétválasztást a fejhallgatókban) +\cl_voice_directional\Irányított hangok engedélyezése +\cl_voice_directional_taunt_attenuation\A távolság, ahonnan a gúnyolódás még hallható +\cl_autotaunt\Az ellenség mindig gúnyolódik, ha legyüröd +\cl_sound_maptime_warning\Kihirdető hang, ami a meccsből hátralévő percekről tájékoztat +\cl_hitsound\Egy találatjelző hang, ha sikeres lövés vittél be az ellenségre +\menu_sounds\Hang lejátszás, ha klikkelsz vagy a menüpontok fölött siklasz + +\XonoticSettingsDialog/Hálózat\Hálózat beállítások +\cl_movement\Kliensoldali mozgás jóslás engedélyezés +\cl_nolerp\Engedélyezi a hálózat frissítés simítását +\shownetgraph\Csomagméret és egyéb információk grafikonjának kirajzolása +\_cl_rate\A hálózat sebessége határozható meg ezzel a csúszkával +\cl_netfps\A szervernek küldött bemeneti csomagot másodpercenkénti száma +\cl_curl_maxdownloads\Az egyszerre futó HTTP/FTP letöltések maximális száma +\cl_curl_maxspeed\Maximum letöltési sebesség +\cl_port\Kényszeríti a klienst, hogy a választott portot használja, amíg nem 0 az érték + +\XonoticSettingsDialog/Egyéb\Egyéb beállítások +\showtime\Az aktuális időt mutatja, kép mentésekor hasznos +\showdate\Az aktuális dátumot mutatja, kép mentésekor hasznos +\showfps\A másodpercenként megjelenített képkockák száma + +\XonoticSettingsDialog/Haladó beállítások...\Haladó beállítások, ahol finomíthatod a játék minden egyes változóját +\g_friendlyfire\Sérülés százaléka, amit a csapattársadnak okozol +\g_mirrordamage\Általad okozott csapatsérülés százaléka, amit te szenvedsz el +\g_tdm_teams_override\Csapatjátékban felülbírálja a csapatok számának alapbeállítását + +\viewsize\HUD háttér engedélyezés/letiltás +\cl_hidewaypoints\Különböző játéktípus specifikus iránypontok mutatása +\g_waypointsprite_scale\Az iránypontok szorzódásának mértéke +\g_waypointsprite_alpha\Az iránypontok átlátszóságának ellenőrzése +\cl_shownames\Az éppen célba vett játékos nevének mutatása + +\crosshair_hittest\Nincs: a találat nincs hatással a célkeresztre; Valós célzás: elmossa a célkeresztet, mikor nem a falat találod el; Ellenségek: Fel is nagyítja a célkeresztet, mikor egy ellenfelet találsz el diff --git a/tooltips.db.it b/tooltips.db.it new file mode 100644 index 0000000000..e8ec95a985 --- /dev/null +++ b/tooltips.db.it @@ -0,0 +1,201 @@ +0 +\XonoticSingleplayerDialog\Gioca la campagna in giocatore singolo o una partita istantanea contro dei bot + + +\XonoticMultiplayerDialog\Gioca online, contro i tuoi amici in LAN, guarda demo o cambia le impostazioni del giocatore +\XonoticMultiplayerDialog/Server\Cerca dei server dove giocare +\menu_slist_showempty\Mostra server vuoti +\menu_slist_showfull\Mostra server pieni che non hanno slot disponibili +\net_slist_pause\Ferma l'aggiornamento della lista server per prevenire il continuo spostamento di posizione dei server +\XonoticMultiplayerDialog/Info...\Mostra maggiori informazioni riguardo il server attualmente selezionato +\XonoticMultiplayerDialog/Aggiungi tra i preferiti\Aggiungi nel segnalibri il server attualmente selezionato in modo che sia più veloce da trovare in futuro +\XonoticMultiplayerDialog/Crea\Ospita la tua partita +\XonoticMultiplayerDialog/Demo\Naviga e vedi le demo +\XonoticMultiplayerDialog/Setup giocatore\Personalizza le tue impostazioni del giocatore + +\XonoticTeamSelectDialog/entra nel 'miglior' team (auto-selezione)\Autoseleziona team (raccomandato) +\XonoticTeamSelectDialog/rosso\Entra nel team rosso +\XonoticTeamSelectDialog/blu\Entra nel team blu +\XonoticTeamSelectDialog/giallo\Entra nel team giallo +\XonoticTeamSelectDialog/rosa\Entra nel team rosa + +\timelimit_override\Tempo limite in minuti che appena raggiunto terminerà la partita +\fraglimit_override\Il numero di frag necessari prima che la partita finisca +\menu_maxplayers\Il massimo numero di giocatori o bot che possono essere connessi al tuo server alla volta +\bot_number\Numero di bot nel tuo server +\skill\Specifica quanto i bot saranno esperti +\g_maplist_votable\Numero di mappe che sono mostrate nel voto delle mappe alla fine di una partita +\sv_vote_simple_majority_factor\La semplice maggioranza vince il voto +\XonoticMultiplayerDialog/Impostazioni avanzate...\Impostazioni avanzate del server +\XonoticMultiplayerDialog/Mutatori...\Mutatori e arene dedicate ad armi +\g_dodging\Abilita schivamento +\g_cloaked\Tutti i giocatori sono quasi invisibili +\g_footsteps\Abilita suoni dei passi +\g_midair\È possibile infliggere danni al tuo nemico solo quando è per aria +\g_vampire\Il danno causato al tuo nemico aumenta la tua vita +\g_bloodloss\L'ammontare di vita sotto la quale il tuo giocatore viene stordito per la perdita di sangue +\sv_gravity\Rendi la caduta degli oggetti più lenta, valori inferiori significano minor gravità +\g_grappling_hook\I giocatori nascono con il grappling hook +\g_jetpack\I giocatori nascono col jetpack +\g_pinata\I giocatori rilasceranno tutte le armi che possedevano appena vengono uccisi +\g_weapon_stay\Le armi rimangono dopo che vengono raccolte +\g_weaponarena\Selezionando un'arena dedicata ad un'arma si darà a tutti i giocatori quell'arma con munizioni infinite, e disabiliterà tutti gli altri raccoglimenti delle armi. +\menu_weaponarena_with_laser\Abilita anche il laser nelle arene dedicate ad un'arma +\g_minstagib\Ai giocatori sarà dato il Minstanex, che è un railgun con danni illimitati. Se il giocatore rimane senza munizioni, avrà 10 secondi per trovarne alcune, altrimenti morirà. Il fuoco secondario è un laser che non infligge nessun danno ed è buono per effettuare vari trickjump. +\g_nix\"No items Xonotic" - invece di raccogliere oggetti, ognuno giocherà con la stessa arma. Dopo un pò di tempo, un conto alla rovescia inizierà, dopo il quale ognuno passerà ad un'altra arma. +\g_nix_with_laser\Porta sempre il laser come arma aggiuntiva nella modalità "No items Xonotic" +\XonoticMultiplayerDialog/Seleziona tutto\Seleziona tutte le mappe +\XonoticMultiplayerDialog/Deseleziona tutto\Deseleziona tutte le mappe + + +\XonoticMultiplayerDialog/Timedemo\Testa quanto velocemente il tuo computer fa girare il demo selezionato + +\fov\Il campo di vista da 60 a 130 gradi, di default è a 90 gradi +\cl_bobcycle\Frequenza dell'ondeggiamento della visuale, disabilita per nessun ondeggiamento +\cl_zoomfactor\Quanto grande è il fattore zoom quando il tasto per lo zoom viene premuto +\cl_zoomsensitivity\Come lo zoom fa variare la sensibilità del mouse, da 0 (sensibilità più bassa) a 1 (nessun cambio di sensibilità) +\cl_zoomspeed\Quando velocemente la vista viene zoomata, disabilitalo per lo zoom istantaneo +\XonoticMultiplayerDialog/Impostazioni arma...\Imposta le tue armi preferite, i cambi automatici e le impostazioni dei modelli delle armi + +\cl_weaponpriority_useforcycling\Usa la lista qui sotto per definire le armi usando la rotellina del mouse +\cl_autoswitch\Automaticamente passa all'arma appena raccolta se è migliore di quella che stavi già usando +\r_drawviewmodel\Mostra il modello dell'arma +\cl_gunalign\Posizione del modello dell'arma; richiede riconnessione + +\crosshair_per_weapon\Imposta un differente mirino per ogni arma, buono se giochi senza i modelli delle armi +\crosshair_color_per_weapon\Imposta il colore del mirino dipendente dall'arma che stai correntemente usando +\crosshair_size\Imposta la dimensione del mirino +\crosshair_alpha\Imposta l'opacità del mirino +\crosshair_color\Imposta il colore del mirino +\sbar_hudselector\Usa il tema del vecchio HUD +\XonoticMultiplayerDialog/Waypoints setup...\- +\_cl_name\Nome col quale apparirai nel gioco + +\XonoticSettingsDialog\Cambia le impostazioni del gioco +\XonoticCreditsDialog\I crediti di Xonotic +\XonoticTeamSelectDialog\- +\XonoticMutatorsDialog\- +\XonoticMapInfoDialog\- +\XonoticUserbindEditDialog\- +\XonoticWinnerDialog\- +\XonoticWeaponsDialog\- +\XonoticRadarDialog\- +\XonoticServerInfoDialog\- +\XonoticCvarsDialog\- + +\XonoticQuitDialog\Esci dal gioco +\XonoticQuitDialog/Sì\Devo tornare a lavorare... +\XonoticQuitDialog/No\Ho ancora un pò di frag da fare! + +\XonoticSettingsDialog/Comandi\Impostazioni input +\sensitivity\Moltiplicatore velocità del mouse +\menu_mouse_speed\Velocità mouse nel menu, non riguarda il puntamento nel gioco +\m_filter\Rendi più morbido il movimento del mouse, però rende la sua risposta leggermente più lenta +\m_pitch\Inverti il movimento del mouse nell'asse Y +\vid_dgamouse\Fai uso dell'input DGA del mouse +\con_closeontoggleconsole\Rendi il tasto di chiusura console uguale a quella di apertura + +\XonoticSettingsDialog/Video\Impostazioni video +\vid_width\Risoluzione schermo +\vid_bitsperpixel\Bit per pixel (BPP) per il rendering, 32 è raccomandato +\vid_fullscreen\Abilita modalità a tutto schermo (predefinito: abilitato) +\vid_vsync\Abilita la sincronizzazione verticale per prevenire la lacrimazione (tearing), imposta il limite massimo di fps alla velocità di aggiornamento dello schermo (predefinito: disabilitato) +\r_glsl\Abilita i pixel shader OpenGL 2.0 per l'illuminazione (predefinito: abilitato) +\gl_vbo\Fai uso dei Vertex Buffer Objects per salvare nella memoria grafica la geometria statica per un rendering più veloce (predefinito: Vertici e Triangoli) +\r_depthfirst\Elimina eccesso di disegno (overdraw) eseguendo il rendering della sola profondità della scena prima di iniziare il rendering "standard" (predefinito: disabilitato) +\gl_texturecompression\Comprimi le texture per le schede video con poca memoria grafica disponibile (predefinito: Nessuna) +\gl_finish\Fa in modo che la CPU attenda che la GPU finisca di elaborare ogni frame, può aiutare con alcuni strani input o in presenza di video lag in alcune macchine (predefinito: disabilitato) +\v_brightness\Luminosità del nero (predefinito: 0) +\v_contrast\Luminosità del bianco (predefinito: 1) +\v_gamma\Valore della correzione gamma inversa, un effetto di luminosità che non tocca il bianco o il nero (predefinito: 1.125) +\v_contrastboost\Di quanto viene moltiplicato il contrasto nelle aree oscure (predefinito: 1) +\r_glsl_saturation\Adattamento saturazione (0 = scala di grigi, 1 = normale, 2 = sovra-saturo), richiede il GLSL color control (predefinito: 1) +\v_glslgamma\Abilita l'uso delle GLSL per applicare la correzione gamma, nota che le performance potrebbero decrementare di tanto (predefinito: disabilitato) +\r_ambient\Luminosità dell'ambiente, se è impostato ad un valore troppo alto tende a rendere la luce delle mappe opaca e piatta (predefinito: 4) +\r_hdr_scenebrightness\Luminosità del rendering globale (predefinito: 1) +\vid_samples\Abilita l'antialiasing, che smussa i bordi dei modelli in 3D. Nota che le performance potrebbero decrementare di un bel pò (predefinito: disabilitato) +\v_flipped\Modalità mancino (Predefinito: off) + +\XonoticSettingsDialog/Effetti\Impostazioni effetti +\r_subdivisions_tolerance\Cambia lo smussamento delle curve della mappa (predefinito: normali) +\gl_picmip\Cambia la nitidezza delle textures. Valori più bassi riducono l'uso della memoria per le texture, però faranno apparire quest'ultime molto sfuocate. (predefinito: buona) +\r_picmipworld\Se impostato, riduce solo la qualità delle texture dei modelli (predefinito: abilitato) +\mod_q3bsp_nolightmaps\Usa le mappe di luce ad alta risoluzione, che appaiono più gradite alla vista, però sfruttano più memoria video (predefinito: abilitato) +\cl_particles_quality\Moltiplicatore del numero di particelle. Valori inferiori significano meno particelle, che di conseguenza incrementano le performance (predefinito: 0.5) +\r_drawparticles_drawdistance\Distanza per cui le particelle non vengono mostrate (predefinito: 1000) +\cl_decals\Abilita i decal (buchi dei proiettili e sangue) (predefinito: abilitati) +\r_drawdecals_drawdistance\I decal più lontano di questa distanza non vengono mostrati (predefinito: 300) +\cl_decals_time\Tempo in secondi passato il quale i decal sfumano (predefinito: 2) +\cl_gentle\Sostituisci il sangue e i gib con contenuti che non hanno alcun effetto di sangue (predefinito: disabilitato) +\cl_nogibs\Riduci il numero di gib o rimuovili completamente (predefinito: parecchi) +\v_kicktime\Quanto dura un colpo alla visuale per il danno (predefinito: 0) +\gl_texture_anisotropy\Qualità del filtro anisotropico (predefinito: 1x) +\r_glsl_deluxemapping\Usa gli effetti di illuminazione pixel per pixel (predefinito: abilitati) +\r_shadow_gloss\Abilita l'uso della lucentezza delle mappe sulle texture che la supportano (predefinito: abilitati) +\gl_flashblend\Abilita luci dinamiche più veloci ma meno gradevoli tramite il rendering di corone luminose invece di luci dinamiche reali (predefinito: disabilitato) +\r_shadow_realtime_dlight\Abilita il rendering delle luci dinamiche come esplosioni e lancio di razzi (predefinito: abilitato) +\r_shadow_realtime_dlight_shadows\Abilita il rendering di ombre dalle luci dinamiche (predefinito: abilitato) +\r_shadow_realtime_world\Abilita il rendering delle luci dell'ambiente in tempo reale in mappe che le supportano. Nota che questo potrebbe avere un grande impatto sulle performance. (predefinito: disabilitato) +\r_shadow_realtime_world_shadows\Abilita il rendering di ombre dalle luci dell'ambiente in tempo reale (predefinito: disabilitato) +\r_shadow_usenormalmap\Abilita l'uso di ombre direzionali sulle texture (predefinito: abilitato) +\r_showsurfaces\Disabilita completamente le texture per hardware molto lento. Questo dà un enorme boost alle performance, però appare molto poco gradevole. (predefinito: disabilitato) +\r_glsl_offsetmapping\Effetto del mappaggio in offset che fa sembrare che le texture con bumpmaps "saltino fuori" dalle piane superfici in 2D (predefinito: disabilitato) +\r_glsl_offsetmapping_reliefmapping\Mappaggio dell'offset di maggior qualità, che ha anche un enorme impatto sulle performance (predefinito: disabilitato) +\r_water\Qualità dei riflessi e delle rifrazioni, ha un enorme impatto sulle performance nelle mappe superfici riflettenti (predefinito: disabilitato) +\r_water_resolutionmultiplier\Risoluzione dei riflessi/rifrazioni (predefinito: buona) +\r_coronas\Abilita i bagliori corona attorno a determinate luci (predefinito: abilitati) +\r_coronas_occlusionquery\Dissolvi corone rispetto a visibilità (predefinito: abilitato) +\r_bloom\Abilita effetti bloom, che illuminano i pixel più vicini a pixel molto luminosi. Hanno un grosso impatto sulle performance. (predefinito: disabilitato) +\r_hdr\Versione a più alta qualità dei bloom, che hanno un enorme impatto sulle performance. (predefinito: disabilitato) +\r_motionblur\Forza della sfocatura da movimento - raccomandato a 0.5 +\r_damageblur\Ammontare della sfocatura da movimento quando si è colpiti - raccomandato a 0.4 + +\XonoticSettingsDialog/Audio\Impostazioni audio +\mastervolume\- +\bgmvolume\- +\snd_staticvolume\- +\snd_channel0volume\- +\snd_channel3volume\- +\snd_channel6volume\- +\snd_channel7volume\- +\snd_channel4volume\- +\snd_channel2volume\- +\snd_channel1volume\- +\snd_speed\Frequenza di campionamento in uscita +\snd_channels\Numero di canali in uscita +\snd_swapstereo\Inverti canali sinistro/destro +\snd_spatialization_control\Abilita spazialità (mischia leggermente i canali destro e sinistro per decrementare di un pò la separazione stereo per le cuffie) +\cl_voice_directional\Abilita voci direzionali +\cl_voice_directional_taunt_attenuation\Distanza dalla quale gli insulti possono essere uditi +\cl_autotaunt\Automaticamente insulta i nemici quando gli fragghi +\cl_sound_maptime_warning\Un annuncio ti avverte dei minuti rimanenti alla fine della partita +\cl_hitsound\Riproduci un suono quando il tuo sparo colpisce un nemico +\menu_sounds\Riproduci suoni quando clicchi o navighi su oggetti del menu + +\XonoticSettingsDialog/Rete\Impostazioni di rete +\cl_movement\Abilita predizione del movimento lato client +\cl_nolerp\Abilita aggiornamento da rete spianato +\shownetgraph\Mostra un grafico delle dimensioni dei pacchetti e di altre informazioni +\_cl_rate\Specifica la velocità della tua rete con questa barra +\cl_netfps\Quanti pacchetti in ingresso inviare al server ogni secondo +\cl_curl_maxdownloads\Massimo numero di download HTTP/FTP contemporanei +\cl_curl_maxspeed\Velocità massima di download +\cl_port\Forza il client a usare la porta selezionata a meno che non è impostata a 0 + +\XonoticSettingsDialog/Altro\Impostazioni varie +\showtime\Mostra l'orario corrente, utile negli screenshot +\showdate\Mostra la data corrente, utile negli screenshot +\showfps\Mostra i fotogrammi al secondo + +\XonoticSettingsDialog/Impostazioni avanzate...\Impostazioni avanzate dove puoi mettere mano ad ogni singola variabile del gioco +\g_friendlyfire\Percentuale di danno inflitto ai compagni di squadra +\g_mirrordamage\Percentuale di danno inflitto ai compagni di squadra che viene riversato su di te +\g_tdm_teams_override\Non tenere conto del numero predefinito di squadre nei giochi di squadra + +\viewsize\Abilita/disabilita lo sfondo dell'HUD +\cl_hidewaypoints\Mostra vari waypoint specifici di certi tipi di gioco +\g_waypointsprite_scale\Scala moltiplicatore dei waypoint +\g_waypointsprite_alpha\Controlla la trasparenza dei waypoint +\cl_shownames\Mostra il nome del giocatore a cui stai mirando + +\crosshair_hittest\Nessuno: non fare il test di colpire per il mirino; TrueAim: sfoca il mirino quando non colpiresti il muro; Nemici: allarga anche il mirino quando colpiresti un nemico diff --git a/tooltips.db.ru b/tooltips.db.ru new file mode 100644 index 0000000000..f8e286210a --- /dev/null +++ b/tooltips.db.ru @@ -0,0 +1,220 @@ +0 +\XonoticSingleplayerDialog\Начать одиночную кампанию или быструю игру против ботов + + +\XonoticMultiplayerDialog\Играть по сети, просмотреть демо или изменить настройки игрока +\XonoticMultiplayerDialog/Серверы\Поиск игровых серверов +\menu_slist_showempty\Показывать пустые сервера +\menu_slist_showfull\Показывать полные сервера, не имеющие свободных мест +\net_slist_pause\Приостановить обновление списка серверов для предотвращения их скакания +\XonoticMultiplayerDialog/Info...\Показать больше сведений о выбранном сервере +\XonoticMultiplayerDialog/В закладки\Добавить выбранный сервер в закладки, так найти его будет быстрее +\XonoticMultiplayerDialog/Создать\Запустить собственную игру +\XonoticMultiplayerDialog/Демо\Список демо для просмотра +\XonoticMultiplayerDialog/Player Setup\Изменить настройки игрока + +\XonoticTeamSelectDialog/join 'best' team (auto-select)\Автовыбор команды (советуется) +\XonoticTeamSelectDialog/красная\Присоединиться к красной команде +\XonoticTeamSelectDialog/синяя\Присоединиться к синей команде +\XonoticTeamSelectDialog/жёлтая\Присоединиться к жёлтой команде +\XonoticTeamSelectDialog/розовая\Присоединиться к розовой команде + +\timelimit_override\Ограничение времени в минутах, состязание закончится при его достижении +\fraglimit_override\Количество очков, необходимых для завершения состязания +\menu_maxplayers\Предельное количество игроков и ботов, которые могут быть одновременно подключены к серверу +\bot_number\Количество ботов на сервере +\skill\Насколько искусными будут боты +\g_maplist_votable\Количество карт, предлагаемых в голосовании после состязания +\sv_vote_simple_majority_factor\Простое большинство выигрывает голосование +\XonoticMultiplayerDialog/Advanced settings...\Дополнительные серверные настройки +\XonoticMultiplayerDialog/Mutators...\Мутаторы и арены оружий +\g_cloaked\Все игроки почти невидимы +\g_footsteps\Включить звуки шагов +\g_midair\Только находящиеся в воздухе получают повреждения +\g_vampire\Урон, наносимый противнику, прибавляется к собственному здоровью +\g_bloodloss\Величина здоровья, ниже которой наступает оглушение из-за потери крови +\sv_gravity\Падение происходит медленнее. Чем ниже значение, тем ниже гравитация +\g_grappling_hook\Передвижение и полёты на подтягивающем крюке +\g_jetpack\Полёты на реактивном ранце +\g_pinata\Во время смерти выбрасывается всё оружие, которое нёс "убитый", что даёт возможность его подобрать +\g_weapon_stay\Всё собранное оружие остаётся после возрождений +\g_weaponarena\Selecting a weapon arena will give all players that weapon at spawn as well as unlimited ammo, and disable all other weapon pickups. +\menu_weaponarena_with_laser\Also enable the laser in the weapon arena +\g_minstagib\Players will be given the Minstanex, which is a railgun with infinite damage. If the player runs out of ammo, he will have 10 seconds to find some or if he fails to do so, face death. The secondary fire mode is a laser which does not inflict any damage and is good for doing trickjumps. +\g_nix\No items Xonotic - instead of pickup items, everyone plays with the same weapon. After some time, a countdown will start, after which everyone will switch to another weapon. +\g_nix_with_laser\Always carry the laser as an additional weapon in Nix +\XonoticMultiplayerDialog/Select all\Выбрать все карты +\XonoticMultiplayerDialog/Select none\Снять выделение со всех карт + + +\XonoticMultiplayerDialog/Проверка производительности\Замерить, насколько быстро компьютер способен играть выбранное демо + +\fov\Угол обзора в градусах, допустимы значения от 60 то 130, по умолчанию 90 +\cl_bobcycle\Частота качания вида +\cl_zoomfactor\How big the zoom factor is when the zoom button is pressed +\cl_zoomsensitivity\How zoom changes sensitivity, from 0 (lower sensitivity) to 1 (no sensitivity change) +\cl_zoomspeed\How fast the view will be zoomed, disable to zoom instantly +\XonoticMultiplayerDialog/Weapon settings...\Set your most preferred weapons, autoswitch and weapon model settings + +\cl_weaponpriority_useforcycling\Make use of the list above when cycling through weapons with the mouse wheel +\cl_autoswitch\Automatically switch to newly picked up weapons if they are better than what you are carrying +\r_drawviewmodel\Draw the weapon model +\cl_gunalign\Position of the weapon model; requires reconnect + +\crosshair_per_weapon\Set a different crosshair for each weapon, good if you play without weapon models +\crosshair_color_override\Also set the color of the crosshair depending on the weapon you are currently holding +\crosshair_size\Настроить размер перекрестья +\crosshair_color_alpha\Настроить прозрачность перекрестья +\crosshair_color_red\Красная составляющая цвета перекрестья +\crosshair_color_green\Зелёная составляющая цвета перекрестья +\crosshair_color_blue\Синяя составляющая цвета перекрестья +\sbar_hudselector\Use the old HUD layout +\XonoticMultiplayerDialog/Waypoints setup...\- +\_cl_name\Имя, под которым вы появитесь в игре + +\XonoticSettingsDialog\Изменить настройки игры +\XonoticCreditsDialog\The Xonotic credits +\XonoticTeamSelectDialog\- +\XonoticMutatorsDialog\- +\XonoticMapInfoDialog\- +\XonoticUserbindEditDialog\- +\XonoticWinnerDialog\- +\XonoticWeaponsDialog\- +\XonoticRadarDialog\- +\XonoticServerInfoDialog\- +\XonoticCvarsDialog\- + +\XonoticQuitDialog\Выйти из игры +\XonoticQuitDialog/Да\Пора саночки возить... +\XonoticQuitDialog/Нет\Остались здесь ещё дела! + +\XonoticSettingsDialog/Ввод\Настройки устройств ввода +\sensitivity\Множитель скорости мыши +\menu_mouse_speed\Множитель скорости мыши в меню, не влияет на прицеливание в игре +\m_filter\Сглаживает движения мыши, но значительно ухудшает отзывчивость прицеливания +\m_pitch\Обратить движения мыши по вертикальной оси +\vid_dgamouse\Использовать DGA ввод для мыши +\con_closeontoggleconsole\Использовать привязку для открытия консоли также и для её сокрытия +\sbar_showbinds\Отображать действия / привязанные клавиши в строках, показываемых во время игры +\cl_showpressedkeys\Показывать, какие кнопки движений нажимает игрок + +\XonoticSettingsDialog/Изображение\Настройки изображения +\vid_width\Разрешение экрана +\vid_bitsperpixel\Сколько бит на точку использовать для вывода, советуется 32 +\vid_fullscreen\Включить полноэкранный режим (по умолчанию: включено) +\vid_vsync\Enable vertical synchronization to prevent tearing, will cap your fps to the screen refresh rate (default: disabled) +\r_glsl\Enable OpenGL 2.0 pixel shaders for lightning (default: enabled) +\gl_vbo\Make use of Vertex Buffer Objects to store static geometry in video memory for faster rendering (default: Vertex and Triangles) +\r_depthfirst\Eliminate overdraw by rendering a depth-only version of the scene before the normal rendering starts (default: disabled) +\gl_texturecompression\Compress the textures for video cards with small amounts of video memory available (default: None) +\gl_finish\Make the CPU wait for the GPU to finish each frame, can help with some strange input or video lag on some machines (default: disabled) +\v_brightness\Яркость чёрного (по умолчанию: 0) +\v_contrast\Яркость белого (по умолчанию: 1) +\v_gamma\Inverse gamma correction value, a brightness effect that does not affect white or black (default: 1.125) +\v_contrastboost\By how much to multiply the contrast in dark areas (default: 1) +\r_glsl_saturation\Saturation adjustment (0 = grayscale, 1 = normal, 2 = oversaturated), requires GLSL color control (default: 1) +\v_glslgamma\Enable use of GLSL to apply gamma correction, note that it might decrease performance by a lot (default: disabled) +\r_ambient\Окружающее освещение, если выставлено слишком сильным, приводит к тому, что свет на картах выглядит блёклым и плоским (по умолчанию: 4) +\r_hdr_scenebrightness\Общая яркость вывода (по умолчанию: 1) +\vid_samples\Enable antialiasing, which smooths the edges of 3D geometry. Note that it might decrease performance by quite a lot (default: disabled) +\v_flipped\Poor man's left handed mode (default: off) + +\XonoticSettingsDialog/Эффекты\Настройки эффектов +\r_subdivisions_tolerance\Change the smoothness of the curves on the map (default: normal) +\gl_picmip\Change the sharpness of the textures. Lowering it will effectively reduce texture memory usage, but make the textures appear very blurry. (default: good) +\r_picmipworld\If set, only reduce the texture quality of models (default: enabled) +\mod_q3bsp_nolightmaps\Use high resolution lightmaps, which will look pretty but use up some extra video memory (default: enabled) +\cl_particles_quality\Multiplier for amount of particles. Less means less particles, which in turn gives for better performance (default: 0.5) +\r_drawparticles_drawdistance\Particles further away than this will not be drawn (default: 1000) +\cl_decals\Enable decals (bullet holes and blood) (default: enabled) +\r_drawdecals_drawdistance\Decals further away than this will not be drawn (default: 300) +\cl_decals_time\Time in seconds before decals fade away (default: 2) +\cl_gentle\Replace blood and gibs with content that does not have any gore effects (default: disabled) +\cl_nogibs\Reduce the amount of gibs or remove them completely (default: lots) +\v_kicktime\How long a view kick from damage lasts (default: 0) +\gl_texture_anisotropy\Anisotropic filtering quality (default: 1x) +\r_glsl_deluxemapping\Use per-pixel lighting effects (default: enabled) +\r_shadow_gloss\Enable the use of glossmaps on textures supporting it (default: enabled) +\gl_flashblend\Enable faster but uglier dynamic lights by rendering bright coronas instead of real dynamic lights (default: disabled) +\r_shadow_realtime_dlight\Enable rendering of dynamic lights such as explosions and rocket lights (default: enabled) +\r_shadow_realtime_dlight_shadows\Enable rendering of shadows from dynamic lights (default: disabled) +\r_shadow_realtime_world\Enable rendering of full realtime world lighting on maps that support it. Note that this might have a big impact on performance. (default: disabled) +\r_shadow_realtime_world_shadows\Enable rendering of shadows from realtime world lights (default: disabled) +\r_shadow_usenormalmap\Enable use of directional shading on textures (default: enabled) +\r_showsurfaces\Disable textures completely for very slow hardware. This gives a huge performance boost, but looks very ugly. (default: disabled) +\r_glsl_offsetmapping\Offset mapping effect that will make textures with bumpmaps appear like they "pop out" of the flat 2D surface (default: disabled) +\r_glsl_offsetmapping_reliefmapping\Higher quality offset mapping, which also has a huge impact on performance (default: disabled) +\r_water\Reflection and refraction quality, has a huge impact on performance on maps with reflecting surfaces (default: disabled) +\r_water_resolutionmultiplier\Resolution of reflections/refractions (default: good) +\r_coronas\Enable corona flares around certain lights (default: enabled) +\r_coronas_occlusionquery\Fade coronas according to visibility (default: enabled) +\r_bloom\Enable bloom effect, which brightens the neighboring pixels of very bright pixels. Has a big impact on performance. (default: disabled) +\r_hdr\Higher quality version of bloom, which has a huge impact on performance. (default: disabled) +\r_motionblur\Motion blur strength - 0.5 recommended +\r_damageblur\Amount of motion blur when hurt - 0.4 recommended + +\XonoticSettingsDialog/Звук\Настройки звука +\mastervolume\- +\bgmvolume\- +\snd_staticvolume\- +\snd_channel0volume\- +\snd_channel3volume\- +\snd_channel6volume\- +\snd_channel7volume\- +\snd_channel4volume\- +\snd_channel2volume\- +\snd_channel1volume\- +\snd_speed\Частота дискретизации для вывода звука +\snd_channels\Число каналов для вывода звука +\snd_swapstereo\Поменять местами правый и левый каналы +\snd_spatialization_control\Enable spatialization (blend the right and left channel slightly to decrease stereo separation a bit for headphones) +\cl_voice_directional\Enable directional voices +\cl_voice_directional_taunt_attenuation\Расстояние, с которого будут слышны насмешки +\cl_autotaunt\Автоматически насмехаться над противниками после их поражений +\cl_sound_maptime_warning\Звук предупреждения, сообщающий оставшиеся до конца состязания минуты +\cl_hitsound\Играть звук оповещения, когда выстрел достигает противника +\menu_sounds\Играть звуки при взаимодействии с меню + +\XonoticSettingsDialog/Сеть\Настройки сети +\cl_movement\Включить предсказание движения на стороне клиента +\cl_nolerp\Enable network update smoothing +\shownetgraph\Показывать график размеров пакетов и других сведений +\_cl_rate\Укажите скорость вашей сети с помощью этого ползунка +\cl_netfps\Сколько пакетов посылать серверу каждую секунду +\cl_curl_maxdownloads\Предел одновременных HTTP/FTP загрузок +\cl_curl_maxspeed\Предел скорости скачивания +\cl_port\Force client to use chosen port unless it is set to 0 + +\XonoticSettingsDialog/Разное\Разные настройки +\showtime\Показывать текущее время, полезно на снимках экранов +\showdate\Показывать текущую дату, полезно на снимках экранов +\showfps\Show your rendered frames per second +\cl_showspeed\Показывать скорость игрока +\cl_showspeed_unit\Выбор единиц измерения спидометра. qu/s = quake units/second = дюйм/секунду +\cl_showacceleration\Показывать ускорение игрока +\cl_showacceleration_scale\Excaggerate the accelerometer by this scale multiplier + +\XonoticSettingsDialog/Advanced settings...\Продвинутые настройки, в которых можно подстроить каждую переменную игры +\g_friendlyfire\Доля урона, получаемого союзниками от союзников +\g_mirrordamage\Доля урона, наносимого союзнику, которая будет отражена на себя +\g_tdm_teams_override\Заменить значение по умолчанию количества команд в командных играх + +\cl_teamradar_position\- +\cl_teamradar_size\- +\cl_teamradar_zoommode\- +\cl_teamradar_rotation\- +\cl_teamradar_scale\- +\cl_teamradar_foreground_alpha\- +\cl_teamradar_background_alpha\Значение прозрачности фона радара +\viewsize\Включить/выключить фон HUD +\sbar_alpha_bg\Значение прозрачности фона HUD +\sbar_color_bg_r\Красная составляющая цвета фона HUD +\sbar_color_bg_g\Зелёная составляющая цвета фона HUD +\sbar_color_bg_b\Синяя составляющая цвета фона HUD +\sbar_color_bg_team\Насыщенность командного цвета фона HUD +\cl_hidewaypoints\Показывать различные отметки, определяемые видом игры +\g_waypointsprite_scale\Множитель размера отметок +\g_waypointsprite_alpha\Управление прозрачностью отметок +\cl_shownames\Показывать имя игрока, в которого вы целитесь + +\crosshair_hittest\Отключена: нет проверок перекрестья на попадание; TrueAim: размывать перекрестье, когда не наведено на стену; Враги: также увеличивать перекрестье, когда наведено на врага diff --git a/tooltips.db.uk b/tooltips.db.uk new file mode 100644 index 0000000000..97dec8cba7 --- /dev/null +++ b/tooltips.db.uk @@ -0,0 +1,201 @@ +0 +\XonoticSingleplayerDialog\Почніть одиночну кампанію або випадковий бій проти ботів + + +\XonoticMultiplayerDialog\Грайте по інтернету, локальній мережі, переглядайте демо та змінюйте налаштування гравця +\XonoticMultiplayerDialog/Сервери\Знайти сервери для гри +\menu_slist_showempty\Показувати порожні сервери +\menu_slist_showfull\Показувати повні сервери без вільних місць +\net_slist_pause\Призупинити оновлення списку серверів для зручнішого вибору +\XonoticMultiplayerDialog/Відомості...\Показати більше інформації про виділений сервер +\XonoticMultiplayerDialog/Закладка\Зробити закладку на цьому сервері для того, щоб потім знаходити його швидше +\XonoticMultiplayerDialog/Створити\Почніть свою власну гру +\XonoticMultiplayerDialog/Демо\Знайдіть та перегляньте демо записи +\XonoticMultiplayerDialog/Гравець\Налаштування вашого гравця + +\XonoticTeamSelectDialog/обрати підхожу команду (автовибір)\Автоматично обрати команду (рекомендується) +\XonoticTeamSelectDialog/червона\Приєднатися до червоної команди +\XonoticTeamSelectDialog/синя\Приєднатися до синьої команди +\XonoticTeamSelectDialog/жовта\Приєднатися до жовтої команди +\XonoticTeamSelectDialog/рожева\Приєднатися до рожевої команди + +\timelimit_override\Час, після якого матч закінчиться +\fraglimit_override\Кількість фрагів, яка потрібна для закінчення матчу +\menu_maxplayers\Максимальна кількість гравців та ботів на вашому сервері +\bot_number\Кількість ботів на вашому сервері +\skill\Вкажіть досвідченість ботів +\g_maplist_votable\Кількість мап які будуть доступні для голосування у кінці матчу +\sv_vote_simple_majority_factor\Проста більшість перемагає в голосуванні +\XonoticMultiplayerDialog/Додаткові налаштування...\Додаткові налаштування сервера +\XonoticMultiplayerDialog/Мутатори...\Мутатори і арени +\g_dodging\Вмикає ухилення +\g_cloaked\Всі гравці майже невидимі +\g_footsteps\Вмикає звуки кроків +\g_midair\Шкоду можливо нанести тільки коли ворог у повітрі +\g_vampire\Шкода яку ви наносите ворогам додається до вашого здоров'я +\g_bloodloss\Кількість здоров'я, нижче за яку гравець буде паралізований від втрати крові +\sv_gravity\Предмети падатимуть повільніше, менше значення робить гравітацію нижче +\g_grappling_hook\Гравці отримують гак +\g_jetpack\Гравці отримують реактивний ранець +\g_pinata\Після того, як гравця вб'ють, з нього випаде вся зброя яку він мав +\g_weapon_stay\Зброя залишається після того, як була підібраною +\g_weaponarena\Вибір арени з окремою зброєю дасть гравцям цю зброю і необмежену кількість боєприпасів до неї, і прибере з мапи всю іншу зброю +\menu_weaponarena_with_laser\Зробити лазер доступним на аренах +\g_minstagib\Гравці отримують МінстаНекс, рейкову гармату яка вбиває одним пострілом. Якщо гравець витратить усі боєприпаси, у нього буде десять секунд щоб поновити його, інакше він загине. Альтернативний вогонь гармати це лазер який не наносить шкоди, корисний для трюків +\g_nix\Нікс (No items Xonotic) - замість того щоб підбирати предмети, всі гравці грають з однією зброєю. Через деякий час почнеться відлік, і зброя у всіх зміниться на іншу +\g_nix_with_laser\Зробити лазер доступним у Нікс +\XonoticMultiplayerDialog/Обрати все\Обрати всі мапи +\XonoticMultiplayerDialog/Обрати нічого\Зняти вибір з усіх мап + + +\XonoticMultiplayerDialog/Тест продуктивності\Перевірте як швидко ваш комп'ютер зможе програти обране демо + +\fov\Поле огляду у градусах, від 60 до 130, 90 за замовчуванням +\cl_bobcycle\Частота гойдання, вимкнути щоб прибрати гойдання +\cl_zoomfactor\Сила зуму коли натиснута клавіша +\cl_zoomsensitivity\Як зум змінює чутливість миші, від 0 (зменшує чутливість) до 1 (без змін) +\cl_zoomspeed\Швидкість зуму, вимкніть щоб збільшувати зображення миттєво +\XonoticMultiplayerDialog/Налаштування зброї...\Вкажіть зброю якій ви надаєте перевагу, налаштуйте автоматичне перемикання та моделі зброї + +\cl_weaponpriority_useforcycling\Використовувати список вгорі під час вибору зброї колесиком миші +\cl_autoswitch\Автоматично перемикатися на щойно підняту зброю, якщо вона краща за ту, що ви тримаєте у руках +\r_drawviewmodel\Показувати модель зброї +\cl_gunalign\Положення моделі зброї, потрібно буде з'єднатися знову + +\crosshair_per_weapon\Встановити приціл для кожної зброї окремо, корисно для гри без моделей зброї +\crosshair_color_per_weapon\Колір прицілу буде залежати від кожної окремої зброї +\crosshair_size\Встановити розмір прицілу +\crosshair_alpha\Встановити прозорість прицілу +\crosshair_color\Встановити колір прицілу +\sbar_hudselector\Використовувати старе розміщення HUD +\XonoticMultiplayerDialog/Налаштування дороговказів...\- +\_cl_name\Ім'я під яким ви з'явитесь у грі + +\XonoticSettingsDialog\Змінити налаштування гри +\XonoticCreditsDialog\Розробники Xonotic +\XonoticTeamSelectDialog\- +\XonoticMutatorsDialog\- +\XonoticMapInfoDialog\- +\XonoticUserbindEditDialog\- +\XonoticWinnerDialog\- +\XonoticWeaponsDialog\- +\XonoticRadarDialog\- +\XonoticServerInfoDialog\- +\XonoticCvarsDialog\- + +\XonoticQuitDialog\Вийти з гри +\XonoticQuitDialog/Так\Назад до роботи... +\XonoticQuitDialog/Ні\На мене чекають ще кілька фрагів! + +\XonoticSettingsDialog/Керування\Налаштування керування +\sensitivity\Швидкість миші +\menu_mouse_speed\Швидкість миші у меню, не впливає на ігровий процес +\m_filter\Згладжування руху миші +\m_pitch\Інвертувати рух миші по осі Y +\vid_dgamouse\Використовувати ввід DGA для миші +\con_closeontoggleconsole\Дозволяє закривати і відкривати консоль однією клавішею + +\XonoticSettingsDialog/Відео\Налаштування відео +\vid_width\Роздільність екрану +\vid_bitsperpixel\Скільки використовувати бітів на піксель (BPP), рекомендується 32 +\vid_fullscreen\На повний екран (за замовчуванням: увімкнуто) +\vid_vsync\Вмикає вертикальну синхронізацію щоб запобігти розривам зображення, ваші FPS не будуть підніматися вище швидкості оновлення монітору (за замовчуванням: увімкнуто) +\r_glsl\Вмикає піксельні шейдери OpenGL 2.0 для освітлення (за замовчуванням: увімкнуто) +\gl_vbo\Використовувати Vertex Buffer Objects щоб зберігати нерухому геометрію у відеопам'яті для прискорення рендеренгу (за замовчуванням: вершини та трикутники) +\r_depthfirst\Прибирає перекриття одних пікселів іншими створюючи спочатку версію сцени з лише глибиною (за замовчуванням: вимкнуто) +\gl_texturecompression\Стискати текстури для відеокарт з малою кількістю відеопам'яті (за замовчуванням: вимкнуто) +\gl_finish\Центральний процесор буде чекати, поки GPU відеокарти не закінчить кадр, може допомогти на деяких системах при деяких проблемах (за замовчуванням: вимкнуто) +\v_brightness\Яскравіcть чорного (за замовчуванням: 0) +\v_contrast\Яскравість білого (за замовчуванням: 1) +\v_gamma\Яскравість що не впливає на білий та чорний колір (за замовчуванням: 1.125) +\v_contrastboost\На скільки збільшувати контраст в темних місцях (за замовчуванням: 1) +\r_glsl_saturation\Корекція насиченості (0 = чорно-біла, 1 = нормальна, 2 = перенасичена), необхідно використовувати шейдери GLSL для контролю кольором (за замовчуванням: 1) +\v_glslgamma\Вмикає GLSL для використання корекції гамми, може мати сильній вплив на продуктивність (за замовчуванням: вимкнуто) +\r_ambient\Навколишнє освітлення, якщо значення надто високе, то освітлення на мапах стає приглушеним та плоским (за замовчуванням: 4) +\r_hdr_scenebrightness\Яскравість (за замовчуванням: 1) +\vid_samples\Увімкнути антиаліасинг, який буде згладжувати грані 3D поверхонь. Прийміть до уваги, що це може сильно зменшити продуктивність. (за замовчуванням: вимкнуто) +\v_flipped\Простий режим для лівші (за замовчуванням: вимкнуто) + +\XonoticSettingsDialog/Ефекти\Налаштування ефектів +\r_subdivisions_tolerance\Змінити рівність кривих на мапі (за замовчуванням: нормально) +\gl_picmip\Чіткість текстур. Зниження параметру зменшить використання відеопам'яті, але зробить текстури нечіткими (за замовчуванням: добре) +\r_picmipworld\Знижує якість текстур тільки на моделях (за замовчуванням: увімкнуто) +\mod_q3bsp_nolightmaps\Використовувати мапи освітлення з високою роздільністю, красиві, але використовують більше відеопам'яті (за замовчуванням: увімкнуто) +\cl_particles_quality\Кількість часток, чим менша кількість тим менший вплив на продуктивність (за замовчуванням: 0.5) +\r_drawparticles_drawdistance\Частки на відстані більшій ніж ця не будуть створюватись (за замовчуванням: 1000) +\cl_decals\Сліди від куль та пострілів (за замовчуванням: увімкнуто) +\r_drawdecals_drawdistance\Сліди на відстані більшій ніж ця не будуть створюватись (за замовчуванням: 300) +\cl_decals_time\Час у секундах після якого сліди зникатимуть (за замовчуванням: 2) +\cl_gentle\Замінити шматки тіла та кров не жорстокими елементами (за замовчуванням: вимкнуто) +\cl_nogibs\Зменшити кількість шматків тіла, або відключити їх зовсім (за замовчуванням: багато) +\v_kicktime\Як довго триватиме поштовх від ураження (за замовчуванням: 0) +\gl_texture_anisotropy\Якість анізотропної фільтрації (за замовчуванням: 1x) +\r_glsl_deluxemapping\Використовувати попіксельні ефекти освітлення (за замовчуванням: увімкнуто) +\r_shadow_gloss\Вмикає використання мап блиску на текстурах, які їх підтримують (за замовчуванням: увімкнуто) +\gl_flashblend\Вмикає швидкіше, але не таке гарне динамічне освітлення за допомогою яскравих корон, а не справжніх динамічних вогнів (за замовчуванням: вимкнуто) +\r_shadow_realtime_dlight\Вмикає рендеринг динамічних вогнів від вибухів та ракет (за замовчуванням: увімкнуто) +\r_shadow_realtime_dlight_shadows\Вмикає тіні від динамічних джерел освітлення (за замовчуванням: вимкнуто) +\r_shadow_realtime_world\Вмикає повний рендеринг динамічного освітлення світу, може мати сильний вплив на продуктивність. (за замовчуванням: вимкнуто) +\r_shadow_realtime_world_shadows\Вмикає тіні від динамічних джерел освітлення світу (за замовчуванням: увімкнуто) +\r_shadow_usenormalmap\Вмикає використання directional shading на текстурах (за замовчуванням: увімкнуто) +\r_showsurfaces\Вимикає текстури повністю, для дуже слабких систем. Покращує продуктивність, але виглядає погано (за замовчуванням: вимкнуто) +\r_glsl_offsetmapping\Офсетне текстурування, що змусить текстури з мапами висот виглядати об'ємними (за замовчуванням: вимкнуто) +\r_glsl_offsetmapping_reliefmapping\Якісніше офсетне текстурування, має великий вплив на продуктивність (за замовчуванням: вимкнуто) +\r_water\Якість віддзеркалень та заломлень, сильно впливає на продуктивність на мапах, де є дзеркальні поверхні (за замовчуванням: вимкнуто) +\r_water_resolutionmultiplier\Роздільність віддзеркалень/заломлень (за замовчуванням: увімкнуто) +\r_coronas\Увімкнути сонячні корони навколо деяких джерел освітлення (за замовчуванням: увімкнуто) +\r_coronas_occlusionquery\Прибирати корони відповідно з видимістю (за замовчуванням: увімкнуто) +\r_bloom\Увімкнути ефект bloom, який освітлює ближні пікселі дуже яскравих пікселів. Має сильний вплив на продуктивність (за замовчуванням: вимкнуто) +\r_hdr\Якісніша версія ефекту bloom, сильно впливає на продуктивність (за замовчуванням: вимкнуто) +\r_motionblur\Сила ефекту motion blur - рекомендується 0.5 +\r_damageblur\Кількість motion blur під час поранення - рекомендується 0.4 + +\XonoticSettingsDialog/Звук\Налаштування аудіо +\mastervolume\- +\bgmvolume\- +\snd_staticvolume\- +\snd_channel0volume\- +\snd_channel3volume\- +\snd_channel6volume\- +\snd_channel7volume\- +\snd_channel4volume\- +\snd_channel2volume\- +\snd_channel1volume\- +\snd_speed\Частотність звуку +\snd_channels\Кількість каналів +\snd_swapstereo\Поміняти місцями лівий та правий канал +\snd_spatialization_control\Злегка змішати правий та лівий канали щоб трохи зменшити розділення стерео для навушників +\cl_voice_directional\Вмикає просторові голоси +\cl_voice_directional_taunt_attenuation\Відстань на якій можливо почути глузування +\cl_autotaunt\Автоматично глузувати над ворогами після того, як ви вбили їх +\cl_sound_maptime_warning\Увімкнути попередження про те, скільки залишилося часу до кінця матчу +\cl_hitsound\Грати спеціальний звук коли ви влучаєте у ворога +\menu_sounds\Увімкнути звуки меню + +\XonoticSettingsDialog/Мережа\Налаштування мережі +\cl_movement\Увімкнути передбачення руху зі сторони клієнта +\cl_nolerp\Увімкнути згладжування оновлення мережі +\shownetgraph\Показувати графік розмірів пакетів та іншої інформації +\_cl_rate\Вкажіть швидкість вашої мережі +\cl_netfps\Скільки вхідних пакетів посилати серверу кожну секунду +\cl_curl_maxdownloads\Максимальна кількість одночасних HTTP/FTP завантажень +\cl_curl_maxspeed\Максимальна швидкість завантаження +\cl_port\Змушувати клієнта використовувати обраний порт, але тільки якщо значення не 0 + +\XonoticSettingsDialog/Різне\Різні налаштування +\showtime\Показувати поточний час, корисно для скриншотів +\showdate\Показувати поточну дату, корисно для скриншотів +\showfps\Показувати лічильник кадрів за секунду + +\XonoticSettingsDialog/Додаткові налаштування...\Тут ви зможете змінити будь-які деталі гри +\g_friendlyfire\Процент шкоди яку ви будете наносити товаришам по команді +\g_mirrordamage\Процент від шкоди що ви нанесли товаришу по команді який буде віддзеркалений вам +\g_tdm_teams_override\Переписати клькість команд за замовчуванням в командних іграх + +\viewsize\Увімкнути/вимкнути фон HUD +\cl_hidewaypoints\Показувати дороговкази різний ігрових режимів +\g_waypointsprite_scale\Вкажіть розмір дороговказів +\g_waypointsprite_alpha\Вкажіть прозорість дороговказів +\cl_shownames\Показувати ім'я гравця в якого ви цілитися + +\crosshair_hittest\Жодного: не проводити тест на влучання для прицілу; TrueAim: робити приціл нечітким коли ви не влучите у стіну; Вороги: також збільшувати приціл коли ви влучите у ворога diff --git a/unit_walker.cfg b/unit_walker.cfg index 607553c8e0..e08374945e 100644 --- a/unit_walker.cfg +++ b/unit_walker.cfg @@ -8,6 +8,12 @@ set g_turrets_unit_walker_speed_swim 200 set g_turrets_unit_walker_speed_jump 800 set g_turrets_unit_walker_speed_stop 90 +set g_turrets_unit_walker_turn 20 +set g_turrets_unit_walker_turn_walk 15 +set g_turrets_unit_walker_turn_run 7 +set g_turrets_unit_walker_turn_swim 10 +set g_turrets_unit_walker_turn_strafe 5 + // Main machineguns prop's set g_turrets_unit_walker_std_shot_dmg 5 set g_turrets_unit_walker_std_shot_refire 0.05 @@ -45,11 +51,11 @@ set g_turrets_unit_walker_std_track_type 1 set g_turrets_unit_walker_std_rockets_range 4000 set g_turrets_unit_walker_std_rockets_range_min 500 set g_turrets_unit_walker_std_rocket_refire 10 -set g_turrets_unit_walker_std_rocket_dmg 50 +set g_turrets_unit_walker_std_rocket_dmg 45 set g_turrets_unit_walker_std_rocket_radius 150 set g_turrets_unit_walker_std_rocket_force 150 -set g_turrets_unit_walker_std_rocket_turnrate 0.4 -set g_turrets_unit_walker_std_rocket_speed 900 +set g_turrets_unit_walker_std_rocket_turnrate 0.05 +set g_turrets_unit_walker_std_rocket_speed 1000 // Meele attack. Only happens when theres a target directly in front set g_turrets_unit_walker_std_meele_range 100 diff --git a/update-cvarcount.sh b/update-cvarcount.sh deleted file mode 100755 index 0bd63e9fb2..0000000000 --- a/update-cvarcount.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh - -countw=`awk '/^seta? g_/ { print $2; }' balanceXonotic.cfg | sort -u | tr -d '\r' | git hash-object --stdin | cut -c 1-32` -for b in balance*.cfg; do - countb=`awk '/^seta? g_/ { print $2; }' "$b" | sort -u | tr -d '\r' | git hash-object --stdin | cut -c 1-32` - if [ "$countw" != "$countb" ]; then - echo "Mismatch between balanceXonotic.cfg and $b. Aborting." - echo "Differences are:" - echo "< missing in $b" - echo "> must get removed from $b" - A=`mktemp || echo a.tmp` - B=`mktemp || echo b.tmp` - awk '/^seta? g_/ { print $2; }' balanceXonotic.cfg | sort -u | tr -d '\r' > "$A" - awk '/^seta? g_/ { print $2; }' "$b" | sort -u | tr -d '\r' > "$B" - diff "$A" "$B" | grep '^[<>]' | sort - rm -f "$A" "$B" - exit 1 - fi -done diff --git a/vehicle_bumblebee.cfg b/vehicle_bumblebee.cfg new file mode 100644 index 0000000000..0d4feb3da0 --- /dev/null +++ b/vehicle_bumblebee.cfg @@ -0,0 +1,40 @@ +set g_vehicle_bumblebee_speed_forward 400 +set g_vehicle_bumblebee_speed_strafe 200 +set g_vehicle_bumblebee_speed_up 200 +set g_vehicle_bumblebee_speed_down 200 +set g_vehicle_bumblebee_turnspeed 72 +set g_vehicle_bumblebee_pitchspeed 36 +set g_vehicle_bumblebee_pitchlimit 15 +set g_vehicle_bumblebee_friction 0.75 + +set g_vehicle_bumblebee_energy 500 +set g_vehicle_bumblebee_energy_regen 50 +set g_vehicle_bumblebee_energy_regen_pause 1 + +set g_vehicle_bumblebee_health 750 +set g_vehicle_bumblebee_health_regen 25 +set g_vehicle_bumblebee_health_regen_pause 5 + +set g_vehicle_bumblebee_shield 250 +set g_vehicle_bumblebee_shield_regen 100 +set g_vehicle_bumblebee_shield_regen_pause 2 + +set g_vehicle_bumblebee_cannon_cost 10 +set g_vehicle_bumblebee_cannon_damage 75 +set g_vehicle_bumblebee_cannon_radius 150 +set g_vehicle_bumblebee_cannon_refire 1.5 +set g_vehicle_bumblebee_cannon_speed 5000 +set g_vehicle_bumblebee_cannon_spread 0.0125 +set g_vehicle_bumblebee_cannon_force 400 +set g_vehicle_bumblebee_cannon_turnspeed 90 +set g_vehicle_bumblebee_cannon_pitchlimit_down 60 +set g_vehicle_bumblebee_cannon_pitchlimit_up 60 +set g_vehicle_bumblebee_cannon_turnlimit_in 5 +set g_vehicle_bumblebee_cannon_turnlimit_out 45 + +set g_vehicle_bumblebee_respawntime 10 + +set g_vehicle_bumblebee_blowup_radius 500 +set g_vehicle_bumblebee_blowup_coredamage 500 +set g_vehicle_bumblebee_blowup_edgedamage 100 +set g_vehicle_bumblebee_blowup_forceintensity 600 \ No newline at end of file diff --git a/vehicle_racer.cfg b/vehicle_racer.cfg index 1ab10cdae6..33fb4140ba 100644 --- a/vehicle_racer.cfg +++ b/vehicle_racer.cfg @@ -1,54 +1,68 @@ -set g_vehicle_racer_reload 1 +set g_vehicle_racer_respawntime 25 -set g_vehicle_racer_respawntime 10 -set g_vehicle_racer_health 250 +set g_vehicle_racer_health 190 +set g_vehicle_racer_health_regen 0 +set g_vehicle_racer_health_regen_pause 0 -set g_vehicle_racer_shield 100 -set g_vehicle_racer_shield_block 1 -set g_vehicle_racer_shield_regen 50 -set g_vehicle_racer_shield_regen_dmgpause 0.25 -set g_vehicle_racer_shield_regen_energyrate 2 +set g_vehicle_racer_shield 75 +set g_vehicle_racer_shield_regen 25 +set g_vehicle_racer_shield_regen_pause 1 -set g_vehicle_racer_energy 150 -set g_vehicle_racer_energy_regen 50 -set g_vehicle_racer_energy_usepause 1 +set g_vehicle_racer_energy 125 +set g_vehicle_racer_energy_regen 40 +set g_vehicle_racer_energy_regen_pause 1 -set g_vehicle_racer_speed_stop 2000 -set g_vehicle_racer_speed_forward 1600 -set g_vehicle_racer_speed_strafe 750 +set g_vehicle_racer_speed_stop 2000 +set g_vehicle_racer_speed_forward 800 +set g_vehicle_racer_speed_strafe 500 +set g_vehicle_racer_speed_afterburn 2000 +set g_vehicle_racer_friction 0.4 +set g_vehicle_racer_afterburn_cost 60 // energy consumed per second -set g_vehicle_racer_speed_afterburn 3500 -set g_vehicle_racer_speed_afterburn_emin 25 -set g_vehicle_racer_speed_afterburn_cost 50 +set g_vehicle_racer_hovertype 0 // 0 = hover, != 0 = maglev +set g_vehicle_racer_hoverpower 5000 // NOTE!! x 4 (4 engines) +set g_vehicle_racer_upforcedamper 10 -set g_vehicle_racer_power_min 0 -set g_vehicle_racer_power_air 0 -set g_vehicle_racer_power_solid 8000 +set g_vehicle_racer_downforce 0.01 +set g_vehicle_racer_springlength 65 +set g_vehicle_racer_collision_multiplier 0.05 +set g_vehicle_racer_anglestabilizer 1.75 -set g_vehicle_racer_drag 0.25 -set g_vehicle_racer_dragexp 0.9 - -set g_vehicle_racer_downforce 0.01 +set g_vehicle_racer_turnspeed 200 +set g_vehicle_racer_pitchspeed 100 +set g_vehicle_racer_maxpitch 25 +set g_vehicle_racer_turnroll 32 -set g_vehicle_racer_springlength 125 -set g_vehicle_racer_anglestabilizer 18 +set g_vehicle_racer_cannon_speed 9000 +set g_vehicle_racer_cannon_damage 20 +set g_vehicle_racer_cannon_radius 100 +set g_vehicle_racer_cannon_refire 0.1 +set g_vehicle_racer_cannon_cost 4 +set g_vehicle_racer_cannon_spread 0.0125 +set g_vehicle_racer_cannon_force 50 -set g_vehicle_racer_turnspeed 180 -set g_vehicle_racer_pitchspeed 360 -set g_vehicle_racer_maxpitch 25 -set g_vehicle_racer_turnroll 0.3 - -set g_vehicle_racer_laser_speed 18000 -set g_vehicle_racer_laser_damage 20 -set g_vehicle_racer_laser_radius 100 -set g_vehicle_racer_laser_refire 0.05 -set g_vehicle_racer_laser_cost 2 - -set g_vehicle_racer_rocket_speed 1500 -set g_vehicle_racer_rocket_accel 1500 -set g_vehicle_racer_rocket_turnrate 0.5 -set g_vehicle_racer_rocket_damage 200 -set g_vehicle_racer_rocket_radius 100 -set g_vehicle_racer_rocket_refire 5 +set g_vehicle_racer_rocket_speed 1000 +set g_vehicle_racer_rocket_accel 1400 +set g_vehicle_racer_rocket_turnrate 0.17 +set g_vehicle_racer_rocket_damage 160 +set g_vehicle_racer_rocket_force 350 +set g_vehicle_racer_rocket_radius 125 +set g_vehicle_racer_rocket_refire 6 set g_vehicle_racer_rocket_cost 0 +set g_vehicle_racer_rocket_locktarget 1 +set g_vehicle_racer_rocket_locking_time 0.4 +set g_vehicle_racer_rocket_locking_releasetime 1.6 +set g_vehicle_racer_rocket_locked_time 5 +set g_vehicle_racer_rocket_locked_maxangle 1.46 + +set g_vehicle_racer_blowup_radius 250 +set g_vehicle_racer_blowup_coredamage 250 +set g_vehicle_racer_blowup_edgedamage 15 +set g_vehicle_racer_blowup_forceintensity 250 + +set g_vehicle_racer_bouncefactor 0.25 // Factor of old velocity to keep after colission +set g_vehicle_racer_bouncestop 0 // if != 0, New veloctiy after bounce = 0 if new velocity < this +set g_vehicle_racer_bouncepain "35 2 250" // "minspeed_for_pain speedchange_to_pain_factor max_damage" + +set g_vehicle_racer_mass 900 diff --git a/vehicle_raptor.cfg b/vehicle_raptor.cfg index cbc3a1a69c..2a46dd2825 100644 --- a/vehicle_raptor.cfg +++ b/vehicle_raptor.cfg @@ -1,37 +1,65 @@ -set g_vehicle_raptor_reload 1 +set g_vehicle_raptor_respawntime 35 +// 0: go where player aims, +forward etc relative to aim angles +// 1: ignore aim for up/down movement. +forward always moved forward, +jump always moves up set g_vehicle_raptor_movestyle 1 -set g_vehicle_raptor_turnspeed 90 + set g_vehicle_raptor_turnroll 0.1 -set g_vehicle_raptor_pitchspeed 45 -set g_vehicle_raptor_speed_forward 1500 -set g_vehicle_raptor_speed_strafe 1500 -set g_vehicle_raptor_speed_up 1250 -set g_vehicle_raptor_speed_down 1400 - -set g_vehicle_raptor_bomblet_waves 2 -set g_vehicle_raptor_bomblet_wavefirst 0.5 -set g_vehicle_raptor_bomblet_wavenext 0.3 -set g_vehicle_raptor_bomblet_wawespread 0.3 -set g_vehicle_raptor_bomblets 3 -set g_vehicle_raptor_bomblet_damage 90 -set g_vehicle_raptor_bomblet_edgedamage 40 -set g_vehicle_raptor_bomblet_radius 250 -set g_vehicle_raptor_bomblet_force 300 -set g_vehicle_raptor_bombs_refire 1 - -set g_vehicle_raptor_beam_dps 200 -set g_vehicle_raptor_beam_fops 150 -set g_vehicle_raptor_beam_aps 100 -set g_vehicle_raptor_beam_size 8 -set g_vehicle_raptor_beam_leangth 1 -set g_vehicle_raptor_beam_refire 2 - -set g_vehicle_raptor_shield 250 -set g_vehicle_raptor_shield_regen 50 - -set g_vehicle_raptor_health 250 -set g_vehicle_raptor_health_regen 10 - -set g_vehicle_raptor_energy 300 -set g_vehicle_raptor_energy_regen 50 \ No newline at end of file + +set g_vehicle_raptor_turnspeed 80 +set g_vehicle_raptor_pitchspeed 40 +set g_vehicle_raptor_pitchlimit 35 + +set g_vehicle_raptor_speed_forward 900 +set g_vehicle_raptor_speed_strafe 700 +set g_vehicle_raptor_speed_up 500 +set g_vehicle_raptor_speed_down 800 +set g_vehicle_raptor_friction 0.7 + +set g_vehicle_raptor_bomblets 8 +set g_vehicle_raptor_bomblet_alt 750 +set g_vehicle_raptor_bomblet_time 0.5 +set g_vehicle_raptor_bomblet_spread 0.4 +set g_vehicle_raptor_bomblet_damage 50 +set g_vehicle_raptor_bomblet_edgedamage 20 +set g_vehicle_raptor_bomblet_radius 310 +set g_vehicle_raptor_bomblet_force 150 +set g_vehicle_raptor_bomblet_explode_delay 0.4 +set g_vehicle_raptor_bombs_refire 5 + +set g_vehicle_raptor_cannon_turnspeed 90 +set g_vehicle_raptor_cannon_turnlimit 20 +set g_vehicle_raptor_cannon_pitchlimit_up 12 +set g_vehicle_raptor_cannon_pitchlimit_down 32 + +set g_vehicle_raptor_cannon_locktarget 1 +set g_vehicle_raptor_cannon_locking_time 0.4 +set g_vehicle_raptor_cannon_locking_releasetime 1.6 +set g_vehicle_raptor_cannon_locked_time 5 +set g_vehicle_raptor_cannon_predicttarget 1 + +set g_vehicle_raptor_cannon_cost 1 +set g_vehicle_raptor_cannon_damage 25 +set g_vehicle_raptor_cannon_radius 60 +set g_vehicle_raptor_cannon_refire 0.05 +set g_vehicle_raptor_cannon_speed 12000 +set g_vehicle_raptor_cannon_spread 0.01 +set g_vehicle_raptor_cannon_force 50 + +set g_vehicle_raptor_energy 30 +set g_vehicle_raptor_energy_regen 15 +set g_vehicle_raptor_energy_regen_pause 0.8 + +set g_vehicle_raptor_health 150 +set g_vehicle_raptor_health_regen 0 +set g_vehicle_raptor_health_regen_pause 0 + +set g_vehicle_raptor_shield 120 +set g_vehicle_raptor_shield_regen 25 +set g_vehicle_raptor_shield_regen_pause 1.5 + +set g_vehicle_raptor_bouncefactor 0.2 +set g_vehicle_raptor_bouncestop 0 +set g_vehicle_raptor_bouncepain "1 1.5 500" + +set g_vehicle_raptor_mass 2200 diff --git a/vehicle_spiderbot.cfg b/vehicle_spiderbot.cfg index d25ce205bc..bb866037ad 100644 --- a/vehicle_spiderbot.cfg +++ b/vehicle_spiderbot.cfg @@ -1,47 +1,63 @@ -set g_vehicle_spiderbot_respawntime 30 -set g_vehicle_spiderbot_health 875 -set g_vehicle_spiderbot_health_regen 10 -set g_vehicle_spiderbot_health_regen_dmgpause 10 +set g_vehicle_spiderbot_respawntime 45 -set g_vehicle_spiderbot_shield 125 +set g_vehicle_spiderbot_health 850 +set g_vehicle_spiderbot_health_regen 15 +set g_vehicle_spiderbot_health_regen_pause 10 + +set g_vehicle_spiderbot_shield 150 set g_vehicle_spiderbot_shield_block 1 set g_vehicle_spiderbot_shield_regen 25 -set g_vehicle_spiderbot_shield_regen_dmgpause 0.25 +set g_vehicle_spiderbot_shield_regen_pause 0.2 + +set g_vehicle_spiderbot_energy 0 +set g_vehicle_spiderbot_energy_regen 0 +set g_vehicle_spiderbot_energy_regen_pause 0 -set g_vehicle_spiderbot_turnspeed 90 +set g_vehicle_spiderbot_turnspeed 180 set g_vehicle_spiderbot_head_turnspeed 120 set g_vehicle_spiderbot_head_turnlimit 120 -set g_vehicle_spiderbot_head_pitchspeed 60 -set g_vehicle_spiderbot_head_pitchlimit_up 8 -set g_vehicle_spiderbot_head_pitchlimit_down -24 +set g_vehicle_spiderbot_head_pitchspeed 70 +set g_vehicle_spiderbot_head_pitchlimit_up 24 +set g_vehicle_spiderbot_head_pitchlimit_down -16 set g_vehicle_spiderbot_speed_stop 50 set g_vehicle_spiderbot_speed_walk 400 set g_vehicle_spiderbot_speed_strafe 300 set g_vehicle_spiderbot_movement_inertia 0.25 -set g_vehicle_spiderbot_minigun_damage 25 +set g_vehicle_spiderbot_minigun_damage 16 set g_vehicle_spiderbot_minigun_spread 0.015 set g_vehicle_spiderbot_minigun_speed 50000 set g_vehicle_spiderbot_minigun_refire 0.05 +set g_vehicle_spiderbot_minigun_ammo_cost 1 +set g_vehicle_spiderbot_minigun_ammo_max 200 +set g_vehicle_spiderbot_minigun_ammo_regen 15 +set g_vehicle_spiderbot_minigun_ammo_regen_pause 1 -set g_vehicle_spiderbot_minigun_heat 10 -set g_vehicle_spiderbot_minigun_cooldown 10 +set g_vehicle_spiderbot_springlength 150 +set g_vehicle_spiderbot_springup 5 +set g_vehicle_spiderbot_springblend 0.15 set g_vehicle_spiderbot_rocket_health 100 set g_vehicle_spiderbot_rocket_damage 75 set g_vehicle_spiderbot_rocket_edgedamage 15 set g_vehicle_spiderbot_rocket_force 150 set g_vehicle_spiderbot_rocket_radius 150 -set g_vehicle_spiderbot_rocket_reload 2.5 -set g_vehicle_spiderbot_rocket_refire 0.15 -set g_vehicle_spiderbot_rocket_speed 900 -set g_vehicle_spiderbot_rocket_turnrate 0.25 -set g_vehicle_spiderbot_rocket_noise 0.25 +set g_vehicle_spiderbot_rocket_reload 4 +set g_vehicle_spiderbot_rocket_refire 0.2 +set g_vehicle_spiderbot_rocket_speed 1750 +set g_vehicle_spiderbot_rocket_turnrate 0.2 +set g_vehicle_spiderbot_rocket_noise 0.3 set g_vehicle_spiderbot_rocket_lifetime 30 set g_vehicle_spiderbot_crush_dmg 50 set g_vehicle_spiderbot_crush_force 50 +set g_vehicle_spiderbot_mass 5000 + +set g_vehicle_spiderbot_bouncefactor 0 // Factor of old velocity to keep after colission +set g_vehicle_spiderbot_bouncestop 0 // if != 0, New veloctiy after bounce = 0 if new velocity < this +set g_vehicle_spiderbot_bouncepain "0 0 0" // "minspeed_for_pain speedchange_to_pain_factor max_damage" + set cl_vehicle_spiderbot_cross_alpha 0.4 set cl_vehicle_spiderbot_cross_size 1 diff --git a/vehicles.cfg b/vehicles.cfg new file mode 100644 index 0000000000..e002321222 --- /dev/null +++ b/vehicles.cfg @@ -0,0 +1,19 @@ +set g_vehicles 1 + +exec vehicle_racer.cfg +exec vehicle_raptor.cfg +exec vehicle_spiderbot.cfg +exec vehicle_bumblebee.cfg + +//set g_vehicle_racer_respawntime 10 +//set g_vehicle_spiderbot_respawntime 10 +//set g_vehicle_raptor_respawntime 10 + +set g_vehicles_crush_dmg 70 +set g_vehicles_crush_force 50 + +set cl_vehicles_hudscale 0.5way + +set g_vehicles_delayspawn 1 +set g_vehicles_delayspawn_jitter 10 +set g_vehicles_allow_flagcarry 1 diff --git a/weapons.cfg b/weapons.cfg new file mode 100644 index 0000000000..80305a5fe2 --- /dev/null +++ b/weapons.cfg @@ -0,0 +1,18 @@ +alias weapon_laser "impulse 230" +alias weapon_shotgun "impulse 231" +alias weapon_uzi "impulse 232" +alias weapon_grenadelauncher "impulse 233" +alias weapon_minelayer "impulse 234" +alias weapon_electro "impulse 235" +alias weapon_crylink "impulse 236" +alias weapon_nex "impulse 237" +alias weapon_hagar "impulse 238" +alias weapon_rocketlauncher "impulse 239" +alias weapon_porto "impulse 240" +alias weapon_minstanex "impulse 241" +alias weapon_hook "impulse 242" +alias weapon_hlac "impulse 243" +alias weapon_tuba "impulse 244" +alias weapon_rifle "impulse 245" +alias weapon_fireball "impulse 246" +alias weapon_seeker "impulse 247" diff --git a/weapons.cfg.sh b/weapons.cfg.sh new file mode 100755 index 0000000000..f02d43cf10 --- /dev/null +++ b/weapons.cfg.sh @@ -0,0 +1,2 @@ +#!/bin/sh +<qcsrc/server/w_all.qc perl -ne 'BEGIN{$i=230}/w_(.*?)\./ or+next;printf qq{alias weapon_%s "impulse %d"\n},$1,$i++;' diff --git a/xonotic-credits.txt b/xonotic-credits.txt index ec46525c90..2e60c679fc 100644 --- a/xonotic-credits.txt +++ b/xonotic-credits.txt @@ -1,20 +1,20 @@ **Core Team Rudolf "divVerent" Polzer --z- +Tyler "-z-" Mulligan Merlijn Hofstra morphed -mand1nga -tZork - +Samual "Ares" Lenks +Saulo "mand1nga" Gil +Jakob "tZork" Markström Gröhn **Coordinators *Art -Diabolik a.k.a Dib +Sahil "DiaboliK" Singhal *2D Art / Web --z- (web / game) +Tyler "-z-" Mulligan (web / game) FruitieX (game / web) *3D Art @@ -22,16 +22,24 @@ morphed *Concept Art LJFHutch -theShadow +Pearce "theShadow" Michal + +*Animation +Sahil "DiaboliK" Singhal +nifrek *Level Design FruitieX MirceaKitsune +Jakob "tZork" Markström Gröhn +Ruszkai "C.Brutail" Ákos *Music / Sound FX mand1nga Merlijn Hofstra remaxim +Stephan +Independent.nu *Engine Code Additions & QA Rudolf "divVerent" Polzer @@ -39,11 +47,12 @@ Rudolf "divVerent" Polzer *Game Code Rudolf "divVerent" Polzer FruitieX -tZork +Jakob "tZork" Markström Gröhn *Marketing / PR --z- +Tyler "-z-" Mulligan mand1nga +Ruszkai "C.Brutail" Ákos *Legal Rudolf "divVerent" Polzer @@ -53,18 +62,81 @@ Merlijn Hofstra DarkPlaces by Forest "LordHavoc" Hale -**Active Contributors +**Translators + +*Dutch +Alexander "freefang" van Dam +PinkRobot + +*German +Rudolf "divVerent" Polzer + +*Finnish +Henry "Exitium" Sanmark + +*French +Calinou +Maxime "Taximus" Paradis + +*Greek +Γιάννης Α. + +*Hungarian +xaN1C4n3 +Ruszkai "C.Brutail" Ákos + +*Italian Antonio "terencehill" Piu +Felice "MaidenBeast" Sallustio + +*Portuguese +Ricardo "Hellgardia" Silva + +*Romanian +MirceaKitsune + +*Russian +Lord Canistra +Nikoli + +*Spanish +Rodrigo Mouton Laudin + +*Swedish +marcus256 + +*Ukrainian +Vasyl "Harmata" Melnyk + +**Other Active Contributors +Akari +Ant "Antibody" Zucaro +Antonio "terencehill" Piu +atheros Ben "MooKow" Banker +blkrbt Calinou chooksta +cortez Cuinn "Cuinnton" Herrick -Kristian "morfar" Johansson +Florian Paul "lda17h" Schmidt kojn +Kristian "morfar" Johansson +kuniuthefrogg +magorian Maik "SavageX" Merten +Marvin "Mirio" Beck +Mick Rippon MrBougo -Samual Lenks +parasti +Paul Scott +PlasmaSheep +Przemysław "atheros" Grzywacz +{SC0RP} - Ian "ID" Dorrell +Severin "sev" Meyer +SoulKeeper_p Stephan "esteel" Stahl +The player with the unnecessarily long name Wolfgang "Blub\0" Bumiller **Past Contributors @@ -73,7 +145,6 @@ Amos "torus" Dudley Andreas "Black" Kirsch Attila "WW3" Houtkooper BigMac -blkrbt Braden "meoblast001" Walters Brain Younds Chris "amethyst7" Matz @@ -124,7 +195,6 @@ Rick "Rat" Kelley Robert "ai" Kuroto Ronan Sajt -Severin "sev" Meyer Shaggy Shank Simon O'Callaghan @@ -134,7 +204,6 @@ Spirit Steve Vermeulen Supajoe Tei -terencehill Tomaz Ulrich Galbraith Vortex diff --git a/xonotic-credits.txt.fr b/xonotic-credits.txt.fr new file mode 100644 index 0000000000..ec2d299a80 --- /dev/null +++ b/xonotic-credits.txt.fr @@ -0,0 +1,172 @@ +**Dévlopeurs principaux + +Rudolf "divVerent" Polzer +Tyler "-z-" Mulligan +Merlijn Hofstra +morphed +mand1nga +tZork + + +**Dévlopeurs secondaires + +*Art +Diabolik a.k.a Dib + +*Textures / Web +Tyler "-z-" Mulligan (web / game) +FruitieX (game / web) + +*Modèles 3D +morphed + +*Concepts +LJFHutch +Pearce "theShadow" Michal + +*Création des cartes +FruitieX +MirceaKitsune +Ruszkai "C.Brutail" Ákos + +*Musique / Sons +mand1nga +Merlijn Hofstra +remaxim + +*Améliorations du moteur et QA +Rudolf "divVerent" Polzer + +*Code source du jeu +Rudolf "divVerent" Polzer +FruitieX +tZork + +*Marketing / Management du Projet +Tyler "-z-" Mulligan +mand1nga +Ruszkai "C.Brutail" Ákos + +*Légalité +Rudolf "divVerent" Polzer +Merlijn Hofstra + +**Moteur du jeu +DarkPlaces +by Forest "LordHavoc" Hale + +**Traducteurs + +*Allemand +Rudolf "divVerent" Polzer + +*Finnish (TODO TRANSLATE THIS) +Henry "Exitium" Sanmark + +*Français +Calinou + +*Italien +Antonio "terencehill" Piu +Felice "MaidenBeast" Sallustio + +*Portugais +Ricardo "Hellgardia" Silva + +*Roumain +MirceaKitsune + +*Russe +Lord Canistra +Nikoli + +**Contribueurs actifs +Antonio "terencehill" Piu +Ben "MooKow" Banker +Calinou +chooksta +Cuinn "Cuinnton" Herrick +Kristian "morfar" Johansson +kojn +Maik "SavageX" Merten +MrBougo +Samual Lenks +Severin "sev" Meyer +Stephan "esteel" Stahl +Wolfgang "Blub\0" Bumiller + +**Anciens contribueurs +Alexander "motorsep" Zubov +Amos "torus" Dudley +Andreas "Black" Kirsch +Attila "WW3" Houtkooper +BigMac +blkrbt +Braden "meoblast001" Walters +Brain Younds +Chris "amethyst7" Matz +Christian Ice +Clinton "Kaziganthe" Freeman +Dan "Digger" Korostelev +Dan "Wazat" Hale +Donkey +dstrek +Dustin Geeraert +Edgenetwork +Edward "Ed" Holness +Eric "Munyul Verminard" Sambach +Fabien "H. Reaper" Tschirhart +FrikaC +Garth "Zombie" Hendy +Gerd "Elysis" Raudenbusch +Gottfried "Toddd" Hofmann +Henning "Tymo" Janssen +"Innovati" +Jitspoe +Jody Gallagher +Juergen "LowDragon" Timm +KadaverJack +Kevin "Tyrann" Shanahan +Kurt Dereli +lcatlnx +Lee David Ash +Lee Vermeulen +leileilol +Marius "GreEn`mArine" Shekow +Marko "Urre" Permanto +Mathieu "Elric" Olivier +Mattrew "Tronyn" Rye +MauveBib +Mephisto +michaelb +Michael "Tenshihan" Quinn +Munyul +Netzwerg +NoelCower +Parapraxis +Paul "Strahlemann" Evers +Petithomme +Q1 Retexturing Project +Qantourisc +Rick "Rat" Kelley +Robert "ai" Kuroto +Ronan +Sajt +Severin "sev" Meyer +Shaggy +Shank +Simon O'Callaghan +SomeGuy +Spike +Spirit +Steve Vermeulen +Supajoe +Tei +terencehill +Tomaz +Ulrich Galbraith +Vortex +William Libert +William "Willis" Weilep +Yves "EviLair" Allaire +Zenex diff --git a/xonotic-credits.txt.hu b/xonotic-credits.txt.hu new file mode 100644 index 0000000000..faf205bce3 --- /dev/null +++ b/xonotic-credits.txt.hu @@ -0,0 +1,207 @@ +**A Csapat magja - Team Xonotic + +Rudolf "divVerent" Polzer +Tyler "-z-" Mulligan +Merlijn Hofstra +morphed +Samual "Ares" Lenks +Saulo "mand1nga" Gil +Jakob "tZork" Markström Gröhn + +**Feladat felelősök + +*Művészet +Sahil "DiaboliK" Singhal + +*2D Művészet / Web +Tyler "-z-" Mulligan (web / game) +FruitieX (game / web) + +*3D Művészet +morphed + +*Művészeti elképzelés +LJFHutch +Pearce "theShadow" Michal + +*Animáció +Sahil "DiaboliK" Singhal +nifrek + +*Pálya tervezés +FruitieX +MirceaKitsune +Jakob "tZork" Markström Gröhn +Ruszkai "C.Brutail" Ákos + +*Zene / Hang effekt +mand1nga +Merlijn Hofstra +remaxim +Stephan + +*Játék motor kiegészitések +Rudolf "divVerent" Polzer + +*Játék kód +Rudolf "divVerent" Polzer +FruitieX +Jakob "tZork" Markström Gröhn + +*Marketing / PR +Tyler "-z-" Mulligan +mand1nga +Ruszkai "C.Brutail" Ákos + +*Jogi engedélyek +Rudolf "divVerent" Polzer +Merlijn Hofstra + +**Játék motor +DarkPlaces +by Forest "LordHavoc" Hale + + +**Fordítók + +*Finn +Henry "Exitium" Sanmark + +*Francia +Calinou +Maxime "Taximus" Paradis + +*Holland +Alexander "freefang" van Dam +PinkRobot + +*Magyar +xaN1C4n3 +Ruszkai "C.Brutail" Ákos + +*Német +Rudolf "divVerent" Polzer + +*Olasz +Antonio "terencehill" Piu +Felice "MaidenBeast" Sallustio + +*Orosz +Lord Canistra +Nikoli + +*Portugál +Ricardo "Hellgardia" Silva + +*Román +MirceaKitsune + +*Spanyol +Rodrigo Mouton Laudin + +*Svéd +marcus256 + +**További aktív résztvevők +Akari +Ant "Antibody" Zucaro +Antonio "terencehill" Piu +atheros +Ben "MooKow" Banker +blkrbt +Calinou +chooksta +cortez +Cuinn "Cuinnton" Herrick +Florian Paul "lda17h" Schmidt +kojn +Kristian "morfar" Johansson +kuniuthefrogg +magorian +Maik "SavageX" Merten +Marvin "Mirio" Beck +Mick Rippon +MrBougo +parasti +Paul Scott +PlasmaSheep +Przemysław "atheros" Grzywacz +{SC0RP} - Ian "ID" Dorrell +Severin "sev" Meyer +SoulKeeper_p +Stephan "esteel" Stahl +The player with the unnecessarily long name +Wolfgang "Blub\0" Bumiller + +**Múltbeli résztvevők +Alexander "motorsep" Zubov +Amos "torus" Dudley +Andreas "Black" Kirsch +Attila "WW3" Houtkooper +BigMac +Braden "meoblast001" Walters +Brain Younds +Chris "amethyst7" Matz +Christian Ice +Clinton "Kaziganthe" Freeman +Dan "Digger" Korostelev +Dan "Wazat" Hale +Donkey +dstrek +Dustin Geeraert +Edgenetwork +Edward "Ed" Holness +Eric "Munyul Verminard" Sambach +Fabien "H. Reaper" Tschirhart +FrikaC +Garth "Zombie" Hendy +Gerd "Elysis" Raudenbusch +Gottfried "Toddd" Hofmann +Henning "Tymo" Janssen +"Innovati" +Jitspoe +Jody Gallagher +Juergen "LowDragon" Timm +KadaverJack +Kevin "Tyrann" Shanahan +Kurt Dereli +lcatlnx +Lee David Ash +Lee Vermeulen +leileilol +Marius "GreEn`mArine" Shekow +Marko "Urre" Permanto +Mathieu "Elric" Olivier +Mattrew "Tronyn" Rye +MauveBib +Mephisto +michaelb +Michael "Tenshihan" Quinn +Munyul +Netzwerg +NoelCower +Parapraxis +Paul "Strahlemann" Evers +Petithomme +Q1 Retexturing Project +Qantourisc +Rick "Rat" Kelley +Robert "ai" Kuroto +Ronan +Sajt +Shaggy +Shank +Simon O'Callaghan +SomeGuy +Spike +Spirit +Steve Vermeulen +Supajoe +Tei +Tomaz +Ulrich Galbraith +Vortex +William Libert +William "Willis" Weilep +Yves "EviLair" Allaire +Zenex diff --git a/xonotic-credits.txt.it b/xonotic-credits.txt.it new file mode 100644 index 0000000000..f0ace06812 --- /dev/null +++ b/xonotic-credits.txt.it @@ -0,0 +1,178 @@ +**Sviluppatori principali + +Rudolf "divVerent" Polzer +Tyler "-z-" Mulligan +Merlijn Hofstra +morphed +mand1nga +Jakob "tZork" Markström Gröhn + +**Coordinatori + +*Parte artistica +Sahil "DiaboliK" Singhal + +*Texture / Web +Tyler "-z-" Mulligan (web / game) +FruitieX (game / web) + +*Modellazione 3D +morphed + +*Concept Art +LJFHutch +Pearce "theShadow" Michal + +*Animazioni +Sahil "DiaboliK" Singhal +nifrek + +*Design dei livelli +FruitieX +MirceaKitsune +Jakob "tZork" Markström Gröhn + +*Musiche / Effetti sonori +mand1nga +Merlijn Hofstra +remaxim +Stephan + +*Aggiunte al codice del motore e QA +Rudolf "divVerent" Polzer + +*Codice del gioco +Rudolf "divVerent" Polzer +FruitieX +Jakob "tZork" Markström Gröhn + +*Marketing / Pubbliche Relazioni +Tyler "-z-" Mulligan +mand1nga + +*Aspetti legali +Rudolf "divVerent" Polzer +Merlijn Hofstra + +**Motore del gioco +DarkPlaces +by Forest "LordHavoc" Hale + +**Traduttori + +*Tedesco +Rudolf "divVerent" Polzer + +*Finlandese +Henry "Exitium" Sanmark + +*Francese +Calinou + +*Italiano +Antonio "terencehill" Piu +Felice "MaidenBeast" Sallustio + +*Portoghese +Ricardo "Hellgardia" Silva + +*Rumeno +MirceaKitsune + +*Russo +Lord Canistra +Nikoli + +**Contributori attivi +Ant "Antibody" Zucaro +Antonio "terencehill" Piu +Ben "MooKow" Banker +blkrbt +Calinou +chooksta +Cuinn "Cuinnton" Herrick +Florian Paul "lda17h" Schmidt +Kristian "morfar" Johansson +kojn +Maik "SavageX" Merten +MrBougo +Przemysław "atheros" Grzywacz +Ruszkai "C.Brutail" Ákos +Samual Lenks +Severin "sev" Meyer +Stephan "esteel" Stahl +Wolfgang "Blub\0" Bumiller +SoulKeeper_p + +**Contributori passati +Alexander "motorsep" Zubov +Amos "torus" Dudley +Andreas "Black" Kirsch +Attila "WW3" Houtkooper +BigMac +Braden "meoblast001" Walters +Brain Younds +Chris "amethyst7" Matz +Christian Ice +Clinton "Kaziganthe" Freeman +Dan "Digger" Korostelev +Dan "Wazat" Hale +Donkey +dstrek +Dustin Geeraert +Edgenetwork +Edward "Ed" Holness +Eric "Munyul Verminard" Sambach +Fabien "H. Reaper" Tschirhart +FrikaC +Garth "Zombie" Hendy +Gerd "Elysis" Raudenbusch +Gottfried "Toddd" Hofmann +Henning "Tymo" Janssen +"Innovati" +Jitspoe +Jody Gallagher +Juergen "LowDragon" Timm +KadaverJack +Kevin "Tyrann" Shanahan +Kurt Dereli +lcatlnx +Lee David Ash +Lee Vermeulen +leileilol +Marius "GreEn`mArine" Shekow +Marko "Urre" Permanto +Mathieu "Elric" Olivier +Mattrew "Tronyn" Rye +MauveBib +Mephisto +michaelb +Michael "Tenshihan" Quinn +Munyul +Netzwerg +NoelCower +Parapraxis +Paul "Strahlemann" Evers +Petithomme +Q1 Retexturing Project +Qantourisc +Rick "Rat" Kelley +Robert "ai" Kuroto +Ronan +Sajt +Shaggy +Shank +Simon O'Callaghan +SomeGuy +Spike +Spirit +Steve Vermeulen +Supajoe +Tei +Tomaz +Ulrich Galbraith +Vortex +William Libert +William "Willis" Weilep +Yves "EviLair" Allaire +Zenex diff --git a/xonotic-credits.txt.uk b/xonotic-credits.txt.uk new file mode 100644 index 0000000000..1b3351d4f8 --- /dev/null +++ b/xonotic-credits.txt.uk @@ -0,0 +1,208 @@ +**Ядро команди + +Rudolf "divVerent" Polzer +Tyler "-z-" Mulligan +Merlijn Hofstra +morphed +Samual "Ares" Lenks +Saulo "mand1nga" Gil +Jakob "tZork" Markström Gröhn + +**Координатори + +*Художній координатор +Sahil "DiaboliK" Singhal + +*2D контент / Сайт +Tyler "-z-" Mulligan (сайт / гра) +FruitieX (гра / сайт) + +*3D контент +morphed + +*Концепт-арт +LJFHutch +Pearce "theShadow" Michal + +*Анімація +Sahil "DiaboliK" Singhal +nifrek + +*Дизайн рівнів +FruitieX +MirceaKitsune +Jakob "tZork" Markström Gröhn +Ruszkai "C.Brutail" Ákos + +*Музика / Звукові ефекти +mand1nga +Merlijn Hofstra +remaxim +Stephan + +*Додатки до коду рушія та контроль якості +Rudolf "divVerent" Polzer + +*Код гри +Rudolf "divVerent" Polzer +FruitieX +Jakob "tZork" Markström Gröhn + +*Маркетинг / PR +Tyler "-z-" Mulligan +mand1nga +Ruszkai "C.Brutail" Ákos + +*Правові питання +Rudolf "divVerent" Polzer +Merlijn Hofstra + +**Ігровий рушій +DarkPlaces +by Forest "LordHavoc" Hale + +**Перекладачі + +*Голландська мова +Alexander "freefang" van Dam +PinkRobot + +*Німецька мова +Rudolf "divVerent" Polzer + +*Фінська мова +Henry "Exitium" Sanmark + +*Французька мова +Calinou +Maxime "Taximus" Paradis + +*Угорська мова +xaN1C4n3 + +*Італійська мова +Antonio "terencehill" Piu +Felice "MaidenBeast" Sallustio + +*Португальська мова +Ricardo "Hellgardia" Silva + +*Румунська мова +MirceaKitsune + +*Російська мова +Lord Canistra +Nikoli + +*Іспанська мова +Rodrigo Mouton Laudin + +*Шведська мова +marcus256 + +*Українська мова +Василь "Harmata" Мельник + +**Інші активні помічники +Akari +Ant "Antibody" Zucaro +Antonio "terencehill" Piu +atheros +Ben "MooKow" Banker +blkrbt +Calinou +chooksta +cortez +Cuinn "Cuinnton" Herrick +Florian Paul "lda17h" Schmidt +kojn +Kristian "morfar" Johansson +kuniuthefrogg +magorian +Maik "SavageX" Merten +Marvin "Mirio" Beck +Mick Rippon +MrBougo +parasti +Paul Scott +PlasmaSheep +Przemysław "atheros" Grzywacz +{SC0RP} - Ian "ID" Dorrell +Severin "sev" Meyer +SoulKeeper_p +Stephan "esteel" Stahl +The player with the unnecessarily long name +Wolfgang "Blub\0" Bumiller + +**Колишні помічники +Alexander "motorsep" Zubov +Amos "torus" Dudley +Andreas "Black" Kirsch +Attila "WW3" Houtkooper +BigMac +Braden "meoblast001" Walters +Brain Younds +Chris "amethyst7" Matz +Christian Ice +Clinton "Kaziganthe" Freeman +Dan "Digger" Korostelev +Dan "Wazat" Hale +Donkey +dstrek +Dustin Geeraert +Edgenetwork +Edward "Ed" Holness +Eric "Munyul Verminard" Sambach +Fabien "H. Reaper" Tschirhart +FrikaC +Garth "Zombie" Hendy +Gerd "Elysis" Raudenbusch +Gottfried "Toddd" Hofmann +Henning "Tymo" Janssen +"Innovati" +Jitspoe +Jody Gallagher +Juergen "LowDragon" Timm +KadaverJack +Kevin "Tyrann" Shanahan +Kurt Dereli +lcatlnx +Lee David Ash +Lee Vermeulen +leileilol +Marius "GreEn`mArine" Shekow +Marko "Urre" Permanto +Mathieu "Elric" Olivier +Mattrew "Tronyn" Rye +MauveBib +Mephisto +michaelb +Michael "Tenshihan" Quinn +Munyul +Netzwerg +NoelCower +Parapraxis +Paul "Strahlemann" Evers +Petithomme +Q1 Retexturing Project +Qantourisc +Rick "Rat" Kelley +Robert "ai" Kuroto +Ronan +Sajt +Shaggy +Shank +Simon O'Callaghan +SomeGuy +Spike +Spirit +Steve Vermeulen +Supajoe +Tei +Tomaz +Ulrich Galbraith +Vortex +William Libert +William "Willis" Weilep +Yves "EviLair" Allaire +Zenex